This commit was manufactured by cvs2svn to create branch 'vserver'.
authorPlanet-Lab Support <support@planet-lab.org>
Mon, 13 Nov 2006 15:58:55 +0000 (15:58 +0000)
committerPlanet-Lab Support <support@planet-lab.org>
Mon, 13 Nov 2006 15:58:55 +0000 (15:58 +0000)
914 files changed:
Documentation/ABI/README [new file with mode: 0644]
Documentation/ABI/obsolete/devfs [new file with mode: 0644]
Documentation/ABI/stable/syscalls [new file with mode: 0644]
Documentation/ABI/stable/sysfs-module [new file with mode: 0644]
Documentation/ABI/testing/sysfs-class [new file with mode: 0644]
Documentation/ABI/testing/sysfs-devices [new file with mode: 0644]
Documentation/DocBook/genericirq.tmpl [new file with mode: 0644]
Documentation/IRQ.txt [new file with mode: 0644]
Documentation/SubmitChecklist [new file with mode: 0644]
Documentation/accounting/delay-accounting.txt [new file with mode: 0644]
Documentation/accounting/getdelays.c [new file with mode: 0644]
Documentation/accounting/taskstats.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/S3C2412.txt [new file with mode: 0644]
Documentation/arm/Samsung-S3C24XX/S3C2413.txt [new file with mode: 0644]
Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen [new file with mode: 0644]
Documentation/arm/Sharp-LH/LCDPanels [new file with mode: 0644]
Documentation/connector/ucon.c [new file with mode: 0644]
Documentation/console/console.txt [new file with mode: 0644]
Documentation/fb/imacfb.txt [new file with mode: 0644]
Documentation/filesystems/caching/backend-api.txt [new file with mode: 0644]
Documentation/filesystems/caching/cachefiles.txt [new file with mode: 0644]
Documentation/filesystems/caching/fscache.txt [new file with mode: 0644]
Documentation/filesystems/caching/netfs-api.txt [new file with mode: 0644]
Documentation/filesystems/relay.txt [new file with mode: 0644]
Documentation/hwmon/abituguru [new file with mode: 0644]
Documentation/hwmon/abituguru-datasheet [new file with mode: 0644]
Documentation/hwmon/lm70 [new file with mode: 0644]
Documentation/hwmon/smsc47m192 [new file with mode: 0644]
Documentation/hwmon/w83791d [new file with mode: 0644]
Documentation/i2c/busses/i2c-ocores [new file with mode: 0644]
Documentation/ia64/aliasing.txt [new file with mode: 0644]
Documentation/irqflags-tracing.txt [new file with mode: 0644]
Documentation/lockdep-design.txt [new file with mode: 0644]
Documentation/networking/ipvs-sysctl.txt [new file with mode: 0644]
Documentation/pcmcia/crc32hash.c [new file with mode: 0644]
Documentation/pi-futex.txt [new file with mode: 0644]
Documentation/rt-mutex-design.txt [new file with mode: 0644]
Documentation/rt-mutex.txt [new file with mode: 0644]
Documentation/scsi/hptiop.txt [new file with mode: 0644]
Documentation/utrace.txt [new file with mode: 0644]
Documentation/video4linux/README.pvrusb2 [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-calling.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-decoder-api.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-dma.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-encoder-api.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-memory.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-osd-api.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-upload.txt [new file with mode: 0644]
Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt [new file with mode: 0644]
Documentation/video4linux/v4lgrab.c [new file with mode: 0644]
Documentation/w1/masters/ds2490 [new file with mode: 0644]
Documentation/w1/w1.netlink [new file with mode: 0644]
Documentation/watchdog/src/watchdog-simple.c [new file with mode: 0644]
Documentation/watchdog/src/watchdog-test.c [new file with mode: 0644]
arch/arm/configs/ateb9200_defconfig [new file with mode: 0644]
arch/arm/configs/carmeva_defconfig [new file with mode: 0644]
arch/arm/configs/kafa_defconfig [new file with mode: 0644]
arch/arm/configs/kb9202_defconfig [new file with mode: 0644]
arch/arm/configs/lpd270_defconfig [new file with mode: 0644]
arch/arm/configs/netx_defconfig [new file with mode: 0644]
arch/arm/configs/onearm_defconfig [new file with mode: 0644]
arch/arm/configs/pnx4008_defconfig [new file with mode: 0644]
arch/arm/configs/trizeps4_defconfig [new file with mode: 0644]
arch/arm/kernel/crunch-bits.S [new file with mode: 0644]
arch/arm/kernel/crunch.c [new file with mode: 0644]
arch/arm/kernel/iwmmxt-notifier.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/at91rm9200.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/at91rm9200_time.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-1arm.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-carmeva.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-eb9200.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-kafa.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/board-kb9202.c [new file with mode: 0644]
arch/arm/mach-at91rm9200/pm.c [new file with mode: 0644]
arch/arm/mach-ep93xx/clock.c [new file with mode: 0644]
arch/arm/mach-ep93xx/edb9302.c [new file with mode: 0644]
arch/arm/mach-ep93xx/edb9315.c [new file with mode: 0644]
arch/arm/mach-ep93xx/edb9315a.c [new file with mode: 0644]
arch/arm/mach-lh7a40x/clcd.c [new file with mode: 0644]
arch/arm/mach-lh7a40x/clocks.c [new file with mode: 0644]
arch/arm/mach-lh7a40x/lcd-panel.h [new file with mode: 0644]
arch/arm/mach-lh7a40x/ssp-cpld.c [new file with mode: 0644]
arch/arm/mach-netx/Kconfig [new file with mode: 0644]
arch/arm/mach-netx/Makefile [new file with mode: 0644]
arch/arm/mach-netx/Makefile.boot [new file with mode: 0644]
arch/arm/mach-netx/fb.c [new file with mode: 0644]
arch/arm/mach-netx/fb.h [new file with mode: 0644]
arch/arm/mach-netx/generic.c [new file with mode: 0644]
arch/arm/mach-netx/generic.h [new file with mode: 0644]
arch/arm/mach-netx/nxdb500.c [new file with mode: 0644]
arch/arm/mach-netx/nxdkn.c [new file with mode: 0644]
arch/arm/mach-netx/nxeb500hmi.c [new file with mode: 0644]
arch/arm/mach-netx/pfifo.c [new file with mode: 0644]
arch/arm/mach-netx/time.c [new file with mode: 0644]
arch/arm/mach-netx/xc.c [new file with mode: 0644]
arch/arm/mach-omap1/board-fsample.c [new file with mode: 0644]
arch/arm/mach-omap2/gpmc.c [new file with mode: 0644]
arch/arm/mach-omap2/pm-domain.c [new file with mode: 0644]
arch/arm/mach-pnx4008/Makefile [new file with mode: 0644]
arch/arm/mach-pnx4008/Makefile.boot [new file with mode: 0644]
arch/arm/mach-pnx4008/clock.c [new file with mode: 0644]
arch/arm/mach-pnx4008/clock.h [new file with mode: 0644]
arch/arm/mach-pnx4008/core.c [new file with mode: 0644]
arch/arm/mach-pnx4008/dma.c [new file with mode: 0644]
arch/arm/mach-pnx4008/gpio.c [new file with mode: 0644]
arch/arm/mach-pnx4008/irq.c [new file with mode: 0644]
arch/arm/mach-pnx4008/pm.c [new file with mode: 0644]
arch/arm/mach-pnx4008/serial.c [new file with mode: 0644]
arch/arm/mach-pnx4008/sleep.S [new file with mode: 0644]
arch/arm/mach-pnx4008/time.c [new file with mode: 0644]
arch/arm/mach-pxa/leds-trizeps4.c [new file with mode: 0644]
arch/arm/mach-pxa/trizeps4.c [new file with mode: 0644]
arch/arm/mach-s3c2410/mach-smdk2413.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2410-clock.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2412-clock.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2412-irq.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2412.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2412.h [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2442-clock.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2442.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2442.h [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c244x-irq.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c244x.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c244x.h [new file with mode: 0644]
arch/arm/mm/iomap.c [new file with mode: 0644]
arch/arm/mm/nommu.c [new file with mode: 0644]
arch/i386/kernel/hpet.c [new file with mode: 0644]
arch/i386/kernel/i8253.c [new file with mode: 0644]
arch/i386/kernel/tsc.c [new file with mode: 0644]
arch/i386/mach-xen/irqflags.c [new file with mode: 0644]
arch/ia64/ia32/audit.c [new file with mode: 0644]
arch/ia64/kernel/audit.c [new file with mode: 0644]
arch/ia64/xen/Makefile [new file with mode: 0644]
arch/ia64/xen/drivers/README [new file with mode: 0644]
arch/ia64/xen/hypercall.S [new file with mode: 0644]
arch/ia64/xen/hypervisor.c [new file with mode: 0644]
arch/ia64/xen/util.c [new file with mode: 0644]
arch/ia64/xen/xenentry.S [new file with mode: 0644]
arch/ia64/xen/xenhpski.c [new file with mode: 0644]
arch/ia64/xen/xenivt.S [new file with mode: 0644]
arch/ia64/xen/xenminstate.h [new file with mode: 0644]
arch/ia64/xen/xenpal.S [new file with mode: 0644]
arch/ia64/xen/xensetup.S [new file with mode: 0644]
arch/m68k/kernel/dma.c [new file with mode: 0644]
arch/m68k/lib/uaccess.c [new file with mode: 0644]
arch/m68knommu/platform/532x/Makefile [new file with mode: 0644]
arch/m68knommu/platform/532x/config.c [new file with mode: 0644]
arch/m68knommu/platform/68328/romvec.S [new file with mode: 0644]
arch/mips/basler/excite/Makefile [new file with mode: 0644]
arch/mips/basler/excite/excite_dbg_io.c [new file with mode: 0644]
arch/mips/basler/excite/excite_device.c [new file with mode: 0644]
arch/mips/basler/excite/excite_flashtest.c [new file with mode: 0644]
arch/mips/basler/excite/excite_fpga.h [new file with mode: 0644]
arch/mips/basler/excite/excite_iodev.c [new file with mode: 0644]
arch/mips/basler/excite/excite_iodev.h [new file with mode: 0644]
arch/mips/basler/excite/excite_irq.c [new file with mode: 0644]
arch/mips/basler/excite/excite_procfs.c [new file with mode: 0644]
arch/mips/basler/excite/excite_prom.c [new file with mode: 0644]
arch/mips/basler/excite/excite_setup.c [new file with mode: 0644]
arch/mips/configs/emma2rh_defconfig [new file with mode: 0644]
arch/mips/configs/excite_defconfig [new file with mode: 0644]
arch/mips/configs/wrppmc_defconfig [new file with mode: 0644]
arch/mips/emma2rh/common/Makefile [new file with mode: 0644]
arch/mips/emma2rh/common/irq.c [new file with mode: 0644]
arch/mips/emma2rh/common/irq_emma2rh.c [new file with mode: 0644]
arch/mips/emma2rh/common/prom.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/Makefile [new file with mode: 0644]
arch/mips/emma2rh/markeins/irq.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/irq_markeins.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/led.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/platform.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/setup.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/Makefile [new file with mode: 0644]
arch/mips/gt64120/wrppmc/irq.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/pci.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/reset.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/setup.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/time.c [new file with mode: 0644]
arch/mips/kernel/apm.c [new file with mode: 0644]
arch/mips/lib/ashldi3.c [new file with mode: 0644]
arch/mips/lib/ashrdi3.c [new file with mode: 0644]
arch/mips/lib/libgcc.h [new file with mode: 0644]
arch/mips/lib/lshrdi3.c [new file with mode: 0644]
arch/mips/mm/sc-mips.c [new file with mode: 0644]
arch/mips/pci/fixup-emma2rh.c [new file with mode: 0644]
arch/mips/pci/fixup-excite.c [new file with mode: 0644]
arch/mips/pci/fixup-wrppmc.c [new file with mode: 0644]
arch/mips/pci/ops-bridge.c [new file with mode: 0644]
arch/mips/pci/ops-emma2rh.c [new file with mode: 0644]
arch/mips/pci/pci-emma2rh.c [new file with mode: 0644]
arch/mips/pci/pci-excite.c [new file with mode: 0644]
arch/mips/qemu/q-reset.c [new file with mode: 0644]
arch/mips/sni/sniprom.c [new file with mode: 0644]
arch/powerpc/boot/dts/mpc7448hpc2.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8349emds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8540ads.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8541cds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8548cds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8555cds.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8641_hpcn.dts [new file with mode: 0644]
arch/powerpc/configs/chrp32_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc7448_hpc2_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc834x_itx_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc834x_mds_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc85xx_cds_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc8641_hpcn_defconfig [new file with mode: 0644]
arch/powerpc/kernel/audit.c [new file with mode: 0644]
arch/powerpc/kernel/compat_audit.c [new file with mode: 0644]
arch/powerpc/kernel/misc.S [new file with mode: 0644]
arch/powerpc/platforms/83xx/mpc834x_itx.c [new file with mode: 0644]
arch/powerpc/platforms/83xx/mpc834x_itx.h [new file with mode: 0644]
arch/powerpc/platforms/85xx/mpc85xx_cds.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/mpc85xx_cds.h [new file with mode: 0644]
arch/powerpc/platforms/86xx/Kconfig [new file with mode: 0644]
arch/powerpc/platforms/86xx/Makefile [new file with mode: 0644]
arch/powerpc/platforms/86xx/mpc8641_hpcn.h [new file with mode: 0644]
arch/powerpc/platforms/86xx/mpc86xx.h [new file with mode: 0644]
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/mpc86xx_pcie.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/mpc86xx_smp.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/pci.c [new file with mode: 0644]
arch/powerpc/platforms/cell/cbe_regs.c [new file with mode: 0644]
arch/powerpc/platforms/cell/cbe_regs.h [new file with mode: 0644]
arch/powerpc/platforms/cell/ras.c [new file with mode: 0644]
arch/powerpc/platforms/cell/ras.h [new file with mode: 0644]
arch/powerpc/platforms/cell/spu_priv1_mmio.c [new file with mode: 0644]
arch/powerpc/platforms/embedded6xx/Makefile [new file with mode: 0644]
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c [new file with mode: 0644]
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h [new file with mode: 0644]
arch/powerpc/platforms/iseries/dt.c [new file with mode: 0644]
arch/powerpc/sysdev/todc.c [new file with mode: 0644]
arch/powerpc/sysdev/tsi108_dev.c [new file with mode: 0644]
arch/powerpc/sysdev/tsi108_pci.c [new file with mode: 0644]
arch/s390/hypfs/Makefile [new file with mode: 0644]
arch/s390/hypfs/hypfs.h [new file with mode: 0644]
arch/s390/hypfs/hypfs_diag.c [new file with mode: 0644]
arch/s390/hypfs/hypfs_diag.h [new file with mode: 0644]
arch/s390/hypfs/inode.c [new file with mode: 0644]
arch/s390/kernel/audit.c [new file with mode: 0644]
arch/s390/kernel/compat_audit.c [new file with mode: 0644]
arch/s390/kernel/stacktrace.c [new file with mode: 0644]
arch/s390/lib/div64.c [new file with mode: 0644]
arch/sparc/kernel/of_device.c [new file with mode: 0644]
arch/sparc/kernel/prom.c [new file with mode: 0644]
arch/sparc/lib/iomap.c [new file with mode: 0644]
arch/sparc64/kernel/audit.c [new file with mode: 0644]
arch/sparc64/kernel/compat_audit.c [new file with mode: 0644]
arch/sparc64/kernel/of_device.c [new file with mode: 0644]
arch/sparc64/kernel/prom.c [new file with mode: 0644]
arch/um/kernel/exec.c [new file with mode: 0644]
arch/um/kernel/irq.c.orig [new file with mode: 0644]
arch/um/kernel/sigio.c [new file with mode: 0644]
arch/um/kernel/signal.c [new file with mode: 0644]
arch/um/kernel/trap.c [new file with mode: 0644]
arch/x86_64/ia32/audit.c [new file with mode: 0644]
arch/x86_64/kernel/audit.c [new file with mode: 0644]
arch/x86_64/kernel/irqflags-xen.c [new file with mode: 0644]
arch/x86_64/kernel/k8.c [new file with mode: 0644]
arch/x86_64/kernel/pci-calgary.c [new file with mode: 0644]
arch/x86_64/kernel/stacktrace.c [new file with mode: 0644]
arch/x86_64/kernel/tce.c [new file with mode: 0644]
arch/x86_64/lib/rwlock.S [new file with mode: 0644]
configs/kernel-2.6.18-i586-smp.config [new file with mode: 0644]
configs/kernel-2.6.18-i586.config [new file with mode: 0644]
configs/kernel-2.6.18-i686-kdump.config [new file with mode: 0644]
configs/kernel-2.6.18-i686-smp.config [new file with mode: 0644]
configs/kernel-2.6.18-i686-xen.config [new file with mode: 0644]
configs/kernel-2.6.18-i686-xen0.config [new file with mode: 0644]
configs/kernel-2.6.18-i686-xenU.config [new file with mode: 0644]
configs/kernel-2.6.18-i686.config [new file with mode: 0644]
configs/kernel-2.6.18-ia64-xen.config [new file with mode: 0644]
configs/kernel-2.6.18-ia64.config [new file with mode: 0644]
configs/kernel-2.6.18-ppc-smp.config [new file with mode: 0644]
configs/kernel-2.6.18-ppc.config [new file with mode: 0644]
configs/kernel-2.6.18-ppc64-kdump.config [new file with mode: 0644]
configs/kernel-2.6.18-ppc64.config [new file with mode: 0644]
configs/kernel-2.6.18-ppc64iseries.config [new file with mode: 0644]
configs/kernel-2.6.18-s390.config [new file with mode: 0644]
configs/kernel-2.6.18-s390x.config [new file with mode: 0644]
configs/kernel-2.6.18-x86_64-kdump.config [new file with mode: 0644]
configs/kernel-2.6.18-x86_64-xen.config [new file with mode: 0644]
configs/kernel-2.6.18-x86_64-xen0.config [new file with mode: 0644]
configs/kernel-2.6.18-x86_64-xenU.config [new file with mode: 0644]
configs/kernel-2.6.18-x86_64.config [new file with mode: 0644]
drivers/acpi/cm_sbs.c [new file with mode: 0644]
drivers/acpi/dock.c [new file with mode: 0644]
drivers/acpi/i2c_ec.c [new file with mode: 0644]
drivers/acpi/i2c_ec.h [new file with mode: 0644]
drivers/acpi/sbs.c [new file with mode: 0644]
drivers/base/hypervisor.c [new file with mode: 0644]
drivers/base/isa.c [new file with mode: 0644]
drivers/base/power/trace.c [new file with mode: 0644]
drivers/char/hw_random/Kconfig [new file with mode: 0644]
drivers/char/hw_random/Makefile [new file with mode: 0644]
drivers/char/hw_random/amd-rng.c [new file with mode: 0644]
drivers/char/hw_random/core.c [new file with mode: 0644]
drivers/char/hw_random/geode-rng.c [new file with mode: 0644]
drivers/char/hw_random/intel-rng.c [new file with mode: 0644]
drivers/char/hw_random/ixp4xx-rng.c [new file with mode: 0644]
drivers/char/hw_random/omap-rng.c [new file with mode: 0644]
drivers/char/hw_random/via-rng.c [new file with mode: 0644]
drivers/char/nsc_gpio.c [new file with mode: 0644]
drivers/char/pc8736x_gpio.c [new file with mode: 0644]
drivers/clocksource/Makefile [new file with mode: 0644]
drivers/clocksource/acpi_pm.c [new file with mode: 0644]
drivers/clocksource/cyclone.c [new file with mode: 0644]
drivers/clocksource/scx200_hrt.c [new file with mode: 0644]
drivers/dma/Kconfig [new file with mode: 0644]
drivers/dma/Makefile [new file with mode: 0644]
drivers/dma/dmaengine.c [new file with mode: 0644]
drivers/dma/ioatdma.c [new file with mode: 0644]
drivers/dma/ioatdma.h [new file with mode: 0644]
drivers/dma/ioatdma_hw.h [new file with mode: 0644]
drivers/dma/ioatdma_io.h [new file with mode: 0644]
drivers/dma/ioatdma_registers.h [new file with mode: 0644]
drivers/dma/iovlock.c [new file with mode: 0644]
drivers/edac/k8_edac.c [new file with mode: 0644]
drivers/hwmon/abituguru.c [new file with mode: 0644]
drivers/hwmon/lm70.c [new file with mode: 0644]
drivers/hwmon/smsc47m192.c [new file with mode: 0644]
drivers/hwmon/w83791d.c [new file with mode: 0644]
drivers/i2c/busses/i2c-ocores.c [new file with mode: 0644]
drivers/infiniband/core/addr.c [new file with mode: 0644]
drivers/infiniband/core/cma.c [new file with mode: 0644]
drivers/infiniband/core/uverbs_marshall.c [new file with mode: 0644]
drivers/infiniband/ulp/iser/Kconfig [new file with mode: 0644]
drivers/infiniband/ulp/iser/Makefile [new file with mode: 0644]
drivers/infiniband/ulp/iser/iscsi_iser.c [new file with mode: 0644]
drivers/infiniband/ulp/iser/iscsi_iser.h [new file with mode: 0644]
drivers/infiniband/ulp/iser/iser_initiator.c [new file with mode: 0644]
drivers/infiniband/ulp/iser/iser_memory.c [new file with mode: 0644]
drivers/infiniband/ulp/iser/iser_verbs.c [new file with mode: 0644]
drivers/leds/leds-ams-delta.c [new file with mode: 0644]
drivers/leds/leds-net48xx.c [new file with mode: 0644]
drivers/leds/ledtrig-heartbeat.c [new file with mode: 0644]
drivers/macintosh/via-pmu-backlight.c [new file with mode: 0644]
drivers/macintosh/via-pmu-event.c [new file with mode: 0644]
drivers/macintosh/via-pmu-event.h [new file with mode: 0644]
drivers/macintosh/via-pmu-led.c [new file with mode: 0644]
drivers/media/dvb/dvb-core/dvb_math.c [new file with mode: 0644]
drivers/media/dvb/dvb-core/dvb_math.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/gp8psk-fe.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/gp8psk.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/gp8psk.h [new file with mode: 0644]
drivers/media/dvb/frontends/isl6421.c [new file with mode: 0644]
drivers/media/dvb/frontends/isl6421.h [new file with mode: 0644]
drivers/media/dvb/frontends/lg_h06xf.h [new file with mode: 0644]
drivers/media/dvb/frontends/lnbp21.c [new file with mode: 0644]
drivers/media/radio/dsbr100.c [new file with mode: 0644]
drivers/media/video/bt866.c [new file with mode: 0644]
drivers/media/video/cx2341x.c [new file with mode: 0644]
drivers/media/video/ks0127.c [new file with mode: 0644]
drivers/media/video/ks0127.h [new file with mode: 0644]
drivers/media/video/pvrusb2/Kconfig [new file with mode: 0644]
drivers/media/video/pvrusb2/Makefile [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-audio.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-audio.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-context.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-context.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-ctrl.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-ctrl.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-debug.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-debugifc.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-debugifc.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-eeprom.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-eeprom.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-encoder.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-encoder.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-hdw.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-hdw.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-i2c-core.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-io.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-io.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-ioread.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-ioread.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-main.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-std.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-std.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-sysfs.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-sysfs.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-tuner.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-tuner.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-util.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-v4l2.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-v4l2.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-video-v4l.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-video-v4l.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-wm8775.c [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2-wm8775.h [new file with mode: 0644]
drivers/media/video/pvrusb2/pvrusb2.h [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec1.c [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec1.h [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec23.c [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec23.h [new file with mode: 0644]
drivers/media/video/pwc/pwc-v4l.c [new file with mode: 0644]
drivers/media/video/tlv320aic23b.c [new file with mode: 0644]
drivers/media/video/usbvideo/quickcam_messenger.c [new file with mode: 0644]
drivers/media/video/usbvideo/quickcam_messenger.h [new file with mode: 0644]
drivers/media/video/zc0301/zc0301_pb0330.c [new file with mode: 0644]
drivers/mtd/nand/ams-delta.c [new file with mode: 0644]
drivers/mtd/nand/cs553x_nand.c [new file with mode: 0644]
drivers/mtd/nand/ndfc.c [new file with mode: 0644]
drivers/mtd/nand/ts7250.c [new file with mode: 0644]
drivers/net/fs_enet/fec.h [new file with mode: 0644]
drivers/net/fs_enet/mii-fec.c [new file with mode: 0644]
drivers/net/irda/mcs7780.c [new file with mode: 0644]
drivers/net/irda/mcs7780.h [new file with mode: 0644]
drivers/net/myri10ge/Makefile [new file with mode: 0644]
drivers/net/myri10ge/myri10ge.c [new file with mode: 0644]
drivers/net/myri10ge/myri10ge_mcp.h [new file with mode: 0644]
drivers/net/myri10ge/myri10ge_mcp_gen_header.h [new file with mode: 0644]
drivers/net/netx-eth.c [new file with mode: 0644]
drivers/net/phy/fixed.c [new file with mode: 0644]
drivers/net/phy/smsc.c [new file with mode: 0644]
drivers/net/phy/vitesse.c [new file with mode: 0644]
drivers/net/smc911x.c [new file with mode: 0644]
drivers/net/smc911x.h [new file with mode: 0644]
drivers/net/ucc_geth.c [new file with mode: 0644]
drivers/net/ucc_geth.h [new file with mode: 0644]
drivers/net/ucc_geth_phy.c [new file with mode: 0644]
drivers/net/ucc_geth_phy.h [new file with mode: 0644]
drivers/net/wireless/orinoco_pci.h [new file with mode: 0644]
drivers/net/wireless/zd1201.c [new file with mode: 0644]
drivers/net/wireless/zd1201.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/Kconfig [new file with mode: 0644]
drivers/net/wireless/zd1211rw/Makefile [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_chip.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_chip.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_def.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_ieee80211.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_ieee80211.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_mac.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_mac.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_netdev.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_netdev.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_rf.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_rf.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_rf_al2230.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_types.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_usb.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_usb.h [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_util.c [new file with mode: 0644]
drivers/net/wireless/zd1211rw/zd_util.h [new file with mode: 0644]
drivers/parport/parport_ax88796.c [new file with mode: 0644]
drivers/pci/msi-altix.c [new file with mode: 0644]
drivers/pci/msi-apic.c [new file with mode: 0644]
drivers/rtc/rtc-at91.c [new file with mode: 0644]
drivers/rtc/rtc-ds1307.c [new file with mode: 0644]
drivers/rtc/rtc-ds1553.c [new file with mode: 0644]
drivers/rtc/rtc-ds1742.c [new file with mode: 0644]
drivers/rtc/rtc-isl1208.c [new file with mode: 0644]
drivers/rtc/rtc-max6902.c [new file with mode: 0644]
drivers/rtc/rtc-pcf8583.c [new file with mode: 0644]
drivers/rtc/rtc-pl031.c [new file with mode: 0644]
drivers/rtc/rtc-rs5c348.c [new file with mode: 0644]
drivers/rtc/rtc-s3c.c [new file with mode: 0644]
drivers/rtc/rtc-v3020.c [new file with mode: 0644]
drivers/scsi/hptiop.c [new file with mode: 0644]
drivers/scsi/hptiop.h [new file with mode: 0644]
drivers/scsi/libata-eh.c [new file with mode: 0644]
drivers/scsi/scsi_transport_api.h [new file with mode: 0644]
drivers/serial/netx-serial.c [new file with mode: 0644]
drivers/usb/core/endpoint.c [new file with mode: 0644]
drivers/usb/host/ohci-ep93xx.c [new file with mode: 0644]
drivers/usb/misc/appledisplay.c [new file with mode: 0644]
drivers/usb/misc/cypress_cy7c63.c [new file with mode: 0644]
drivers/usb/serial/sierra.c [new file with mode: 0644]
drivers/video/aty/radeon_backlight.c [new file with mode: 0644]
drivers/video/fb_notify.c [new file with mode: 0644]
drivers/video/imacfb.c [new file with mode: 0644]
drivers/video/mbx/Makefile [new file with mode: 0644]
drivers/video/mbx/mbxdebugfs.c [new file with mode: 0644]
drivers/video/mbx/mbxfb.c [new file with mode: 0644]
drivers/video/mbx/reg_bits.h [new file with mode: 0644]
drivers/video/mbx/regs.h [new file with mode: 0644]
drivers/video/nvidia/nv_backlight.c [new file with mode: 0644]
drivers/video/pnx4008/Makefile [new file with mode: 0644]
drivers/video/pnx4008/dum.h [new file with mode: 0644]
drivers/video/pnx4008/fbcommon.h [new file with mode: 0644]
drivers/video/pnx4008/pnxrgbfb.c [new file with mode: 0644]
drivers/video/pnx4008/sdum.c [new file with mode: 0644]
drivers/video/pnx4008/sdum.h [new file with mode: 0644]
drivers/w1/masters/ds2490.c [new file with mode: 0644]
drivers/xen/blktap/blktapmain.c [new file with mode: 0644]
drivers/xen/xenfb/Makefile [new file with mode: 0644]
drivers/xen/xenfb/xenfb.c [new file with mode: 0644]
drivers/xen/xenkbd/Makefile [new file with mode: 0644]
drivers/xen/xenkbd/xenkbd.c [new file with mode: 0644]
fs/cachefiles/Makefile [new file with mode: 0644]
fs/cachefiles/cf-bind.c [new file with mode: 0644]
fs/cachefiles/cf-interface.c [new file with mode: 0644]
fs/cachefiles/cf-key.c [new file with mode: 0644]
fs/cachefiles/cf-main.c [new file with mode: 0644]
fs/cachefiles/cf-namei.c [new file with mode: 0644]
fs/cachefiles/cf-proc.c [new file with mode: 0644]
fs/cachefiles/cf-sysctl.c [new file with mode: 0644]
fs/cachefiles/cf-xattr.c [new file with mode: 0644]
fs/cachefiles/internal.h [new file with mode: 0644]
fs/cifs/sess.c [new file with mode: 0644]
fs/fscache/Makefile [new file with mode: 0644]
fs/fscache/cookie.c [new file with mode: 0644]
fs/fscache/fscache-int.h [new file with mode: 0644]
fs/fscache/fsdef.c [new file with mode: 0644]
fs/fscache/main.c [new file with mode: 0644]
fs/fscache/page.c [new file with mode: 0644]
fs/fuse/control.c [new file with mode: 0644]
fs/inotify_user.c [new file with mode: 0644]
fs/jffs2/acl.c [new file with mode: 0644]
fs/jffs2/acl.h [new file with mode: 0644]
fs/jffs2/jffs2_fs_i.h [new file with mode: 0644]
fs/jffs2/jffs2_fs_sb.h [new file with mode: 0644]
fs/jffs2/security.c [new file with mode: 0644]
fs/jffs2/xattr.c [new file with mode: 0644]
fs/jffs2/xattr.h [new file with mode: 0644]
fs/jffs2/xattr_trusted.c [new file with mode: 0644]
fs/jffs2/xattr_user.c [new file with mode: 0644]
fs/nfs/client.c [new file with mode: 0644]
fs/nfs/fscache.c [new file with mode: 0644]
fs/nfs/fscache.h [new file with mode: 0644]
fs/nfs/getroot.c [new file with mode: 0644]
fs/nfs/internal.h [new file with mode: 0644]
fs/nfs/namespace.c [new file with mode: 0644]
fs/nfs/nfs4namespace.c [new file with mode: 0644]
fs/nfs/super.c [new file with mode: 0644]
fs/squashfs/squashfs.h [new file with mode: 0644]
fs/squashfs/squashfs2_0.c [new file with mode: 0644]
include/Kbuild [new file with mode: 0644]
include/acpi/acpi_numa.h [new file with mode: 0644]
include/asm-alpha/Kbuild [new file with mode: 0644]
include/asm-arm/Kbuild [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91rm9200_spi.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91rm9200_tc.h [new file with mode: 0644]
include/asm-arm/arch-at91rm9200/at91rm9200_udp.h [new file with mode: 0644]
include/asm-arm/arch-lh7a40x/clocks.h [new file with mode: 0644]
include/asm-arm/arch-lh7a40x/ssp.h [new file with mode: 0644]
include/asm-arm/arch-netx/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-netx/dma.h [new file with mode: 0644]
include/asm-arm/arch-netx/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-netx/eth.h [new file with mode: 0644]
include/asm-arm/arch-netx/hardware.h [new file with mode: 0644]
include/asm-arm/arch-netx/io.h [new file with mode: 0644]
include/asm-arm/arch-netx/irqs.h [new file with mode: 0644]
include/asm-arm/arch-netx/memory.h [new file with mode: 0644]
include/asm-arm/arch-netx/netx-regs.h [new file with mode: 0644]
include/asm-arm/arch-netx/param.h [new file with mode: 0644]
include/asm-arm/arch-netx/pfifo.h [new file with mode: 0644]
include/asm-arm/arch-netx/system.h [new file with mode: 0644]
include/asm-arm/arch-netx/timex.h [new file with mode: 0644]
include/asm-arm/arch-netx/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-netx/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-netx/xc.h [new file with mode: 0644]
include/asm-arm/arch-omap/board-fsample.h [new file with mode: 0644]
include/asm-arm/arch-omap/gpmc.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/clock.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-pnx4008/dma.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-pnx4008/gpio.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/hardware.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/io.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/irq.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/irqs.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/memory.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/param.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/platform.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/pm.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/system.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/timex.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-pxa/trizeps4.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-power.h [new file with mode: 0644]
include/asm-arm/dyntick.h [new file with mode: 0644]
include/asm-arm/hw_irq.h [new file with mode: 0644]
include/asm-arm/mach/serial_at91.h [new file with mode: 0644]
include/asm-arm/page-nommu.h [new file with mode: 0644]
include/asm-arm/pgtable-nommu.h [new file with mode: 0644]
include/asm-arm/thread_notify.h [new file with mode: 0644]
include/asm-cris/Kbuild [new file with mode: 0644]
include/asm-cris/arch-v10/Kbuild [new file with mode: 0644]
include/asm-cris/arch-v32/Kbuild [new file with mode: 0644]
include/asm-frv/Kbuild [new file with mode: 0644]
include/asm-generic/Kbuild [new file with mode: 0644]
include/asm-generic/Kbuild.asm [new file with mode: 0644]
include/asm-generic/audit_change_attr.h [new file with mode: 0644]
include/asm-generic/audit_dir_write.h [new file with mode: 0644]
include/asm-generic/audit_read.h [new file with mode: 0644]
include/asm-generic/audit_write.h [new file with mode: 0644]
include/asm-h8300/Kbuild [new file with mode: 0644]
include/asm-i386/Kbuild [new file with mode: 0644]
include/asm-i386/dwarf2.h [new file with mode: 0644]
include/asm-i386/intel_arch_perfmon.h [new file with mode: 0644]
include/asm-i386/irqflags.h [new file with mode: 0644]
include/asm-i386/k8.h [new file with mode: 0644]
include/asm-i386/mach-default/setup_arch.h [new file with mode: 0644]
include/asm-i386/mach-visws/setup_arch.h [new file with mode: 0644]
include/asm-i386/mach-voyager/setup_arch.h [new file with mode: 0644]
include/asm-i386/mach-xen/asm/irqflags.h [new file with mode: 0644]
include/asm-i386/mach-xen/asm/maddr.h [new file with mode: 0644]
include/asm-i386/mach-xen/asm/stacktrace.h [new file with mode: 0644]
include/asm-i386/mach-xen/asm/timer.h [new file with mode: 0644]
include/asm-i386/mach-xen/setup_arch.h [new file with mode: 0644]
include/asm-i386/mce.h [new file with mode: 0644]
include/asm-i386/stacktrace.h [new file with mode: 0644]
include/asm-i386/tracehook.h [new file with mode: 0644]
include/asm-i386/tsc.h [new file with mode: 0644]
include/asm-i386/unwind.h [new file with mode: 0644]
include/asm-ia64/Kbuild [new file with mode: 0644]
include/asm-ia64/fixmap.h [new file with mode: 0644]
include/asm-ia64/hypercall.h [new file with mode: 0644]
include/asm-ia64/hypervisor.h [new file with mode: 0644]
include/asm-ia64/maddr.h [new file with mode: 0644]
include/asm-ia64/privop.h [new file with mode: 0644]
include/asm-ia64/synch_bitops.h [new file with mode: 0644]
include/asm-ia64/tracehook.h [new file with mode: 0644]
include/asm-ia64/xen/privop.h [new file with mode: 0644]
include/asm-m32r/Kbuild [new file with mode: 0644]
include/asm-m68k/Kbuild [new file with mode: 0644]
include/asm-m68knommu/Kbuild [new file with mode: 0644]
include/asm-m68knommu/m532xsim.h [new file with mode: 0644]
include/asm-mips/Kbuild [new file with mode: 0644]
include/asm-mips/apm.h [new file with mode: 0644]
include/asm-mips/emma2rh/emma2rh.h [new file with mode: 0644]
include/asm-mips/emma2rh/markeins.h [new file with mode: 0644]
include/asm-mips/irqflags.h [new file with mode: 0644]
include/asm-mips/mach-emma2rh/irq.h [new file with mode: 0644]
include/asm-mips/mach-excite/cpu-feature-overrides.h [new file with mode: 0644]
include/asm-mips/mach-excite/excite.h [new file with mode: 0644]
include/asm-mips/mach-excite/excite_nandflash.h [new file with mode: 0644]
include/asm-mips/mach-excite/rm9k_eth.h [new file with mode: 0644]
include/asm-mips/mach-excite/rm9k_wdt.h [new file with mode: 0644]
include/asm-mips/mach-excite/rm9k_xicap.h [new file with mode: 0644]
include/asm-mips/mach-wrppmc/mach-gt64120.h [new file with mode: 0644]
include/asm-mips/rm9k-ocd.h [new file with mode: 0644]
include/asm-mips/sn/fru.h [new file with mode: 0644]
include/asm-mips/vr41xx/irq.h [new file with mode: 0644]
include/asm-parisc/Kbuild [new file with mode: 0644]
include/asm-powerpc/Kbuild [new file with mode: 0644]
include/asm-powerpc/immap_86xx.h [new file with mode: 0644]
include/asm-powerpc/irqflags.h [new file with mode: 0644]
include/asm-powerpc/iseries/iommu.h [new file with mode: 0644]
include/asm-powerpc/mpc86xx.h [new file with mode: 0644]
include/asm-powerpc/spu_priv1.h [new file with mode: 0644]
include/asm-powerpc/systbl.h [new file with mode: 0644]
include/asm-powerpc/todc.h [new file with mode: 0644]
include/asm-powerpc/tracehook.h [new file with mode: 0644]
include/asm-powerpc/tsi108.h [new file with mode: 0644]
include/asm-powerpc/tsi108_irq.h [new file with mode: 0644]
include/asm-s390/Kbuild [new file with mode: 0644]
include/asm-s390/irqflags.h [new file with mode: 0644]
include/asm-s390/tracehook.h [new file with mode: 0644]
include/asm-s390/z90crypt.h [new file with mode: 0644]
include/asm-sh/Kbuild [new file with mode: 0644]
include/asm-sh64/Kbuild [new file with mode: 0644]
include/asm-sparc/Kbuild [new file with mode: 0644]
include/asm-sparc/of_device.h [new file with mode: 0644]
include/asm-sparc/prom.h [new file with mode: 0644]
include/asm-sparc64/Kbuild [new file with mode: 0644]
include/asm-sparc64/of_device.h [new file with mode: 0644]
include/asm-sparc64/prom.h [new file with mode: 0644]
include/asm-sparc64/tracehook.h [new file with mode: 0644]
include/asm-v850/Kbuild [new file with mode: 0644]
include/asm-x86_64/Kbuild [new file with mode: 0644]
include/asm-x86_64/alternative-asm.i [new file with mode: 0644]
include/asm-x86_64/alternative.h [new file with mode: 0644]
include/asm-x86_64/calgary.h [new file with mode: 0644]
include/asm-x86_64/intel_arch_perfmon.h [new file with mode: 0644]
include/asm-x86_64/irqflags.h [new file with mode: 0644]
include/asm-x86_64/k8.h [new file with mode: 0644]
include/asm-x86_64/mach-xen/asm/irqflags.h [new file with mode: 0644]
include/asm-x86_64/mach-xen/asm/maddr.h [new file with mode: 0644]
include/asm-x86_64/mach-xen/asm/stacktrace.h [new file with mode: 0644]
include/asm-x86_64/stacktrace.h [new file with mode: 0644]
include/asm-x86_64/tce.h [new file with mode: 0644]
include/asm-x86_64/tracehook.h [new file with mode: 0644]
include/asm-x86_64/unwind.h [new file with mode: 0644]
include/asm-xtensa/Kbuild [new file with mode: 0644]
include/linux/Kbuild [new file with mode: 0644]
include/linux/byteorder/Kbuild [new file with mode: 0644]
include/linux/clocksource.h [new file with mode: 0644]
include/linux/debug_locks.h [new file with mode: 0644]
include/linux/delayacct.h [new file with mode: 0644]
include/linux/dmaengine.h [new file with mode: 0644]
include/linux/dvb/Kbuild [new file with mode: 0644]
include/linux/elf-em.h [new file with mode: 0644]
include/linux/elfnote.h [new file with mode: 0644]
include/linux/fscache-cache.h [new file with mode: 0644]
include/linux/fscache.h [new file with mode: 0644]
include/linux/hdlc/Kbuild [new file with mode: 0644]
include/linux/hw_random.h [new file with mode: 0644]
include/linux/i2c-ocores.h [new file with mode: 0644]
include/linux/irqflags.h [new file with mode: 0644]
include/linux/irqreturn.h [new file with mode: 0644]
include/linux/isa.h [new file with mode: 0644]
include/linux/isdn/Kbuild [new file with mode: 0644]
include/linux/license.h [new file with mode: 0644]
include/linux/lockdep.h [new file with mode: 0644]
include/linux/m41t00.h [new file with mode: 0644]
include/linux/mtd/ndfc.h [new file with mode: 0644]
include/linux/netfilter/Kbuild [new file with mode: 0644]
include/linux/netfilter/xt_CONNSECMARK.h [new file with mode: 0644]
include/linux/netfilter/xt_SECMARK.h [new file with mode: 0644]
include/linux/netfilter/xt_quota.h [new file with mode: 0644]
include/linux/netfilter/xt_statistic.h [new file with mode: 0644]
include/linux/netfilter_arp/Kbuild [new file with mode: 0644]
include/linux/netfilter_bridge/Kbuild [new file with mode: 0644]
include/linux/netfilter_ipv4/Kbuild [new file with mode: 0644]
include/linux/netfilter_ipv4/ip_conntrack_sip.h [new file with mode: 0644]
include/linux/netfilter_ipv6/Kbuild [new file with mode: 0644]
include/linux/nfsd/Kbuild [new file with mode: 0644]
include/linux/nsc_gpio.h [new file with mode: 0644]
include/linux/plist.h [new file with mode: 0644]
include/linux/poison.h [new file with mode: 0644]
include/linux/raid/Kbuild [new file with mode: 0644]
include/linux/resume-trace.h [new file with mode: 0644]
include/linux/rtc-v3020.h [new file with mode: 0644]
include/linux/rtmutex.h [new file with mode: 0644]
include/linux/stacktrace.h [new file with mode: 0644]
include/linux/sunrpc/Kbuild [new file with mode: 0644]
include/linux/taskstats.h [new file with mode: 0644]
include/linux/taskstats_kern.h [new file with mode: 0644]
include/linux/tc_act/Kbuild [new file with mode: 0644]
include/linux/tc_ematch/Kbuild [new file with mode: 0644]
include/linux/tracehook.h [new file with mode: 0644]
include/linux/uaccess.h [new file with mode: 0644]
include/linux/unwind.h [new file with mode: 0644]
include/linux/usb/cdc.h [new file with mode: 0644]
include/linux/usb/input.h [new file with mode: 0644]
include/linux/usb/isp116x.h [new file with mode: 0644]
include/linux/usb/serial.h [new file with mode: 0644]
include/linux/usb/sl811.h [new file with mode: 0644]
include/linux/utrace.h [new file with mode: 0644]
include/linux/vmstat.h [new file with mode: 0644]
include/linux/vs_cvirt.h.orig [new file with mode: 0644]
include/linux/xenfb.h [new file with mode: 0644]
include/linux/xenkbd.h [new file with mode: 0644]
include/media/cx2341x.h [new file with mode: 0644]
include/media/pwc-ioctl.h [new file with mode: 0644]
include/media/tvp5150.h [new file with mode: 0644]
include/media/v4l2-dev.h [new file with mode: 0644]
include/mtd/Kbuild [new file with mode: 0644]
include/net/netdma.h [new file with mode: 0644]
include/net/netevent.h [new file with mode: 0644]
include/rdma/Kbuild [new file with mode: 0644]
include/rdma/ib_addr.h [new file with mode: 0644]
include/rdma/ib_marshall.h [new file with mode: 0644]
include/rdma/ib_user_sa.h [new file with mode: 0644]
include/rdma/rdma_cm.h [new file with mode: 0644]
include/rdma/rdma_cm_ib.h [new file with mode: 0644]
include/scsi/Kbuild [new file with mode: 0644]
include/sound/Kbuild [new file with mode: 0644]
include/video/Kbuild [new file with mode: 0644]
include/video/mbxfb.h [new file with mode: 0644]
include/xen/hvm.h [new file with mode: 0644]
include/xen/interface/arch-ia64.h [new file with mode: 0644]
include/xen/interface/domctl.h [new file with mode: 0644]
include/xen/interface/elfnote.h [new file with mode: 0644]
include/xen/interface/hvm/e820.h [new file with mode: 0644]
include/xen/interface/platform.h [new file with mode: 0644]
include/xen/interface/sysctl.h [new file with mode: 0644]
kernel/delayacct.c [new file with mode: 0644]
kernel/irq/chip.c [new file with mode: 0644]
kernel/irq/resend.c [new file with mode: 0644]
kernel/lockdep.c [new file with mode: 0644]
kernel/lockdep_internals.h [new file with mode: 0644]
kernel/lockdep_proc.c [new file with mode: 0644]
kernel/rtmutex-debug.c [new file with mode: 0644]
kernel/rtmutex-debug.h [new file with mode: 0644]
kernel/rtmutex-tester.c [new file with mode: 0644]
kernel/rtmutex.c [new file with mode: 0644]
kernel/rtmutex.h [new file with mode: 0644]
kernel/rtmutex_common.h [new file with mode: 0644]
kernel/rwsem.c [new file with mode: 0644]
kernel/stacktrace.c [new file with mode: 0644]
kernel/taskstats.c [new file with mode: 0644]
kernel/time/Makefile [new file with mode: 0644]
kernel/time/clocksource.c [new file with mode: 0644]
kernel/time/jiffies.c [new file with mode: 0644]
kernel/unwind.c [new file with mode: 0644]
kernel/utrace.c [new file with mode: 0644]
lib/audit.c [new file with mode: 0644]
lib/debug_locks.c [new file with mode: 0644]
lib/list_debug.c [new file with mode: 0644]
lib/locking-selftest-hardirq.h [new file with mode: 0644]
lib/locking-selftest-mutex.h [new file with mode: 0644]
lib/locking-selftest-rlock-hardirq.h [new file with mode: 0644]
lib/locking-selftest-rlock-softirq.h [new file with mode: 0644]
lib/locking-selftest-rlock.h [new file with mode: 0644]
lib/locking-selftest-rsem.h [new file with mode: 0644]
lib/locking-selftest-softirq.h [new file with mode: 0644]
lib/locking-selftest-spin-hardirq.h [new file with mode: 0644]
lib/locking-selftest-spin-softirq.h [new file with mode: 0644]
lib/locking-selftest-spin.h [new file with mode: 0644]
lib/locking-selftest-wlock-hardirq.h [new file with mode: 0644]
lib/locking-selftest-wlock-softirq.h [new file with mode: 0644]
lib/locking-selftest-wlock.h [new file with mode: 0644]
lib/locking-selftest-wsem.h [new file with mode: 0644]
lib/locking-selftest.c [new file with mode: 0644]
lib/percpu_counter.c [new file with mode: 0644]
lib/plist.c [new file with mode: 0644]
lib/zlib_inflate/inflate.h [new file with mode: 0644]
mm/vmstat.c [new file with mode: 0644]
net/atm/atm_sysfs.c [new file with mode: 0644]
net/bridge/br_netlink.c [new file with mode: 0644]
net/core/netevent.c [new file with mode: 0644]
net/core/user_dma.c [new file with mode: 0644]
net/ipv4/netfilter/ip_conntrack_sip.c [new file with mode: 0644]
net/ipv4/netfilter/ip_nat_sip.c [new file with mode: 0644]
net/ipv4/tcp_lp.c [new file with mode: 0644]
net/ipv4/tcp_probe.c [new file with mode: 0644]
net/ipv4/tcp_veno.c [new file with mode: 0644]
net/ipv4/xfrm4_mode_transport.c [new file with mode: 0644]
net/ipv4/xfrm4_mode_tunnel.c [new file with mode: 0644]
net/ipv6/xfrm6_mode_transport.c [new file with mode: 0644]
net/ipv6/xfrm6_mode_tunnel.c [new file with mode: 0644]
net/netfilter/xt_CONNSECMARK.c [new file with mode: 0644]
net/netfilter/xt_SECMARK.c [new file with mode: 0644]
net/netfilter/xt_quota.c [new file with mode: 0644]
net/netfilter/xt_statistic.c [new file with mode: 0644]
scripts/Makefile.headersinst [new file with mode: 0644]
scripts/export_report.pl [new file with mode: 0644]
scripts/hdrcheck.sh [new file with mode: 0755]
scripts/rt-tester/check-all.sh [new file with mode: 0644]
scripts/rt-tester/rt-tester.py [new file with mode: 0644]
scripts/rt-tester/t2-l1-2rt-sameprio.tst [new file with mode: 0644]
scripts/rt-tester/t2-l1-pi.tst [new file with mode: 0644]
scripts/rt-tester/t2-l1-signal.tst [new file with mode: 0644]
scripts/rt-tester/t2-l2-2rt-deadlock.tst [new file with mode: 0644]
scripts/rt-tester/t3-l1-pi-1rt.tst [new file with mode: 0644]
scripts/rt-tester/t3-l1-pi-2rt.tst [new file with mode: 0644]
scripts/rt-tester/t3-l1-pi-3rt.tst [new file with mode: 0644]
scripts/rt-tester/t3-l1-pi-signal.tst [new file with mode: 0644]
scripts/rt-tester/t3-l1-pi-steal.tst [new file with mode: 0644]
scripts/rt-tester/t3-l2-pi.tst [new file with mode: 0644]
scripts/rt-tester/t4-l2-pi-deboost.tst [new file with mode: 0644]
scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst [new file with mode: 0644]
scripts/rt-tester/t5-l4-pi-boost-deboost.tst [new file with mode: 0644]
sound/aoa/Kconfig [new file with mode: 0644]
sound/aoa/Makefile [new file with mode: 0644]
sound/aoa/aoa-gpio.h [new file with mode: 0644]
sound/aoa/aoa.h [new file with mode: 0644]
sound/aoa/codecs/Kconfig [new file with mode: 0644]
sound/aoa/codecs/Makefile [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-onyx.c [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-onyx.h [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-tas.c [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-tas.h [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-toonie.c [new file with mode: 0644]
sound/aoa/core/Makefile [new file with mode: 0644]
sound/aoa/core/snd-aoa-alsa.c [new file with mode: 0644]
sound/aoa/core/snd-aoa-alsa.h [new file with mode: 0644]
sound/aoa/core/snd-aoa-core.c [new file with mode: 0644]
sound/aoa/core/snd-aoa-gpio-feature.c [new file with mode: 0644]
sound/aoa/core/snd-aoa-gpio-pmf.c [new file with mode: 0644]
sound/aoa/fabrics/Kconfig [new file with mode: 0644]
sound/aoa/fabrics/Makefile [new file with mode: 0644]
sound/aoa/fabrics/snd-aoa-fabric-layout.c [new file with mode: 0644]
sound/aoa/soundbus/Kconfig [new file with mode: 0644]
sound/aoa/soundbus/Makefile [new file with mode: 0644]
sound/aoa/soundbus/core.c [new file with mode: 0644]
sound/aoa/soundbus/i2sbus/Makefile [new file with mode: 0644]
sound/aoa/soundbus/i2sbus/i2sbus-control.c [new file with mode: 0644]
sound/aoa/soundbus/i2sbus/i2sbus-core.c [new file with mode: 0644]
sound/aoa/soundbus/i2sbus/i2sbus-interface.h [new file with mode: 0644]
sound/aoa/soundbus/i2sbus/i2sbus-pcm.c [new file with mode: 0644]
sound/aoa/soundbus/i2sbus/i2sbus.h [new file with mode: 0644]
sound/aoa/soundbus/soundbus.h [new file with mode: 0644]
sound/aoa/soundbus/sysfs.c [new file with mode: 0644]
sound/pci/cs5535audio/cs5535audio_pm.c [new file with mode: 0644]
sound/pci/echoaudio/Makefile [new file with mode: 0644]
sound/pci/echoaudio/darla20.c [new file with mode: 0644]
sound/pci/echoaudio/darla20_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/darla24.c [new file with mode: 0644]
sound/pci/echoaudio/darla24_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/echo3g.c [new file with mode: 0644]
sound/pci/echoaudio/echo3g_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/echoaudio.c [new file with mode: 0644]
sound/pci/echoaudio/echoaudio.h [new file with mode: 0644]
sound/pci/echoaudio/echoaudio_3g.c [new file with mode: 0644]
sound/pci/echoaudio/echoaudio_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/echoaudio_dsp.h [new file with mode: 0644]
sound/pci/echoaudio/echoaudio_gml.c [new file with mode: 0644]
sound/pci/echoaudio/gina20.c [new file with mode: 0644]
sound/pci/echoaudio/gina20_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/gina24.c [new file with mode: 0644]
sound/pci/echoaudio/gina24_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/indigo.c [new file with mode: 0644]
sound/pci/echoaudio/indigo_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/indigodj.c [new file with mode: 0644]
sound/pci/echoaudio/indigodj_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/indigoio.c [new file with mode: 0644]
sound/pci/echoaudio/indigoio_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/layla20.c [new file with mode: 0644]
sound/pci/echoaudio/layla20_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/layla24.c [new file with mode: 0644]
sound/pci/echoaudio/layla24_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/mia.c [new file with mode: 0644]
sound/pci/echoaudio/mia_dsp.c [new file with mode: 0644]
sound/pci/echoaudio/midi.c [new file with mode: 0644]
sound/pci/echoaudio/mona.c [new file with mode: 0644]
sound/pci/echoaudio/mona_dsp.c [new file with mode: 0644]
sound/pci/emu10k1/p17v.h [new file with mode: 0644]
sound/pci/hda/patch_atihdmi.c [new file with mode: 0644]

diff --git a/Documentation/ABI/README b/Documentation/ABI/README
new file mode 100644 (file)
index 0000000..9feaf16
--- /dev/null
@@ -0,0 +1,77 @@
+This directory attempts to document the ABI between the Linux kernel and
+userspace, and the relative stability of these interfaces.  Due to the
+everchanging nature of Linux, and the differing maturity levels, these
+interfaces should be used by userspace programs in different ways.
+
+We have four different levels of ABI stability, as shown by the four
+different subdirectories in this location.  Interfaces may change levels
+of stability according to the rules described below.
+
+The different levels of stability are:
+
+  stable/
+       This directory documents the interfaces that the developer has
+       defined to be stable.  Userspace programs are free to use these
+       interfaces with no restrictions, and backward compatibility for
+       them will be guaranteed for at least 2 years.  Most interfaces
+       (like syscalls) are expected to never change and always be
+       available.
+
+  testing/
+       This directory documents interfaces that are felt to be stable,
+       as the main development of this interface has been completed.
+       The interface can be changed to add new features, but the
+       current interface will not break by doing this, unless grave
+       errors or security problems are found in them.  Userspace
+       programs can start to rely on these interfaces, but they must be
+       aware of changes that can occur before these interfaces move to
+       be marked stable.  Programs that use these interfaces are
+       strongly encouraged to add their name to the description of
+       these interfaces, so that the kernel developers can easily
+       notify them if any changes occur (see the description of the
+       layout of the files below for details on how to do this.)
+
+  obsolete/
+       This directory documents interfaces that are still remaining in
+       the kernel, but are marked to be removed at some later point in
+       time.  The description of the interface will document the reason
+       why it is obsolete and when it can be expected to be removed.
+       The file Documentation/feature-removal-schedule.txt may describe
+       some of these interfaces, giving a schedule for when they will
+       be removed.
+
+  removed/
+       This directory contains a list of the old interfaces that have
+       been removed from the kernel.
+
+Every file in these directories will contain the following information:
+
+What:          Short description of the interface
+Date:          Date created
+KernelVersion: Kernel version this feature first showed up in.
+Contact:       Primary contact for this interface (may be a mailing list)
+Description:   Long description of the interface and how to use it.
+Users:         All users of this interface who wish to be notified when
+               it changes.  This is very important for interfaces in
+               the "testing" stage, so that kernel developers can work
+               with userspace developers to ensure that things do not
+               break in ways that are unacceptable.  It is also
+               important to get feedback for these interfaces to make
+               sure they are working in a proper way and do not need to
+               be changed further.
+
+
+How things move between levels:
+
+Interfaces in stable may move to obsolete, as long as the proper
+notification is given.
+
+Interfaces may be removed from obsolete and the kernel as long as the
+documented amount of time has gone by.
+
+Interfaces in the testing state can move to the stable state when the
+developers feel they are finished.  They cannot be removed from the
+kernel tree without going through the obsolete state first.
+
+It's up to the developer to place their interfaces in the category they
+wish for it to start out in.
diff --git a/Documentation/ABI/obsolete/devfs b/Documentation/ABI/obsolete/devfs
new file mode 100644 (file)
index 0000000..b8b8739
--- /dev/null
@@ -0,0 +1,13 @@
+What:          devfs
+Date:          July 2005
+Contact:       Greg Kroah-Hartman <gregkh@suse.de>
+Description:
+       devfs has been unmaintained for a number of years, has unfixable
+       races, contains a naming policy within the kernel that is
+       against the LSB, and can be replaced by using udev.
+       The files fs/devfs/*, include/linux/devfs_fs*.h will be removed,
+       along with the the assorted devfs function calls throughout the
+       kernel tree.
+
+Users:
+
diff --git a/Documentation/ABI/stable/syscalls b/Documentation/ABI/stable/syscalls
new file mode 100644 (file)
index 0000000..c3ae3e7
--- /dev/null
@@ -0,0 +1,10 @@
+What:          The kernel syscall interface
+Description:
+       This interface matches much of the POSIX interface and is based
+       on it and other Unix based interfaces.  It will only be added to
+       over time, and not have things removed from it.
+
+       Note that this interface is different for every architecture
+       that Linux supports.  Please see the architecture-specific
+       documentation for details on the syscall numbers that are to be
+       mapped to each syscall.
diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module
new file mode 100644 (file)
index 0000000..75be431
--- /dev/null
@@ -0,0 +1,30 @@
+What:          /sys/module
+Description:
+       The /sys/module tree consists of the following structure:
+
+       /sys/module/MODULENAME
+               The name of the module that is in the kernel.  This
+               module name will show up either if the module is built
+               directly into the kernel, or if it is loaded as a
+               dyanmic module.
+
+       /sys/module/MODULENAME/parameters
+               This directory contains individual files that are each
+               individual parameters of the module that are able to be
+               changed at runtime.  See the individual module
+               documentation as to the contents of these parameters and
+               what they accomplish.
+
+               Note: The individual parameter names and values are not
+               considered stable, only the fact that they will be
+               placed in this location within sysfs.  See the
+               individual driver documentation for details as to the
+               stability of the different parameters.
+
+       /sys/module/MODULENAME/refcnt
+               If the module is able to be unloaded from the kernel, this file
+               will contain the current reference count of the module.
+
+               Note: If the module is built into the kernel, or if the
+               CONFIG_MODULE_UNLOAD kernel configuration value is not enabled,
+               this file will not be present.
diff --git a/Documentation/ABI/testing/sysfs-class b/Documentation/ABI/testing/sysfs-class
new file mode 100644 (file)
index 0000000..4b0cb89
--- /dev/null
@@ -0,0 +1,16 @@
+What:          /sys/class/
+Date:          Febuary 2006
+Contact:       Greg Kroah-Hartman <gregkh@suse.de>
+Description:
+               The /sys/class directory will consist of a group of
+               subdirectories describing individual classes of devices
+               in the kernel.  The individual directories will consist
+               of either subdirectories, or symlinks to other
+               directories.
+
+               All programs that use this directory tree must be able
+               to handle both subdirectories or symlinks in order to
+               work properly.
+
+Users:
+       udev <linux-hotplug-devel@lists.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-devices b/Documentation/ABI/testing/sysfs-devices
new file mode 100644 (file)
index 0000000..6a25671
--- /dev/null
@@ -0,0 +1,25 @@
+What:          /sys/devices
+Date:          February 2006
+Contact:       Greg Kroah-Hartman <gregkh@suse.de>
+Description:
+               The /sys/devices tree contains a snapshot of the
+               internal state of the kernel device tree.  Devices will
+               be added and removed dynamically as the machine runs,
+               and between different kernel versions, the layout of the
+               devices within this tree will change.
+
+               Please do not rely on the format of this tree because of
+               this.  If a program wishes to find different things in
+               the tree, please use the /sys/class structure and rely
+               on the symlinks there to point to the proper location
+               within the /sys/devices tree of the individual devices.
+               Or rely on the uevent messages to notify programs of
+               devices being added and removed from this tree to find
+               the location of those devices.
+
+               Note that sometimes not all devices along the directory
+               chain will have emitted uevent messages, so userspace
+               programs must be able to handle such occurrences.
+
+Users:
+       udev <linux-hotplug-devel@lists.sourceforge.net>
diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl
new file mode 100644 (file)
index 0000000..0f4a4b6
--- /dev/null
@@ -0,0 +1,474 @@
+<?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="Generic-IRQ-Guide">
+ <bookinfo>
+  <title>Linux generic IRQ handling</title>
+
+  <authorgroup>
+   <author>
+    <firstname>Thomas</firstname>
+    <surname>Gleixner</surname>
+    <affiliation>
+     <address>
+      <email>tglx@linutronix.de</email>
+     </address>
+    </affiliation>
+   </author>
+   <author>
+    <firstname>Ingo</firstname>
+    <surname>Molnar</surname>
+    <affiliation>
+     <address>
+      <email>mingo@elte.hu</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2005-2006</year>
+   <holder>Thomas Gleixner</holder>
+  </copyright>
+  <copyright>
+   <year>2005-2006</year>
+   <holder>Ingo Molnar</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 version 2 as published by the Free Software Foundation.
+   </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>
+       The generic interrupt handling layer is designed to provide a
+       complete abstraction of interrupt handling for device drivers.
+       It is able to handle all the different types of interrupt controller
+       hardware. Device drivers use generic API functions to request, enable,
+       disable and free interrupts. The drivers do not have to know anything
+       about interrupt hardware details, so they can be used on different
+       platforms without code changes.
+    </para>
+    <para>
+       This documentation is provided to developers who want to implement
+       an interrupt subsystem based for their architecture, with the help
+       of the generic IRQ handling layer.
+    </para>
+  </chapter>
+
+  <chapter id="rationale">
+    <title>Rationale</title>
+       <para>
+       The original implementation of interrupt handling in Linux is using
+       the __do_IRQ() super-handler, which is able to deal with every
+       type of interrupt logic.
+       </para>
+       <para>
+       Originally, Russell King identified different types of handlers to
+       build a quite universal set for the ARM interrupt handler
+       implementation in Linux 2.5/2.6. He distinguished between:
+       <itemizedlist>
+         <listitem><para>Level type</para></listitem>
+         <listitem><para>Edge type</para></listitem>
+         <listitem><para>Simple type</para></listitem>
+       </itemizedlist>
+       In the SMP world of the __do_IRQ() super-handler another type
+       was identified:
+       <itemizedlist>
+         <listitem><para>Per CPU type</para></listitem>
+       </itemizedlist>
+       </para>
+       <para>
+       This split implementation of highlevel IRQ handlers allows us to
+       optimize the flow of the interrupt handling for each specific
+       interrupt type. This reduces complexity in that particular codepath
+       and allows the optimized handling of a given type.
+       </para>
+       <para>
+       The original general IRQ implementation used hw_interrupt_type
+       structures and their ->ack(), ->end() [etc.] callbacks to
+       differentiate the flow control in the super-handler. This leads to
+       a mix of flow logic and lowlevel hardware logic, and it also leads
+       to unnecessary code duplication: for example in i386, there is a
+       ioapic_level_irq and a ioapic_edge_irq irq-type which share many
+       of the lowlevel details but have different flow handling.
+       </para>
+       <para>
+       A more natural abstraction is the clean separation of the
+       'irq flow' and the 'chip details'.
+       </para>
+       <para>
+       Analysing a couple of architecture's IRQ subsystem implementations
+       reveals that most of them can use a generic set of 'irq flow'
+       methods and only need to add the chip level specific code.
+       The separation is also valuable for (sub)architectures
+       which need specific quirks in the irq flow itself but not in the
+       chip-details - and thus provides a more transparent IRQ subsystem
+       design.
+       </para>
+       <para>
+       Each interrupt descriptor is assigned its own highlevel flow
+       handler, which is normally one of the generic
+       implementations. (This highlevel flow handler implementation also
+       makes it simple to provide demultiplexing handlers which can be
+       found in embedded platforms on various architectures.)
+       </para>
+       <para>
+       The separation makes the generic interrupt handling layer more
+       flexible and extensible. For example, an (sub)architecture can
+       use a generic irq-flow implementation for 'level type' interrupts
+       and add a (sub)architecture specific 'edge type' implementation.
+       </para>
+       <para>
+       To make the transition to the new model easier and prevent the
+       breakage of existing implementations, the __do_IRQ() super-handler
+       is still available. This leads to a kind of duality for the time
+       being. Over time the new model should be used in more and more
+       architectures, as it enables smaller and cleaner IRQ subsystems.
+       </para>
+  </chapter>
+  <chapter id="bugs">
+    <title>Known Bugs And Assumptions</title>
+    <para>
+       None (knock on wood).
+    </para>
+  </chapter>
+
+  <chapter id="Abstraction">
+    <title>Abstraction layers</title>
+    <para>
+       There are three main levels of abstraction in the interrupt code:
+       <orderedlist>
+         <listitem><para>Highlevel driver API</para></listitem>
+         <listitem><para>Highlevel IRQ flow handlers</para></listitem>
+         <listitem><para>Chiplevel hardware encapsulation</para></listitem>
+       </orderedlist>
+    </para>
+    <sect1>
+       <title>Interrupt control flow</title>
+       <para>
+       Each interrupt is described by an interrupt descriptor structure
+       irq_desc. The interrupt is referenced by an 'unsigned int' numeric
+       value which selects the corresponding interrupt decription structure
+       in the descriptor structures array.
+       The descriptor structure contains status information and pointers
+       to the interrupt flow method and the interrupt chip structure
+       which are assigned to this interrupt.
+       </para>
+       <para>
+       Whenever an interrupt triggers, the lowlevel arch code calls into
+       the generic interrupt code by calling desc->handle_irq().
+       This highlevel IRQ handling function only uses desc->chip primitives
+       referenced by the assigned chip descriptor structure.
+       </para>
+    </sect1>
+    <sect1>
+       <title>Highlevel Driver API</title>
+       <para>
+         The highlevel Driver API consists of following functions:
+         <itemizedlist>
+         <listitem><para>request_irq()</para></listitem>
+         <listitem><para>free_irq()</para></listitem>
+         <listitem><para>disable_irq()</para></listitem>
+         <listitem><para>enable_irq()</para></listitem>
+         <listitem><para>disable_irq_nosync() (SMP only)</para></listitem>
+         <listitem><para>synchronize_irq() (SMP only)</para></listitem>
+         <listitem><para>set_irq_type()</para></listitem>
+         <listitem><para>set_irq_wake()</para></listitem>
+         <listitem><para>set_irq_data()</para></listitem>
+         <listitem><para>set_irq_chip()</para></listitem>
+         <listitem><para>set_irq_chip_data()</para></listitem>
+          </itemizedlist>
+         See the autogenerated function documentation for details.
+       </para>
+    </sect1>
+    <sect1>
+       <title>Highlevel IRQ flow handlers</title>
+       <para>
+         The generic layer provides a set of pre-defined irq-flow methods:
+         <itemizedlist>
+         <listitem><para>handle_level_irq</para></listitem>
+         <listitem><para>handle_edge_irq</para></listitem>
+         <listitem><para>handle_simple_irq</para></listitem>
+         <listitem><para>handle_percpu_irq</para></listitem>
+         </itemizedlist>
+         The interrupt flow handlers (either predefined or architecture
+         specific) are assigned to specific interrupts by the architecture
+         either during bootup or during device initialization.
+       </para>
+       <sect2>
+       <title>Default flow implementations</title>
+           <sect3>
+               <title>Helper functions</title>
+               <para>
+               The helper functions call the chip primitives and
+               are used by the default flow implementations.
+               The following helper functions are implemented (simplified excerpt):
+               <programlisting>
+default_enable(irq)
+{
+       desc->chip->unmask(irq);
+}
+
+default_disable(irq)
+{
+       if (!delay_disable(irq))
+               desc->chip->mask(irq);
+}
+
+default_ack(irq)
+{
+       chip->ack(irq);
+}
+
+default_mask_ack(irq)
+{
+       if (chip->mask_ack) {
+               chip->mask_ack(irq);
+       } else {
+               chip->mask(irq);
+               chip->ack(irq);
+       }
+}
+
+noop(irq)
+{
+}
+
+               </programlisting>
+               </para>
+           </sect3>
+       </sect2>
+       <sect2>
+       <title>Default flow handler implementations</title>
+           <sect3>
+               <title>Default Level IRQ flow handler</title>
+               <para>
+               handle_level_irq provides a generic implementation
+               for level-triggered interrupts.
+               </para>
+               <para>
+               The following control flow is implemented (simplified excerpt):
+               <programlisting>
+desc->chip->start();
+handle_IRQ_event(desc->action);
+desc->chip->end();
+               </programlisting>
+               </para>
+           </sect3>
+           <sect3>
+               <title>Default Edge IRQ flow handler</title>
+               <para>
+               handle_edge_irq provides a generic implementation
+               for edge-triggered interrupts.
+               </para>
+               <para>
+               The following control flow is implemented (simplified excerpt):
+               <programlisting>
+if (desc->status &amp; running) {
+       desc->chip->hold();
+       desc->status |= pending | masked;
+       return;
+}
+desc->chip->start();
+desc->status |= running;
+do {
+       if (desc->status &amp; masked)
+               desc->chip->enable();
+       desc-status &amp;= ~pending;
+       handle_IRQ_event(desc->action);
+} while (status &amp; pending);
+desc-status &amp;= ~running;
+desc->chip->end();
+               </programlisting>
+               </para>
+           </sect3>
+           <sect3>
+               <title>Default simple IRQ flow handler</title>
+               <para>
+               handle_simple_irq provides a generic implementation
+               for simple interrupts.
+               </para>
+               <para>
+               Note: The simple flow handler does not call any
+               handler/chip primitives.
+               </para>
+               <para>
+               The following control flow is implemented (simplified excerpt):
+               <programlisting>
+handle_IRQ_event(desc->action);
+               </programlisting>
+               </para>
+           </sect3>
+           <sect3>
+               <title>Default per CPU flow handler</title>
+               <para>
+               handle_percpu_irq provides a generic implementation
+               for per CPU interrupts.
+               </para>
+               <para>
+               Per CPU interrupts are only available on SMP and
+               the handler provides a simplified version without
+               locking.
+               </para>
+               <para>
+               The following control flow is implemented (simplified excerpt):
+               <programlisting>
+desc->chip->start();
+handle_IRQ_event(desc->action);
+desc->chip->end();
+               </programlisting>
+               </para>
+           </sect3>
+       </sect2>
+       <sect2>
+       <title>Quirks and optimizations</title>
+       <para>
+       The generic functions are intended for 'clean' architectures and chips,
+       which have no platform-specific IRQ handling quirks. If an architecture
+       needs to implement quirks on the 'flow' level then it can do so by
+       overriding the highlevel irq-flow handler.
+       </para>
+       </sect2>
+       <sect2>
+       <title>Delayed interrupt disable</title>
+       <para>
+       This per interrupt selectable feature, which was introduced by Russell
+       King in the ARM interrupt implementation, does not mask an interrupt
+       at the hardware level when disable_irq() is called. The interrupt is
+       kept enabled and is masked in the flow handler when an interrupt event
+       happens. This prevents losing edge interrupts on hardware which does
+       not store an edge interrupt event while the interrupt is disabled at
+       the hardware level. When an interrupt arrives while the IRQ_DISABLED
+       flag is set, then the interrupt is masked at the hardware level and
+       the IRQ_PENDING bit is set. When the interrupt is re-enabled by
+       enable_irq() the pending bit is checked and if it is set, the
+       interrupt is resent either via hardware or by a software resend
+       mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when
+       you want to use the delayed interrupt disable feature and your
+       hardware is not capable of retriggering an interrupt.)
+       The delayed interrupt disable can be runtime enabled, per interrupt,
+       by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field.
+       </para>
+       </sect2>
+    </sect1>
+    <sect1>
+       <title>Chiplevel hardware encapsulation</title>
+       <para>
+       The chip level hardware descriptor structure irq_chip
+       contains all the direct chip relevant functions, which
+       can be utilized by the irq flow implementations.
+         <itemizedlist>
+         <listitem><para>ack()</para></listitem>
+         <listitem><para>mask_ack() - Optional, recommended for performance</para></listitem>
+         <listitem><para>mask()</para></listitem>
+         <listitem><para>unmask()</para></listitem>
+         <listitem><para>retrigger() - Optional</para></listitem>
+         <listitem><para>set_type() - Optional</para></listitem>
+         <listitem><para>set_wake() - Optional</para></listitem>
+         </itemizedlist>
+       These primitives are strictly intended to mean what they say: ack means
+       ACK, masking means masking of an IRQ line, etc. It is up to the flow
+       handler(s) to use these basic units of lowlevel functionality.
+       </para>
+    </sect1>
+  </chapter>
+
+  <chapter id="doirq">
+     <title>__do_IRQ entry point</title>
+     <para>
+       The original implementation __do_IRQ() is an alternative entry
+       point for all types of interrupts.
+     </para>
+     <para>
+       This handler turned out to be not suitable for all
+       interrupt hardware and was therefore reimplemented with split
+       functionality for egde/level/simple/percpu interrupts. This is not
+       only a functional optimization. It also shortens code paths for
+       interrupts.
+      </para>
+      <para>
+       To make use of the split implementation, replace the call to
+       __do_IRQ by a call to desc->chip->handle_irq() and associate
+        the appropriate handler function to desc->chip->handle_irq().
+       In most cases the generic handler implementations should
+       be sufficient.
+     </para>
+  </chapter>
+
+  <chapter id="locking">
+     <title>Locking on SMP</title>
+     <para>
+       The locking of chip registers is up to the architecture that
+       defines the chip primitives. There is a chip->lock field that can be used
+       for serialization, but the generic layer does not touch it. The per-irq
+       structure is protected via desc->lock, by the generic layer.
+     </para>
+  </chapter>
+  <chapter id="structs">
+     <title>Structures</title>
+     <para>
+     This chapter contains the autogenerated documentation of the structures which are
+     used in the generic IRQ layer.
+     </para>
+!Iinclude/linux/irq.h
+  </chapter>
+
+  <chapter id="pubfunctions">
+     <title>Public Functions Provided</title>
+     <para>
+     This chapter contains the autogenerated documentation of the kernel API functions
+      which are exported.
+     </para>
+!Ekernel/irq/manage.c
+!Ekernel/irq/chip.c
+  </chapter>
+
+  <chapter id="intfunctions">
+     <title>Internal Functions Provided</title>
+     <para>
+     This chapter contains the autogenerated documentation of the internal functions.
+     </para>
+!Ikernel/irq/handle.c
+!Ikernel/irq/chip.c
+  </chapter>
+
+  <chapter id="credits">
+     <title>Credits</title>
+       <para>
+               The following people have contributed to this document:
+               <orderedlist>
+                       <listitem><para>Thomas Gleixner<email>tglx@linutronix.de</email></para></listitem>
+                       <listitem><para>Ingo Molnar<email>mingo@elte.hu</email></para></listitem>
+               </orderedlist>
+       </para>
+  </chapter>
+</book>
diff --git a/Documentation/IRQ.txt b/Documentation/IRQ.txt
new file mode 100644 (file)
index 0000000..1011e71
--- /dev/null
@@ -0,0 +1,22 @@
+What is an IRQ?
+
+An IRQ is an interrupt request from a device.
+Currently they can come in over a pin, or over a packet.
+Several devices may be connected to the same pin thus
+sharing an IRQ.
+
+An IRQ number is a kernel identifier used to talk about a hardware
+interrupt source.  Typically this is an index into the global irq_desc
+array, but except for what linux/interrupt.h implements the details
+are architecture specific.
+
+An IRQ number is an enumeration of the possible interrupt sources on a
+machine.  Typically what is enumerated is the number of input pins on
+all of the interrupt controller in the system.  In the case of ISA
+what is enumerated are the 16 input pins on the two i8259 interrupt
+controllers.
+
+Architectures can assign additional meaning to the IRQ numbers, and
+are encouraged to in the case  where there is any manual configuration
+of the hardware involved.  The ISA IRQs are a classic example of
+assigning this kind of additional meaning.
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
new file mode 100644 (file)
index 0000000..a10bfb6
--- /dev/null
@@ -0,0 +1,63 @@
+Linux Kernel patch sumbittal checklist
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here are some basic things that developers should do if they want to see their
+kernel patch submissions accepted more quickly.
+
+These are all above and beyond the documentation that is provided in
+Documentation/SubmittingPatches and elsewhere regarding submitting Linux
+kernel patches.
+
+
+
+1: Builds cleanly with applicable or modified CONFIG options =y, =m, and
+   =n.  No gcc warnings/errors, no linker warnings/errors.
+
+2: Passes allnoconfig, allmodconfig
+
+3: Builds on multiple CPU architectures by using local cross-compile tools
+   or something like PLM at OSDL.
+
+4: ppc64 is a good architecture for cross-compilation checking because it
+   tends to use `unsigned long' for 64-bit quantities.
+
+5: Matches kernel coding style(!)
+
+6: Any new or modified CONFIG options don't muck up the config menu.
+
+7: All new Kconfig options have help text.
+
+8: Has been carefully reviewed with respect to relevant Kconfig
+   combinations.  This is very hard to get right with testing -- brainpower
+   pays off here.
+
+9: Check cleanly with sparse.
+
+10: Use 'make checkstack' and 'make namespacecheck' and fix any problems
+    that they find.  Note: checkstack does not point out problems explicitly,
+    but any one function that uses more than 512 bytes on the stack is a
+    candidate for change.
+
+11: Include kernel-doc to document global kernel APIs.  (Not required for
+    static functions, but OK there also.) Use 'make htmldocs' or 'make
+    mandocs' to check the kernel-doc and fix any issues.
+
+12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
+    CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
+    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP all simultaneously
+    enabled.
+
+13: Has been build- and runtime tested with and without CONFIG_SMP and
+    CONFIG_PREEMPT.
+
+14: If the patch affects IO/Disk, etc: has been tested with and without
+    CONFIG_LBD.
+
+15: All codepaths have been exercised with all lockdep features enabled.
+
+16: All new /proc entries are documented under Documentation/
+
+17: All new kernel boot parameters are documented in
+    Documentation/kernel-parameters.txt.
+
+18: All new module parameters are documented with MODULE_PARM_DESC()
diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt
new file mode 100644 (file)
index 0000000..1443cd7
--- /dev/null
@@ -0,0 +1,112 @@
+Delay accounting
+----------------
+
+Tasks encounter delays in execution when they wait
+for some kernel resource to become available e.g. a
+runnable task may wait for a free CPU to run on.
+
+The per-task delay accounting functionality measures
+the delays experienced by a task while
+
+a) waiting for a CPU (while being runnable)
+b) completion of synchronous block I/O initiated by the task
+c) swapping in pages
+
+and makes these statistics available to userspace through
+the taskstats interface.
+
+Such delays provide feedback for setting a task's cpu priority,
+io priority and rss limit values appropriately. Long delays for
+important tasks could be a trigger for raising its corresponding priority.
+
+The functionality, through its use of the taskstats interface, also provides
+delay statistics aggregated for all tasks (or threads) belonging to a
+thread group (corresponding to a traditional Unix process). This is a commonly
+needed aggregation that is more efficiently done by the kernel.
+
+Userspace utilities, particularly resource management applications, can also
+aggregate delay statistics into arbitrary groups. To enable this, delay
+statistics of a task are available both during its lifetime as well as on its
+exit, ensuring continuous and complete monitoring can be done.
+
+
+Interface
+---------
+
+Delay accounting uses the taskstats interface which is described
+in detail in a separate document in this directory. Taskstats returns a
+generic data structure to userspace corresponding to per-pid and per-tgid
+statistics. The delay accounting functionality populates specific fields of
+this structure. See
+     include/linux/taskstats.h
+for a description of the fields pertaining to delay accounting.
+It will generally be in the form of counters returning the cumulative
+delay seen for cpu, sync block I/O, swapin etc.
+
+Taking the difference of two successive readings of a given
+counter (say cpu_delay_total) for a task will give the delay
+experienced by the task waiting for the corresponding resource
+in that interval.
+
+When a task exits, records containing the per-task statistics
+are sent to userspace without requiring a command. If it is the last exiting
+task of a thread group, the per-tgid statistics are also sent. More details
+are given in the taskstats interface description.
+
+The getdelays.c userspace utility in this directory allows simple commands to
+be run and the corresponding delay statistics to be displayed. It also serves
+as an example of using the taskstats interface.
+
+Usage
+-----
+
+Compile the kernel with
+       CONFIG_TASK_DELAY_ACCT=y
+       CONFIG_TASKSTATS=y
+
+Delay accounting is enabled by default at boot up.
+To disable, add
+   nodelayacct
+to the kernel boot options. The rest of the instructions
+below assume this has not been done.
+
+After the system has booted up, use a utility
+similar to  getdelays.c to access the delays
+seen by a given task or a task group (tgid).
+The utility also allows a given command to be
+executed and the corresponding delays to be
+seen.
+
+General format of the getdelays command
+
+getdelays [-t tgid] [-p pid] [-c cmd...]
+
+
+Get delays, since system boot, for pid 10
+# ./getdelays -p 10
+(output similar to next case)
+
+Get sum of delays, since system boot, for all pids with tgid 5
+# ./getdelays -t 5
+
+
+CPU    count   real total      virtual total   delay total
+       7876    92005750        100000000       24001500
+IO     count   delay total
+       0       0
+MEM    count   delay total
+       0       0
+
+Get delays seen in executing a given simple command
+# ./getdelays -c ls /
+
+bin   data1  data3  data5  dev  home  media  opt   root  srv        sys  usr
+boot  data2  data4  data6  etc  lib   mnt    proc  sbin  subdomain  tmp  var
+
+
+CPU    count   real total      virtual total   delay total
+       6       4000250         4000000         0
+IO     count   delay total
+       0       0
+MEM    count   delay total
+       0       0
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
new file mode 100644 (file)
index 0000000..795ca39
--- /dev/null
@@ -0,0 +1,396 @@
+/* getdelays.c
+ *
+ * Utility to get per-pid and per-tgid delay accounting statistics
+ * Also illustrates usage of the taskstats interface
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2005
+ * Copyright (C) Balbir Singh, IBM Corp. 2006
+ * Copyright (c) Jay Lan, SGI. 2006
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <linux/genetlink.h>
+#include <linux/taskstats.h>
+
+/*
+ * Generic macros for dealing with netlink sockets. Might be duplicated
+ * elsewhere. It is recommended that commercial grade applications use
+ * libnl or libnetlink and use the interfaces provided by the library
+ */
+#define GENLMSG_DATA(glh)      ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
+#define GENLMSG_PAYLOAD(glh)   (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
+#define NLA_DATA(na)           ((void *)((char*)(na) + NLA_HDRLEN))
+#define NLA_PAYLOAD(len)       (len - NLA_HDRLEN)
+
+#define err(code, fmt, arg...) do { printf(fmt, ##arg); exit(code); } while (0)
+int done = 0;
+int rcvbufsz=0;
+
+    char name[100];
+int dbg=0, print_delays=0;
+__u64 stime, utime;
+#define PRINTF(fmt, arg...) {                  \
+           if (dbg) {                          \
+               printf(fmt, ##arg);             \
+           }                                   \
+       }
+
+/* Maximum size of response requested or message sent */
+#define MAX_MSG_SIZE   256
+/* Maximum number of cpus expected to be specified in a cpumask */
+#define MAX_CPUS       32
+/* Maximum length of pathname to log file */
+#define MAX_FILENAME   256
+
+struct msgtemplate {
+       struct nlmsghdr n;
+       struct genlmsghdr g;
+       char buf[MAX_MSG_SIZE];
+};
+
+char cpumask[100+6*MAX_CPUS];
+
+/*
+ * Create a raw netlink socket and bind
+ */
+static int create_nl_socket(int protocol)
+{
+       int fd;
+       struct sockaddr_nl local;
+
+       fd = socket(AF_NETLINK, SOCK_RAW, protocol);
+       if (fd < 0)
+               return -1;
+
+       if (rcvbufsz)
+               if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
+                               &rcvbufsz, sizeof(rcvbufsz)) < 0) {
+                       printf("Unable to set socket rcv buf size to %d\n",
+                              rcvbufsz);
+                       return -1;
+               }
+
+       memset(&local, 0, sizeof(local));
+       local.nl_family = AF_NETLINK;
+
+       if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
+               goto error;
+
+       return fd;
+error:
+       close(fd);
+       return -1;
+}
+
+
+int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
+            __u8 genl_cmd, __u16 nla_type,
+            void *nla_data, int nla_len)
+{
+       struct nlattr *na;
+       struct sockaddr_nl nladdr;
+       int r, buflen;
+       char *buf;
+
+       struct msgtemplate msg;
+
+       msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+       msg.n.nlmsg_type = nlmsg_type;
+       msg.n.nlmsg_flags = NLM_F_REQUEST;
+       msg.n.nlmsg_seq = 0;
+       msg.n.nlmsg_pid = nlmsg_pid;
+       msg.g.cmd = genl_cmd;
+       msg.g.version = 0x1;
+       na = (struct nlattr *) GENLMSG_DATA(&msg);
+       na->nla_type = nla_type;
+       na->nla_len = nla_len + 1 + NLA_HDRLEN;
+       memcpy(NLA_DATA(na), nla_data, nla_len);
+       msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+
+       buf = (char *) &msg;
+       buflen = msg.n.nlmsg_len ;
+       memset(&nladdr, 0, sizeof(nladdr));
+       nladdr.nl_family = AF_NETLINK;
+       while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr,
+                          sizeof(nladdr))) < buflen) {
+               if (r > 0) {
+                       buf += r;
+                       buflen -= r;
+               } else if (errno != EAGAIN)
+                       return -1;
+       }
+       return 0;
+}
+
+
+/*
+ * Probe the controller in genetlink to find the family id
+ * for the TASKSTATS family
+ */
+int get_family_id(int sd)
+{
+       struct {
+               struct nlmsghdr n;
+               struct genlmsghdr g;
+               char buf[256];
+       } ans;
+
+       int id, rc;
+       struct nlattr *na;
+       int rep_len;
+
+       strcpy(name, TASKSTATS_GENL_NAME);
+       rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY,
+                       CTRL_ATTR_FAMILY_NAME, (void *)name,
+                       strlen(TASKSTATS_GENL_NAME)+1);
+
+       rep_len = recv(sd, &ans, sizeof(ans), 0);
+       if (ans.n.nlmsg_type == NLMSG_ERROR ||
+           (rep_len < 0) || !NLMSG_OK((&ans.n), rep_len))
+               return 0;
+
+       na = (struct nlattr *) GENLMSG_DATA(&ans);
+       na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
+       if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
+               id = *(__u16 *) NLA_DATA(na);
+       }
+       return id;
+}
+
+void print_delayacct(struct taskstats *t)
+{
+       printf("\n\nCPU   %15s%15s%15s%15s\n"
+              "      %15llu%15llu%15llu%15llu\n"
+              "IO    %15s%15s\n"
+              "      %15llu%15llu\n"
+              "MEM   %15s%15s\n"
+              "      %15llu%15llu\n\n",
+              "count", "real total", "virtual total", "delay total",
+              t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
+              t->cpu_delay_total,
+              "count", "delay total",
+              t->blkio_count, t->blkio_delay_total,
+              "count", "delay total", t->swapin_count, t->swapin_delay_total);
+}
+
+int main(int argc, char *argv[])
+{
+       int c, rc, rep_len, aggr_len, len2, cmd_type;
+       __u16 id;
+       __u32 mypid;
+
+       struct nlattr *na;
+       int nl_sd = -1;
+       int len = 0;
+       pid_t tid = 0;
+       pid_t rtid = 0;
+
+       int fd = 0;
+       int count = 0;
+       int write_file = 0;
+       int maskset = 0;
+       char logfile[128];
+       int loop = 0;
+
+       struct msgtemplate msg;
+
+       while (1) {
+               c = getopt(argc, argv, "dw:r:m:t:p:v:l");
+               if (c < 0)
+                       break;
+
+               switch (c) {
+               case 'd':
+                       printf("print delayacct stats ON\n");
+                       print_delays = 1;
+                       break;
+               case 'w':
+                       strncpy(logfile, optarg, MAX_FILENAME);
+                       printf("write to file %s\n", logfile);
+                       write_file = 1;
+                       break;
+               case 'r':
+                       rcvbufsz = atoi(optarg);
+                       printf("receive buf size %d\n", rcvbufsz);
+                       if (rcvbufsz < 0)
+                               err(1, "Invalid rcv buf size\n");
+                       break;
+               case 'm':
+                       strncpy(cpumask, optarg, sizeof(cpumask));
+                       maskset = 1;
+                       printf("cpumask %s maskset %d\n", cpumask, maskset);
+                       break;
+               case 't':
+                       tid = atoi(optarg);
+                       if (!tid)
+                               err(1, "Invalid tgid\n");
+                       cmd_type = TASKSTATS_CMD_ATTR_TGID;
+                       print_delays = 1;
+                       break;
+               case 'p':
+                       tid = atoi(optarg);
+                       if (!tid)
+                               err(1, "Invalid pid\n");
+                       cmd_type = TASKSTATS_CMD_ATTR_PID;
+                       print_delays = 1;
+                       break;
+               case 'v':
+                       printf("debug on\n");
+                       dbg = 1;
+                       break;
+               case 'l':
+                       printf("listen forever\n");
+                       loop = 1;
+                       break;
+               default:
+                       printf("Unknown option %d\n", c);
+                       exit(-1);
+               }
+       }
+
+       if (write_file) {
+               fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC,
+                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+               if (fd == -1) {
+                       perror("Cannot open output file\n");
+                       exit(1);
+               }
+       }
+
+       if ((nl_sd = create_nl_socket(NETLINK_GENERIC)) < 0)
+               err(1, "error creating Netlink socket\n");
+
+
+       mypid = getpid();
+       id = get_family_id(nl_sd);
+       if (!id) {
+               printf("Error getting family id, errno %d", errno);
+               goto err;
+       }
+       PRINTF("family id %d\n", id);
+
+       if (maskset) {
+               rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
+                             TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
+                             &cpumask, sizeof(cpumask));
+               PRINTF("Sent register cpumask, retval %d\n", rc);
+               if (rc < 0) {
+                       printf("error sending register cpumask\n");
+                       goto err;
+               }
+       }
+
+       if (tid) {
+               rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
+                             cmd_type, &tid, sizeof(__u32));
+               PRINTF("Sent pid/tgid, retval %d\n", rc);
+               if (rc < 0) {
+                       printf("error sending tid/tgid cmd\n");
+                       goto done;
+               }
+       }
+
+       do {
+               int i;
+
+               rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
+               PRINTF("received %d bytes\n", rep_len);
+
+               if (rep_len < 0) {
+                       printf("nonfatal reply error: errno %d\n", errno);
+                       continue;
+               }
+               if (msg.n.nlmsg_type == NLMSG_ERROR ||
+                   !NLMSG_OK((&msg.n), rep_len)) {
+                       printf("fatal reply error,  errno %d\n", errno);
+                       goto done;
+               }
+
+               PRINTF("nlmsghdr size=%d, nlmsg_len=%d, rep_len=%d\n",
+                      sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);
+
+
+               rep_len = GENLMSG_PAYLOAD(&msg.n);
+
+               na = (struct nlattr *) GENLMSG_DATA(&msg);
+               len = 0;
+               i = 0;
+               while (len < rep_len) {
+                       len += NLA_ALIGN(na->nla_len);
+                       switch (na->nla_type) {
+                       case TASKSTATS_TYPE_AGGR_TGID:
+                               /* Fall through */
+                       case TASKSTATS_TYPE_AGGR_PID:
+                               aggr_len = NLA_PAYLOAD(na->nla_len);
+                               len2 = 0;
+                               /* For nested attributes, na follows */
+                               na = (struct nlattr *) NLA_DATA(na);
+                               done = 0;
+                               while (len2 < aggr_len) {
+                                       switch (na->nla_type) {
+                                       case TASKSTATS_TYPE_PID:
+                                               rtid = *(int *) NLA_DATA(na);
+                                               if (print_delays)
+                                                       printf("PID\t%d\n", rtid);
+                                               break;
+                                       case TASKSTATS_TYPE_TGID:
+                                               rtid = *(int *) NLA_DATA(na);
+                                               if (print_delays)
+                                                       printf("TGID\t%d\n", rtid);
+                                               break;
+                                       case TASKSTATS_TYPE_STATS:
+                                               count++;
+                                               if (print_delays)
+                                                       print_delayacct((struct taskstats *) NLA_DATA(na));
+                                               if (fd) {
+                                                       if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
+                                                               err(1,"write error\n");
+                                                       }
+                                               }
+                                               if (!loop)
+                                                       goto done;
+                                               break;
+                                       default:
+                                               printf("Unknown nested nla_type %d\n", na->nla_type);
+                                               break;
+                                       }
+                                       len2 += NLA_ALIGN(na->nla_len);
+                                       na = (struct nlattr *) ((char *) na + len2);
+                               }
+                               break;
+
+                       default:
+                               printf("Unknown nla_type %d\n", na->nla_type);
+                               break;
+                       }
+                       na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
+               }
+       } while (loop);
+done:
+       if (maskset) {
+               rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
+                             TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
+                             &cpumask, sizeof(cpumask));
+               printf("Sent deregister mask, retval %d\n", rc);
+               if (rc < 0)
+                       err(rc, "error sending deregister cpumask\n");
+       }
+err:
+       close(nl_sd);
+       if (fd)
+               close(fd);
+       return 0;
+}
diff --git a/Documentation/accounting/taskstats.txt b/Documentation/accounting/taskstats.txt
new file mode 100644 (file)
index 0000000..92ebf29
--- /dev/null
@@ -0,0 +1,181 @@
+Per-task statistics interface
+-----------------------------
+
+
+Taskstats is a netlink-based interface for sending per-task and
+per-process statistics from the kernel to userspace.
+
+Taskstats was designed for the following benefits:
+
+- efficiently provide statistics during lifetime of a task and on its exit
+- unified interface for multiple accounting subsystems
+- extensibility for use by future accounting patches
+
+Terminology
+-----------
+
+"pid", "tid" and "task" are used interchangeably and refer to the standard
+Linux task defined by struct task_struct.  per-pid stats are the same as
+per-task stats.
+
+"tgid", "process" and "thread group" are used interchangeably and refer to the
+tasks that share an mm_struct i.e. the traditional Unix process. Despite the
+use of tgid, there is no special treatment for the task that is thread group
+leader - a process is deemed alive as long as it has any task belonging to it.
+
+Usage
+-----
+
+To get statistics during a task's lifetime, userspace opens a unicast netlink
+socket (NETLINK_GENERIC family) and sends commands specifying a pid or a tgid.
+The response contains statistics for a task (if pid is specified) or the sum of
+statistics for all tasks of the process (if tgid is specified).
+
+To obtain statistics for tasks which are exiting, the userspace listener
+sends a register command and specifies a cpumask. Whenever a task exits on
+one of the cpus in the cpumask, its per-pid statistics are sent to the
+registered listener. Using cpumasks allows the data received by one listener
+to be limited and assists in flow control over the netlink interface and is
+explained in more detail below.
+
+If the exiting task is the last thread exiting its thread group,
+an additional record containing the per-tgid stats is also sent to userspace.
+The latter contains the sum of per-pid stats for all threads in the thread
+group, both past and present.
+
+getdelays.c is a simple utility demonstrating usage of the taskstats interface
+for reporting delay accounting statistics. Users can register cpumasks,
+send commands and process responses, listen for per-tid/tgid exit data,
+write the data received to a file and do basic flow control by increasing
+receive buffer sizes.
+
+Interface
+---------
+
+The user-kernel interface is encapsulated in include/linux/taskstats.h
+
+To avoid this documentation becoming obsolete as the interface evolves, only
+an outline of the current version is given. taskstats.h always overrides the
+description here.
+
+struct taskstats is the common accounting structure for both per-pid and
+per-tgid data. It is versioned and can be extended by each accounting subsystem
+that is added to the kernel. The fields and their semantics are defined in the
+taskstats.h file.
+
+The data exchanged between user and kernel space is a netlink message belonging
+to the NETLINK_GENERIC family and using the netlink attributes interface.
+The messages are in the format
+
+    +----------+- - -+-------------+-------------------+
+    | nlmsghdr | Pad |  genlmsghdr | taskstats payload |
+    +----------+- - -+-------------+-------------------+
+
+
+The taskstats payload is one of the following three kinds:
+
+1. Commands: Sent from user to kernel. Commands to get data on
+a pid/tgid consist of one attribute, of type TASKSTATS_CMD_ATTR_PID/TGID,
+containing a u32 pid or tgid in the attribute payload. The pid/tgid denotes
+the task/process for which userspace wants statistics.
+
+Commands to register/deregister interest in exit data from a set of cpus
+consist of one attribute, of type
+TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK and contain a cpumask in the
+attribute payload. The cpumask is specified as an ascii string of
+comma-separated cpu ranges e.g. to listen to exit data from cpus 1,2,3,5,7,8
+the cpumask would be "1-3,5,7-8". If userspace forgets to deregister interest
+in cpus before closing the listening socket, the kernel cleans up its interest
+set over time. However, for the sake of efficiency, an explicit deregistration
+is advisable.
+
+2. Response for a command: sent from the kernel in response to a userspace
+command. The payload is a series of three attributes of type:
+
+a) TASKSTATS_TYPE_AGGR_PID/TGID : attribute containing no payload but indicates
+a pid/tgid will be followed by some stats.
+
+b) TASKSTATS_TYPE_PID/TGID: attribute whose payload is the pid/tgid whose stats
+is being returned.
+
+c) TASKSTATS_TYPE_STATS: attribute with a struct taskstsats as payload. The
+same structure is used for both per-pid and per-tgid stats.
+
+3. New message sent by kernel whenever a task exits. The payload consists of a
+   series of attributes of the following type:
+
+a) TASKSTATS_TYPE_AGGR_PID: indicates next two attributes will be pid+stats
+b) TASKSTATS_TYPE_PID: contains exiting task's pid
+c) TASKSTATS_TYPE_STATS: contains the exiting task's per-pid stats
+d) TASKSTATS_TYPE_AGGR_TGID: indicates next two attributes will be tgid+stats
+e) TASKSTATS_TYPE_TGID: contains tgid of process to which task belongs
+f) TASKSTATS_TYPE_STATS: contains the per-tgid stats for exiting task's process
+
+
+per-tgid stats
+--------------
+
+Taskstats provides per-process stats, in addition to per-task stats, since
+resource management is often done at a process granularity and aggregating task
+stats in userspace alone is inefficient and potentially inaccurate (due to lack
+of atomicity).
+
+However, maintaining per-process, in addition to per-task stats, within the
+kernel has space and time overheads. To address this, the taskstats code
+accumalates each exiting task's statistics into a process-wide data structure.
+When the last task of a process exits, the process level data accumalated also
+gets sent to userspace (along with the per-task data).
+
+When a user queries to get per-tgid data, the sum of all other live threads in
+the group is added up and added to the accumalated total for previously exited
+threads of the same thread group.
+
+Extending taskstats
+-------------------
+
+There are two ways to extend the taskstats interface to export more
+per-task/process stats as patches to collect them get added to the kernel
+in future:
+
+1. Adding more fields to the end of the existing struct taskstats. Backward
+   compatibility is ensured by the version number within the
+   structure. Userspace will use only the fields of the struct that correspond
+   to the version its using.
+
+2. Defining separate statistic structs and using the netlink attributes
+   interface to return them. Since userspace processes each netlink attribute
+   independently, it can always ignore attributes whose type it does not
+   understand (because it is using an older version of the interface).
+
+
+Choosing between 1. and 2. is a matter of trading off flexibility and
+overhead. If only a few fields need to be added, then 1. is the preferable
+path since the kernel and userspace don't need to incur the overhead of
+processing new netlink attributes. But if the new fields expand the existing
+struct too much, requiring disparate userspace accounting utilities to
+unnecessarily receive large structures whose fields are of no interest, then
+extending the attributes structure would be worthwhile.
+
+Flow control for taskstats
+--------------------------
+
+When the rate of task exits becomes large, a listener may not be able to keep
+up with the kernel's rate of sending per-tid/tgid exit data leading to data
+loss. This possibility gets compounded when the taskstats structure gets
+extended and the number of cpus grows large.
+
+To avoid losing statistics, userspace should do one or more of the following:
+
+- increase the receive buffer sizes for the netlink sockets opened by
+listeners to receive exit data.
+
+- create more listeners and reduce the number of cpus being listened to by
+each listener. In the extreme case, there could be one listener for each cpu.
+Users may also consider setting the cpu affinity of the listener to the subset
+of cpus to which it listens, especially if they are listening to just one cpu.
+
+Despite these measures, if the userspace receives ENOBUFS error messages
+indicated overflow of receive buffers, it should take measures to handle the
+loss of data.
+
+----
diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2412.txt b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt
new file mode 100644 (file)
index 0000000..cb82a7f
--- /dev/null
@@ -0,0 +1,120 @@
+               S3C2412 ARM Linux Overview
+               ==========================
+
+Introduction
+------------
+
+  The S3C2412 is part of the S3C24XX range of ARM9 System-on-Chip CPUs
+  from Samsung. This part has an ARM926-EJS core, capable of running up
+  to 266MHz (see data-sheet for more information)
+
+
+Clock
+-----
+
+  The core clock code provides a set of clocks to the drivers, and allows
+  for source selection and a number of other features.
+
+
+Power
+-----
+
+  No support for suspend/resume to RAM in the current system.
+
+
+DMA
+---
+
+  No current support for DMA.
+
+
+GPIO
+----
+
+  There is support for setting the GPIO to input/output/special function
+  and reading or writing to them.
+
+
+UART
+----
+
+  The UART hardware is similar to the S3C2440, and is supported by the
+  s3c2410 driver in the drivers/serial directory.
+
+
+NAND
+----
+
+  The NAND hardware is similar to the S3C2440, and is supported by the
+  s3c2410 driver in the drivers/mtd/nand directory.
+
+
+USB Host
+--------
+
+  The USB hardware is similar to the S3C2410, with extended clock source
+  control. The OHCI portion is supported by the ohci-s3c2410 driver, and
+  the clock control selection is supported by the core clock code.
+
+
+USB Device
+----------
+
+  No current support in the kernel
+
+
+IRQs
+----
+
+  All the standard, and external interrupt sources are supported. The
+  extra sub-sources are not yet supported.
+
+
+RTC
+---
+
+  The RTC hardware is similar to the S3C2410, and is supported by the
+  s3c2410-rtc driver.
+
+
+Watchdog
+--------
+
+  The watchdog harware is the same as the S3C2410, and is supported by
+  the s3c2410_wdt driver.
+
+
+MMC/SD/SDIO
+-----------
+
+  No current support for the MMC/SD/SDIO block.
+
+IIC
+---
+
+  The IIC hardware is the same as the S3C2410, and is supported by the
+  i2c-s3c24xx driver.
+
+
+IIS
+---
+
+  No current support for the IIS interface.
+
+
+SPI
+---
+
+  No current support for the SPI interfaces.
+
+
+ATA
+---
+
+  No current support for the on-board ATA block.
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2006 Simtec Electronics
diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2413.txt b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt
new file mode 100644 (file)
index 0000000..ab2a888
--- /dev/null
@@ -0,0 +1,21 @@
+               S3C2413 ARM Linux Overview
+               ==========================
+
+Introduction
+------------
+
+  The S3C2413 is an extended version of the S3C2412, with an camera
+  interface and mobile DDR memory support. See the S3C2412 support
+  documentation for more information.
+
+
+Camera Interface
+---------------
+
+  This block is currently not supported.
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2006 Simtec Electronics
diff --git a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
new file mode 100644 (file)
index 0000000..1e6a23f
--- /dev/null
@@ -0,0 +1,61 @@
+README on the ADC/Touchscreen Controller
+========================================
+
+The LH79524 and LH7A404 include a built-in Analog to Digital
+controller (ADC) that is used to process input from a touchscreen.
+The driver only implements a four-wire touch panel protocol.
+
+The touchscreen driver is maintenance free except for the pen-down or
+touch threshold.  Some resistive displays and board combinations may
+require tuning of this threshold.  The driver exposes some of it's
+internal state in the sys filesystem.  If the kernel is configured
+with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a
+directory
+
+  /sys/devices/platform/adc-lh7.0
+
+containing these files.
+
+  -r--r--r--    1 root     root         4096 Jan  1 00:00 samples
+  -rw-r--r--    1 root     root         4096 Jan  1 00:00 threshold
+  -r--r--r--    1 root     root         4096 Jan  1 00:00 threshold_range
+
+The threshold is the current touch threshold.  It defaults to 750 on
+most targets.
+
+  # cat threshold
+ 750
+
+The threshold_range contains the range of valid values for the
+threshold.  Values outside of this range will be silently ignored.
+
+  # cat threshold_range
+  0 1023
+
+To change the threshold, write a value to the threshold file.
+
+  # echo 500 > threshold
+  # cat threshold
+  500
+
+The samples file contains the most recently sampled values from the
+ADC.  There are 12.  Below are typical of the last sampled values when
+the pen has been released.  The first two and last two samples are for
+detecting whether or not the pen is down.  The third through sixth are
+X coordinate samples.  The seventh through tenth are Y coordinate
+samples.
+
+  # cat samples
+  1023 1023 0 0 0 0 530 529 530 529 1023 1023
+
+To determine a reasonable threshold, press on the touch panel with an
+appropriate stylus and read the values from samples.
+
+  # cat samples
+  1023 676 92 103 101 102 855 919 922 922 1023 679
+
+The first and eleventh samples are discarded.  Thus, the important
+values are the second and twelfth which are used to determine if the
+pen is down.  When both are below the threshold, the driver registers
+that the pen is down.  When either is above the threshold, it
+registers then pen is up.
diff --git a/Documentation/arm/Sharp-LH/LCDPanels b/Documentation/arm/Sharp-LH/LCDPanels
new file mode 100644 (file)
index 0000000..fb1b21c
--- /dev/null
@@ -0,0 +1,59 @@
+README on the LCD Panels
+========================
+
+Configuration options for several LCD panels, available from Logic PD,
+are included in the kernel source.  This README will help you
+understand the configuration data and give you some guidance for
+adding support for other panels if you wish.
+
+
+lcd-panels.h
+------------
+
+There is no way, at present, to detect which panel is attached to the
+system at runtime.  Thus the kernel configuration is static.  The file
+arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the
+panel specific parameters.
+
+It should be possible for this data to be shared among several device
+families.  The current layout may be insufficiently general, but it is
+amenable to improvement.
+
+
+PIXEL_CLOCK
+-----------
+
+The panel data sheets will give a range of acceptable pixel clocks.
+The fundamental LCDCLK input frequency is divided down by a PCD
+constant in field '.tim2'.  It may happen that it is impossible to set
+the pixel clock within this range.  A clock which is too slow will
+tend to flicker.  For the highest quality image, set the clock as high
+as possible.
+
+
+MARGINS
+-------
+
+These values may be difficult to glean from the panel data sheet.  In
+the case of the Sharp panels, the upper margin is explicitly called
+out as a specific number of lines from the top of the frame.  The
+other values may not matter as much as the panels tend to
+automatically center the image.
+
+
+Sync Sense
+----------
+
+The sense of the hsync and vsync pulses may be called out in the data
+sheet.  On one panel, the sense of these pulses determine the height
+of the visible region on the panel.  Most of the Sharp panels use
+negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in
+'.tim2'.
+
+
+Pel Layout
+----------
+
+The Sharp color TFT panels are all configured for 16 bit direct color
+modes.  The amba-lcd driver sets the pel mode to 565 for 5 bits of
+each red and blue and 6 bits of green.
diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c
new file mode 100644 (file)
index 0000000..d738cde
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *     ucon.c
+ *
+ * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/types.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include <linux/connector.h>
+
+#define DEBUG
+#define NETLINK_CONNECTOR      11
+
+#ifdef DEBUG
+#define ulog(f, a...) fprintf(stdout, f, ##a)
+#else
+#define ulog(f, a...) do {} while (0)
+#endif
+
+static int need_exit;
+static __u32 seq;
+
+static int netlink_send(int s, struct cn_msg *msg)
+{
+       struct nlmsghdr *nlh;
+       unsigned int size;
+       int err;
+       char buf[128];
+       struct cn_msg *m;
+
+       size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
+
+       nlh = (struct nlmsghdr *)buf;
+       nlh->nlmsg_seq = seq++;
+       nlh->nlmsg_pid = getpid();
+       nlh->nlmsg_type = NLMSG_DONE;
+       nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+       nlh->nlmsg_flags = 0;
+
+       m = NLMSG_DATA(nlh);
+#if 0
+       ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n",
+              __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack);
+#endif
+       memcpy(m, msg, sizeof(*m) + msg->len);
+
+       err = send(s, nlh, size, 0);
+       if (err == -1)
+               ulog("Failed to send: %s [%d].\n",
+                       strerror(errno), errno);
+
+       return err;
+}
+
+int main(int argc, char *argv[])
+{
+       int s;
+       char buf[1024];
+       int len;
+       struct nlmsghdr *reply;
+       struct sockaddr_nl l_local;
+       struct cn_msg *data;
+       FILE *out;
+       time_t tm;
+       struct pollfd pfd;
+
+       if (argc < 2)
+               out = stdout;
+       else {
+               out = fopen(argv[1], "a+");
+               if (!out) {
+                       ulog("Unable to open %s for writing: %s\n",
+                               argv[1], strerror(errno));
+                       out = stdout;
+               }
+       }
+
+       memset(buf, 0, sizeof(buf));
+
+       s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+       if (s == -1) {
+               perror("socket");
+               return -1;
+       }
+
+       l_local.nl_family = AF_NETLINK;
+       l_local.nl_groups = 0x123; /* bitmask of requested groups */
+       l_local.nl_pid = 0;
+
+       if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
+               perror("bind");
+               close(s);
+               return -1;
+       }
+
+#if 0
+       {
+               int on = 0x57; /* Additional group number */
+               setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
+       }
+#endif
+       if (0) {
+               int i, j;
+
+               memset(buf, 0, sizeof(buf));
+
+               data = (struct cn_msg *)buf;
+
+               data->id.idx = 0x123;
+               data->id.val = 0x456;
+               data->seq = seq++;
+               data->ack = 0;
+               data->len = 0;
+
+               for (j=0; j<10; ++j) {
+                       for (i=0; i<1000; ++i) {
+                               len = netlink_send(s, data);
+                       }
+
+                       ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val);
+               }
+
+               return 0;
+       }
+
+
+       pfd.fd = s;
+
+       while (!need_exit) {
+               pfd.events = POLLIN;
+               pfd.revents = 0;
+               switch (poll(&pfd, 1, -1)) {
+                       case 0:
+                               need_exit = 1;
+                               break;
+                       case -1:
+                               if (errno != EINTR) {
+                                       need_exit = 1;
+                                       break;
+                               }
+                               continue;
+               }
+               if (need_exit)
+                       break;
+
+               memset(buf, 0, sizeof(buf));
+               len = recv(s, buf, sizeof(buf), 0);
+               if (len == -1) {
+                       perror("recv buf");
+                       close(s);
+                       return -1;
+               }
+               reply = (struct nlmsghdr *)buf;
+
+               switch (reply->nlmsg_type) {
+               case NLMSG_ERROR:
+                       fprintf(out, "Error message received.\n");
+                       fflush(out);
+                       break;
+               case NLMSG_DONE:
+                       data = (struct cn_msg *)NLMSG_DATA(reply);
+
+                       time(&tm);
+                       fprintf(out, "%.24s : [%x.%x] [%08u.%08u].\n",
+                               ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack);
+                       fflush(out);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       close(s);
+       return 0;
+}
diff --git a/Documentation/console/console.txt b/Documentation/console/console.txt
new file mode 100644 (file)
index 0000000..d3e1744
--- /dev/null
@@ -0,0 +1,144 @@
+Console Drivers
+===============
+
+The linux kernel has 2 general types of console drivers.  The first type is
+assigned by the kernel to all the virtual consoles during the boot process.
+This type will be called 'system driver', and only one system driver is allowed
+to exist. The system driver is persistent and it can never be unloaded, though
+it may become inactive.
+
+The second type has to be explicitly loaded and unloaded. This will be called
+'modular driver' by this document. Multiple modular drivers can coexist at
+any time with each driver sharing the console with other drivers including
+the system driver. However, modular drivers cannot take over the console
+that is currently occupied by another modular driver. (Exception: Drivers that
+call take_over_console() will succeed in the takeover regardless of the type
+of driver occupying the consoles.) They can only take over the console that is
+occupied by the system driver. In the same token, if the modular driver is
+released by the console, the system driver will take over.
+
+Modular drivers, from the programmer's point of view, has to call:
+
+        take_over_console() - load and bind driver to console layer
+        give_up_console() - unbind and unload driver
+
+In newer kernels, the following are also available:
+
+        register_con_driver()
+        unregister_con_driver()
+
+If sysfs is enabled, the contents of /sys/class/vtconsole can be
+examined. This shows the console backends currently registered by the
+system which are named vtcon<n> where <n> is an integer fro 0 to 15. Thus:
+
+       ls /sys/class/vtconsole
+       .  ..  vtcon0  vtcon1
+
+Each directory in /sys/class/vtconsole has 3 files:
+
+     ls /sys/class/vtconsole/vtcon0
+     .  ..  bind  name  uevent
+
+What do these files signify?
+
+     1. bind - this is a read/write file. It shows the status of the driver if
+        read, or acts to bind or unbind the driver to the virtual consoles
+        when written to. The possible values are:
+
+       0 - means the driver is not bound and if echo'ed, commands the driver
+           to unbind
+
+        1 - means the driver is bound and if echo'ed, commands the driver to
+           bind
+
+     2. name - read-only file. Shows the name of the driver in this format:
+
+       cat /sys/class/vtconsole/vtcon0/name
+       (S) VGA+
+
+           '(S)' stands for a (S)ystem driver, ie, it cannot be directly
+           commanded to bind or unbind
+
+           'VGA+' is the name of the driver
+
+       cat /sys/class/vtconsole/vtcon1/name
+       (M) frame buffer device
+
+           In this case, '(M)' stands for a (M)odular driver, one that can be
+           directly commanded to bind or unbind.
+
+     3. uevent - ignore this file
+
+When unbinding, the modular driver is detached first, and then the system
+driver takes over the consoles vacated by the driver. Binding, on the other
+hand, will bind the driver to the consoles that are currently occupied by a
+system driver.
+
+NOTE1: Binding and binding must be selected in Kconfig. It's under:
+
+Device Drivers -> Character devices -> Support for binding and unbinding
+console drivers
+
+NOTE2: If any of the virtual consoles are in KD_GRAPHICS mode, then binding or
+unbinding will not succeed. An example of an application that sets the console
+to KD_GRAPHICS is X.
+
+How useful is this feature? This is very useful for console driver
+developers. By unbinding the driver from the console layer, one can unload the
+driver, make changes, recompile, reload and rebind the driver without any need
+for rebooting the kernel. For regular users who may want to switch from
+framebuffer console to VGA console and vice versa, this feature also makes
+this possible. (NOTE NOTE NOTE: Please read fbcon.txt under Documentation/fb
+for more details).
+
+Notes for developers:
+=====================
+
+take_over_console() is now broken up into:
+
+     register_con_driver()
+     bind_con_driver() - private function
+
+give_up_console() is a wrapper to unregister_con_driver(), and a driver must
+be fully unbound for this call to succeed. con_is_bound() will check if the
+driver is bound or not.
+
+Guidelines for console driver writers:
+=====================================
+
+In order for binding to and unbinding from the console to properly work,
+console drivers must follow these guidelines:
+
+1. All drivers, except system drivers, must call either register_con_driver()
+   or take_over_console(). register_con_driver() will just add the driver to
+   the console's internal list. It won't take over the
+   console. take_over_console(), as it name implies, will also take over (or
+   bind to) the console.
+
+2. All resources allocated during con->con_init() must be released in
+   con->con_deinit().
+
+3. All resources allocated in con->con_startup() must be released when the
+   driver, which was previously bound, becomes unbound.  The console layer
+   does not have a complementary call to con->con_startup() so it's up to the
+   driver to check when it's legal to release these resources. Calling
+   con_is_bound() in con->con_deinit() will help.  If the call returned
+   false(), then it's safe to release the resources.  This balance has to be
+   ensured because con->con_startup() can be called again when a request to
+   rebind the driver to the console arrives.
+
+4. Upon exit of the driver, ensure that the driver is totally unbound. If the
+   condition is satisfied, then the driver must call unregister_con_driver()
+   or give_up_console().
+
+5. unregister_con_driver() can also be called on conditions which make it
+   impossible for the driver to service console requests.  This can happen
+   with the framebuffer console that suddenly lost all of its drivers.
+
+The current crop of console drivers should still work correctly, but binding
+and unbinding them may cause problems. With minimal fixes, these drivers can
+be made to work correctly.
+
+==========================
+Antonino Daplas <adaplas@pol.net>
+
diff --git a/Documentation/fb/imacfb.txt b/Documentation/fb/imacfb.txt
new file mode 100644 (file)
index 0000000..7590285
--- /dev/null
@@ -0,0 +1,31 @@
+
+What is imacfb?
+===============
+
+This is a generic EFI platform driver for Intel based Apple computers.
+Imacfb is only for EFI booted Intel Macs.
+
+Supported Hardware
+==================
+
+iMac 17"/20"
+Macbook
+Macbook Pro 15"/17"
+MacMini
+
+How to use it?
+==============
+
+Imacfb does not have any kind of autodetection of your machine.
+You have to add the fillowing kernel parameters in your elilo.conf:
+       Macbook :
+               video=imacfb:macbook
+       MacMini :
+               video=imacfb:mini
+       Macbook Pro 15", iMac 17" :
+               video=imacfb:i17
+       Macbook Pro 17", iMac 20" :
+               video=imacfb:i20
+
+--
+Edgar Hucek <gimli@dark-green.com>
diff --git a/Documentation/filesystems/caching/backend-api.txt b/Documentation/filesystems/caching/backend-api.txt
new file mode 100644 (file)
index 0000000..1dd601b
--- /dev/null
@@ -0,0 +1,357 @@
+                         ==========================
+                         FS-CACHE CACHE BACKEND API
+                         ==========================
+
+The FS-Cache system provides an API by which actual caches can be supplied to
+FS-Cache for it to then serve out to network filesystems and other interested
+parties.
+
+This API is declared in <linux/fscache-cache.h>.
+
+
+====================================
+INITIALISING AND REGISTERING A CACHE
+====================================
+
+To start off, a cache definition must be initialised and registered for each
+cache the backend wants to make available.  For instance, CacheFS does this in
+the fill_super() operation on mounting.
+
+The cache definition (struct fscache_cache) should be initialised by calling:
+
+       void fscache_init_cache(struct fscache_cache *cache,
+                               struct fscache_cache_ops *ops,
+                               const char *idfmt,
+                               ...)
+
+Where:
+
+ (*) "cache" is a pointer to the cache definition;
+
+ (*) "ops" is a pointer to the table of operations that the backend supports on
+     this cache;
+
+ (*) and a format and printf-style arguments for constructing a label for the
+     cache.
+
+
+The cache should then be registered with FS-Cache by passing a pointer to the
+previously initialised cache definition to:
+
+       int fscache_add_cache(struct fscache_cache *cache,
+                             struct fscache_object *fsdef,
+                             const char *tagname);
+
+Two extra arguments should also be supplied:
+
+ (*) "fsdef" which should point to the object representation for the FS-Cache
+     master index in this cache.  Netfs primary index entries will be created
+     here.
+
+ (*) "tagname" which, if given, should be a text string naming this cache.  If
+     this is NULL, the identifier will be used instead.  For CacheFS, the
+     identifier is set to name the underlying block device and the tag can be
+     supplied by mount.
+
+This function may return -ENOMEM if it ran out of memory or -EEXIST if the tag
+is already in use.  0 will be returned on success.
+
+
+=====================
+UNREGISTERING A CACHE
+=====================
+
+A cache can be withdrawn from the system by calling this function with a
+pointer to the cache definition:
+
+       void fscache_withdraw_cache(struct fscache_cache *cache)
+
+In CacheFS's case, this is called by put_super().
+
+
+==================
+FS-CACHE UTILITIES
+==================
+
+FS-Cache provides some utilities that a cache backend may make use of:
+
+ (*) Find the parent of an object:
+
+       struct fscache_object *
+       fscache_find_parent_object(struct fscache_object *object)
+
+     This allows a backend to find the logical parent of an index or data file
+     in the cache hierarchy.
+
+ (*) Note occurrence of an I/O error in a cache:
+
+       void fscache_io_error(struct fscache_cache *cache)
+
+     This tells FS-Cache that an I/O error occurred in the cache.  After this
+     has been called, only resource dissociation operations (object and page
+     release) will be passed from the netfs to the cache backend for the
+     specified cache.
+
+     This does not actually withdraw the cache.  That must be done separately.
+
+ (*) Get an extra reference to a read or write context:
+
+       void *fscache_get_context(struct fscache_cookie *cookie, void *context)
+
+     and release a reference:
+
+       void *fscache_put_context(struct fscache_cookie *cookie, void *context)
+
+     These should be used to maintain the presence of the read or write context
+     passed to the cache read/write functions.  This context must then be
+     passed to the I/O completion function.
+
+
+========================
+RELEVANT DATA STRUCTURES
+========================
+
+ (*) Index/Data file FS-Cache representation cookie:
+
+       struct fscache_cookie {
+               struct fscache_object_def       *def;
+               struct fscache_netfs            *netfs;
+               void                            *netfs_data;
+               ...
+       };
+
+     The fields that might be of use to the backend describe the object
+     definition, the netfs definition and the netfs's data for this cookie.
+     The object definition contain functions supplied by the netfs for loading
+     and matching index entries; these are required to provide some of the
+     cache operations.
+
+ (*) In-cache object representation:
+
+       struct fscache_object {
+               struct fscache_cache            *cache;
+               struct fscache_cookie           *cookie;
+               unsigned long                   flags;
+       #define FSCACHE_OBJECT_RECYCLING        1
+               ...
+       };
+
+     Structures of this type should be allocated by the cache backend and
+     passed to FS-Cache when requested by the appropriate cache operation.  In
+     the case of CacheFS, they're embedded in CacheFS's internal object
+     structures.
+
+     Each object contains a pointer to the cookie that represents the object it
+     is backing.  It also contains a flag that indicates whether the object is
+     being retired when put_object() is called.  This should be initialised by
+     calling fscache_object_init(object).
+
+
+================
+CACHE OPERATIONS
+================
+
+The cache backend provides FS-Cache with a table of operations that can be
+performed on the denizens of the cache.  These are held in a structure of type:
+
+       struct fscache_cache_ops
+
+ (*) Name of cache provider [mandatory]:
+
+       const char *name
+
+     This isn't strictly an operation, but should be pointed at a string naming
+     the backend.
+
+ (*) Object lookup [mandatory]:
+
+       struct fscache_object *(*lookup_object)(struct fscache_cache *cache,
+                                               struct fscache_object *parent,
+                                               struct fscache_cookie *cookie)
+
+     This method is used to look up an object in the specified cache, given a
+     pointer to the parent object and the cookie to which the object will be
+     attached.  This should instantiate that object in the cache if it can, or
+     return -ENOBUFS or -ENOMEM if it can't.
+
+ (*) Increment object refcount [mandatory]:
+
+       struct fscache_object *(*grab_object)(struct fscache_object *object)
+
+     This method is called to increment the reference count on an object.  It
+     may fail (for instance if the cache is being withdrawn) by returning NULL.
+     It should return the object pointer if successful.
+
+ (*) Lock/Unlock object [mandatory]:
+
+       void (*lock_object)(struct fscache_object *object)
+       void (*unlock_object)(struct fscache_object *object)
+
+     These methods are used to exclusively lock an object.  It must be possible
+     to schedule with the lock held, so a spinlock isn't sufficient.
+
+ (*) Pin/Unpin object [optional]:
+
+       int (*pin_object)(struct fscache_object *object)
+       void (*unpin_object)(struct fscache_object *object)
+
+     These methods are used to pin an object into the cache.  Once pinned an
+     object cannot be reclaimed to make space.  Return -ENOSPC if there's not
+     enough space in the cache to permit this.
+
+ (*) Update object [mandatory]:
+
+       int (*update_object)(struct fscache_object *object)
+
+     This is called to update the index entry for the specified object.  The
+     new information should be in object->cookie->netfs_data.  This can be
+     obtained by calling object->cookie->def->get_aux()/get_attr().
+
+ (*) Release object reference [mandatory]:
+
+       void (*put_object)(struct fscache_object *object)
+
+     This method is used to discard a reference to an object.  The object may
+     be destroyed when all the references held by FS-Cache are released.
+
+ (*) Synchronise a cache [mandatory]:
+
+       void (*sync)(struct fscache_cache *cache)
+
+     This is called to ask the backend to synchronise a cache with its backing
+     device.
+
+ (*) Dissociate a cache [mandatory]:
+
+       void (*dissociate_pages)(struct fscache_cache *cache)
+
+     This is called to ask a cache to perform any page dissociations as part of
+     cache withdrawal.
+
+ (*) Set the data size on a cache file [mandatory]:
+
+       int (*set_i_size)(struct fscache_object *object, loff_t i_size);
+
+     This is called to indicate to the cache the maximum size a file may reach.
+     The cache may use this to reserve space on the cache.  It may also return
+     -ENOBUFS to indicate that insufficient space is available to expand the
+     metadata used to track the data.  It should return 0 if successful or
+     -ENOMEM or -EIO on error.
+
+ (*) Reserve cache space for an object's data [optional]:
+
+       int (*reserve_space)(struct fscache_object *object, loff_t size);
+
+     This is called to request that cache space be reserved to hold the data
+     for an object and the metadata used to track it.  Zero size should be
+     taken as request to cancel a reservation.
+
+     This should return 0 if successful, -ENOSPC if there isn't enough space
+     available, or -ENOMEM or -EIO on other errors.
+
+     The reservation may exceed the size of the object, thus permitting future
+     expansion.  If the amount of space consumed by an object would exceed the
+     reservation, it's permitted to refuse requests to allocate pages, but not
+     required.  An object may be pruned down to its reservation size if larger
+     than that already.
+
+ (*) Request page be read from cache [mandatory]:
+
+       int (*read_or_alloc_page)(struct fscache_object *object,
+                                 struct page *page,
+                                 fscache_rw_complete_t end_io_func,
+                                 void *end_io_data,
+                                 gfp_t gfp)
+
+     This is called to attempt to read a netfs page from the cache, or to
+     reserve a backing block if not.  FS-Cache will have done as much checking
+     as it can before calling, but most of the work belongs to the backend.
+
+     If there's no page in the cache, then -ENODATA should be returned if the
+     backend managed to reserve a backing block; -ENOBUFS, -ENOMEM or -EIO if
+     it didn't.
+
+     If there is a page in the cache, then a read operation should be queued
+     and 0 returned.  When the read finishes, end_io_func() should be called
+     with the following arguments:
+
+       (*end_io_func)(object->cookie->netfs_data,
+                      page,
+                      end_io_data,
+                      error);
+
+     The mark_pages_cached() cookie operation should be called for the page if
+     any cache metadata is retained.  This will indicate to the netfs that the
+     page needs explicit uncaching.  This operation takes a pagevec, thus
+     allowing several pages to be marked at once.
+
+ (*) Request pages be read from cache [mandatory]:
+
+       int (*read_or_alloc_pages)(struct fscache_object *object,
+                                  struct address_space *mapping,
+                                  struct list_head *pages,
+                                  unsigned *nr_pages,
+                                  fscache_rw_complete_t end_io_func,
+                                  void *end_io_data,
+                                  gfp_t gfp)
+
+     This is like the previous operation, except it will be handed a list of
+     pages instead of one page.  Any pages on which a read operation is started
+     must be added to the page cache for the specified mapping and also to the
+     LRU.  Such pages must also be removed from the pages list and nr_pages
+     decremented per page.
+
+     If there was an error such as -ENOMEM, then that should be returned; else
+     if one or more pages couldn't be read or allocated, then -ENOBUFS should
+     be returned; else if one or more pages couldn't be read, then -ENODATA
+     should be returned.  If all the pages are dispatched then 0 should be
+     returned.
+
+ (*) Request page be allocated in the cache [mandatory]:
+
+       int (*allocate_page)(struct fscache_object *object,
+                            struct page *page,
+                            gfp_t gfp)
+
+     This is like read_or_alloc_page(), except that it shouldn't read from the
+     cache, even if there's data there that could be retrieved.  It should,
+     however, set up any internal metadata required such that write_page() can
+     write to the cache.
+
+     If there's no backing block available, then -ENOBUFS should be returned
+     (or -ENOMEM or -EIO if there were other problems).  If a block is
+     successfully allocated, then the netfs page should be marked and 0
+     returned.
+
+ (*) Request page be written to cache [mandatory]:
+
+       int (*write_page)(struct fscache_object *object,
+                         struct page *page,
+                         fscache_rw_complete_t end_io_func,
+                         void *end_io_data,
+                         gfp_t gfp)
+
+     This is called to write from a page on which there was a previously
+     successful read_or_alloc_page() call.  FS-Cache filters out pages that
+     don't have mappings.
+
+     If there's no backing block available, then -ENOBUFS should be returned
+     (or -ENOMEM or -EIO if there were other problems).
+
+     If the write operation could be queued, then 0 should be returned.  When
+     the write completes, end_io_func() should be called with the following
+     arguments:
+
+       (*end_io_func)(object->cookie->netfs_data,
+                      page,
+                      end_io_data,
+                      error);
+
+ (*) Discard retained per-page metadata [mandatory]:
+
+       void (*uncache_pages)(struct fscache_object *object,
+                             struct pagevec *pagevec)
+
+     This is called when one or more netfs pages are being evicted from the
+     pagecache.  The cache backend should tear down any internal representation
+     or tracking it maintains.
diff --git a/Documentation/filesystems/caching/cachefiles.txt b/Documentation/filesystems/caching/cachefiles.txt
new file mode 100644 (file)
index 0000000..37b6385
--- /dev/null
@@ -0,0 +1,281 @@
+              ===============================================
+              CacheFiles: CACHE ON ALREADY MOUNTED FILESYSTEM
+              ===============================================
+
+Contents:
+
+ (*) Overview.
+
+ (*) Requirements.
+
+ (*) Configuration.
+
+ (*) Starting the cache.
+
+ (*) Things to avoid.
+
+
+========
+OVERVIEW
+========
+
+CacheFiles is a caching backend that's meant to use as a cache a directory on
+an already mounted filesystem of a local type (such as Ext3).
+
+CacheFiles uses a userspace daemon to do some of the cache management - such as
+reaping stale nodes and culling.  This is called cachefilesd and lives in
+/sbin.
+
+The filesystem and data integrity of the cache are only as good as those of the
+filesystem providing the backing services.  Note that CacheFiles does not
+attempt to journal anything since the journalling interfaces of the various
+filesystems are very specific in nature.
+
+CacheFiles creates a proc-file - "/proc/fs/cachefiles" - that is used for
+communication with the daemon.  Only one thing may have this open at once, and
+whilst it is open, a cache is at least partially in existence.  The daemon
+opens this and sends commands down it to control the cache.
+
+CacheFiles is currently limited to a single cache.
+
+CacheFiles attempts to maintain at least a certain percentage of free space on
+the filesystem, shrinking the cache by culling the objects it contains to make
+space if necessary - see the "Cache Culling" section.  This means it can be
+placed on the same medium as a live set of data, and will expand to make use of
+spare space and automatically contract when the set of data requires more
+space.
+
+
+============
+REQUIREMENTS
+============
+
+The use of CacheFiles and its daemon requires the following features to be
+available in the system and in the cache filesystem:
+
+       - dnotify.
+
+       - extended attributes (xattrs).
+
+       - openat() and friends.
+
+       - bmap() support on files in the filesystem (FIBMAP ioctl).
+
+       - The use of bmap() to detect a partial page at the end of the file.
+
+It is strongly recommended that the "dir_index" option is enabled on Ext3
+filesystems being used as a cache.
+
+
+=============
+CONFIGURATION
+=============
+
+The cache is configured by a script in /etc/cachefilesd.conf.  These commands
+set up cache ready for use.  The following script commands are available:
+
+ (*) brun <N>%
+ (*) bcull <N>%
+ (*) bstop <N>%
+
+       Configure the culling limits.  Optional.  See the section on culling
+       The defaults are 7%, 5% and 1% respectively.
+
+ (*) dir <path>
+
+       Specify the directory containing the root of the cache.  Mandatory.
+
+ (*) tag <name>
+
+       Specify a tag to FS-Cache to use in distinguishing multiple caches.
+       Optional.  The default is "CacheFiles".
+
+ (*) debug <mask>
+
+       Specify a numeric bitmask to control debugging in the kernel module.
+       Optional.  The default is zero (all off).  The following values can be
+       OR'd into the mask to collect various information:
+
+               1       Turn on trace of function entry (_enter() macros)
+               2       Turn on trace of function exit (_leave() macros)
+               4       Turn on trace of internal debug points (_debug())
+
+       This mask can also be set through /proc/sys/fs/cachefiles/debug.
+
+
+==================
+STARTING THE CACHE
+==================
+
+The cache is started by running the daemon.  The daemon opens the cache proc
+file, configures the cache and tells it to begin caching.  At that point the
+cache binds to fscache and the cache becomes live.
+
+The daemon is run as follows:
+
+       /sbin/cachefilesd [-d]* [-s] [-n] [-f <configfile>]
+
+The flags are:
+
+ (*) -d
+
+       Increase the debugging level.  This can be specified multiple times and
+       is cumulative with itself.
+
+ (*) -s
+
+       Send messages to stderr instead of syslog.
+
+ (*) -n
+
+       Don't daemonise and go into background.
+
+ (*) -f <configfile>
+
+       Use an alternative configuration file rather than the default one.
+
+
+===============
+THINGS TO AVOID
+===============
+
+Do not mount other things within the cache as this will cause problems.  The
+kernel module contains its own very cut-down path walking facility that ignores
+mountpoints, but the daemon can't avoid them.
+
+Do not create, rename or unlink files and directories in the cache whilst the
+cache is active, as this may cause the state to become uncertain.
+
+Renaming files in the cache might make objects appear to be other objects (the
+filename is part of the lookup key).
+
+Do not change or remove the extended attributes attached to cache files by the
+cache as this will cause the cache state management to get confused.
+
+Do not create files or directories in the cache, lest the cache get confused or
+serve incorrect data.
+
+Do not chmod files in the cache.  The module creates things with minimal
+permissions to prevent random users being able to access them directly.
+
+
+=============
+CACHE CULLING
+=============
+
+The cache may need culling occasionally to make space.  This involves
+discarding objects from the cache that have been used less recently than
+anything else.  Culling is based on the access time of data objects.  Empty
+directories are culled if not in use.
+
+Cache culling is done on the basis of the percentage of blocks available in the
+underlying filesystem.  There are three "limits":
+
+ (*) brun
+
+     If the amount of available space in the cache rises above this limit, then
+     culling is turned off.
+
+ (*) bcull
+
+     If the amount of available space in the cache falls below this limit, then
+     culling is started.
+
+ (*) bstop
+
+     If the amount of available space in the cache falls below this limit, then
+     no further allocation of disk space is permitted until culling has raised
+     the amount above this limit again.
+
+These must be configured thusly:
+
+       0 <= bstop < bcull < brun < 100
+
+Note that these are percentages of available space, and do _not_ appear as 100
+minus the percentage displayed by the "df" program.
+
+The userspace daemon scans the cache to build up a table of cullable objects.
+These are then culled in least recently used order.  A new scan of the cache is
+started as soon as space is made in the table.  Objects will be skipped if
+their atimes have changed or if the kernel module says it is still using them.
+
+
+===============
+CACHE STRUCTURE
+===============
+
+The CacheFiles module will create two directories in the directory it was
+given:
+
+ (*) cache/
+
+ (*) graveyard/
+
+The active cache objects all reside in the first directory.  The CacheFiles
+kernel module moves any retired or culled objects that it can't simply unlink
+to the graveyard from which the daemon will actually delete them.
+
+The daemon uses dnotify to monitor the graveyard directory, and will delete
+anything that appears therein.
+
+
+The module represents index objects as directories with the filename "I..." or
+"J...".  Note that the "cache/" directory is itself a special index.
+
+Data objects are represented as files if they have no children, or directories
+if they do.  Their filenames all begin "D..." or "E...".  If represented as a
+directory, data objects will have a file in the directory called "data" that
+actually holds the data.
+
+Special objects are similar to data objects, except their filenames begin
+"S..." or "T...".
+
+
+If an object has children, then it will be represented as a directory.
+Immediately in the representative directory are a collection of directories
+named for hash values of the child object keys with an '@' prepended.  Into
+this directory, if possible, will be placed the representations of the child
+objects:
+
+       INDEX     INDEX      INDEX                             DATA FILES
+       ========= ========== ================================= ================
+       cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400
+       cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...DB1ry
+       cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...N22ry
+       cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...FP1ry
+
+
+If the key is so long that it exceeds NAME_MAX with the decorations added on to
+it, then it will be cut into pieces, the first few of which will be used to
+make a nest of directories, and the last one of which will be the objects
+inside the last directory.  The names of the intermediate directories will have
+'+' prepended:
+
+       J1223/@23/+xy...z/+kl...m/Epqr
+
+
+Note that keys are raw data, and not only may they exceed NAME_MAX in size,
+they may also contain things like '/' and NUL characters, and so they may not
+be suitable for turning directly into a filename.
+
+To handle this, CacheFiles will use a suitably printable filename directly and
+"base-64" encode ones that aren't directly suitable.  The two versions of
+object filenames indicate the encoding:
+
+       OBJECT TYPE     PRINTABLE       ENCODED
+       =============== =============== ===============
+       Index           "I..."          "J..."
+       Data            "D..."          "E..."
+       Special         "S..."          "T..."
+
+Intermediate directories are always "@" or "+" as appropriate.
+
+
+Each object in the cache has an extended attribute label that holds the object
+type ID (required to distinguish special objects) and the auxiliary data from
+the netfs.  The latter is used to detect stale objects in the cache and update
+or retire them.
+
+
+Note that CacheFiles will erase from the cache any file it doesn't recognise or
+any file of an incorrect type (such as a FIFO file or a device file).
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
new file mode 100644 (file)
index 0000000..82c3168
--- /dev/null
@@ -0,0 +1,151 @@
+                         ==========================
+                         General Filesystem Caching
+                         ==========================
+
+========
+OVERVIEW
+========
+
+This facility is a general purpose cache for network filesystems, though it
+could be used for caching other things such as ISO9660 filesystems too.
+
+FS-Cache mediates between cache backends (such as CacheFS) and network
+filesystems:
+
+       +---------+
+       |         |                        +--------------+
+       |   NFS   |--+                     |              |
+       |         |  |                 +-->|   CacheFS    |
+       +---------+  |   +----------+  |   |  /dev/hda5   |
+                    |   |          |  |   +--------------+
+       +---------+  +-->|          |  |
+       |         |      |          |--+
+       |   AFS   |----->| FS-Cache |
+       |         |      |          |--+
+       +---------+  +-->|          |  |
+                    |   |          |  |   +--------------+
+       +---------+  |   +----------+  |   |              |
+       |         |  |                 +-->|  CacheFiles  |
+       |  ISOFS  |--+                     |  /var/cache  |
+       |         |                        +--------------+
+       +---------+
+
+
+FS-Cache does not follow the idea of completely loading every netfs file
+opened in its entirety into a cache before permitting it to be accessed and
+then serving the pages out of that cache rather than the netfs inode because:
+
+ (1) It must be practical to operate without a cache.
+
+ (2) The size of any accessible file must not be limited to the size of the
+     cache.
+
+ (3) The combined size of all opened files (this includes mapped libraries)
+     must not be limited to the size of the cache.
+
+ (4) The user should not be forced to download an entire file just to do a
+     one-off access of a small portion of it (such as might be done with the
+     "file" program).
+
+It instead serves the cache out in PAGE_SIZE chunks as and when requested by
+the netfs('s) using it.
+
+
+FS-Cache provides the following facilities:
+
+ (1) More than one cache can be used at once.  Caches can be selected
+     explicitly by use of tags.
+
+ (2) Caches can be added / removed at any time.
+
+ (3) The netfs is provided with an interface that allows either party to
+     withdraw caching facilities from a file (required for (2)).
+
+ (4) The interface to the netfs returns as few errors as possible, preferring
+     rather to let the netfs remain oblivious.
+
+ (5) Cookies are used to represent indices, files and other objects to the
+     netfs.  The simplest cookie is just a NULL pointer - indicating nothing
+     cached there.
+
+ (6) The netfs is allowed to propose - dynamically - any index hierarchy it
+     desires, though it must be aware that the index search function is
+     recursive, stack space is limited, and indices can only be children of
+     indices.
+
+ (7) Data I/O is done direct to and from the netfs's pages.  The netfs
+     indicates that page A is at index B of the data-file represented by cookie
+     C, and that it should be read or written.  The cache backend may or may
+     not start I/O on that page, but if it does, a netfs callback will be
+     invoked to indicate completion.  The I/O may be either synchronous or
+     asynchronous.
+
+ (8) Cookies can be "retired" upon release.  At this point FS-Cache will mark
+     them as obsolete and the index hierarchy rooted at that point will get
+     recycled.
+
+ (9) The netfs provides a "match" function for index searches.  In addition to
+     saying whether a match was made or not, this can also specify that an
+     entry should be updated or deleted.
+
+
+FS-Cache maintains a virtual indexing tree in which all indices, files, objects
+and pages are kept.  Bits of this tree may actually reside in one or more
+caches.
+
+                                           FSDEF
+                                             |
+                        +------------------------------------+
+                        |                                    |
+                       NFS                                  AFS
+                        |                                    |
+           +--------------------------+                +-----------+
+           |                          |                |           |
+        homedir                     mirror          afs.org   redhat.com
+           |                          |                            |
+     +------------+           +---------------+              +----------+
+     |            |           |               |              |          |
+   00001        00002       00007           00125        vol00001   vol00002
+     |            |           |               |                         |
+ +---+---+     +-----+      +---+      +------+------+            +-----+----+
+ |   |   |     |     |      |   |      |      |      |            |     |    |
+PG0 PG1 PG2   PG0  XATTR   PG0 PG1   DIRENT DIRENT DIRENT        R/W   R/O  Bak
+                     |                                            |
+                    PG0                                       +-------+
+                                                              |       |
+                                                            00001   00003
+                                                              |
+                                                          +---+---+
+                                                          |   |   |
+                                                         PG0 PG1 PG2
+
+In the example above, you can see two netfs's being backed: NFS and AFS.  These
+have different index hierarchies:
+
+ (*) The NFS primary index contains per-server indices.  Each server index is
+     indexed by NFS file handles to get data file objects.  Each data file
+     objects can have an array of pages, but may also have further child
+     objects, such as extended attributes and directory entries.  Extended
+     attribute objects themselves have page-array contents.
+
+ (*) The AFS primary index contains per-cell indices.  Each cell index contains
+     per-logical-volume indices.  Each of volume index contains up to three
+     indices for the read-write, read-only and backup mirrors of those volumes.
+     Each of these contains vnode data file objects, each of which contains an
+     array of pages.
+
+The very top index is the FS-Cache master index in which individual netfs's
+have entries.
+
+Any index object may reside in more than one cache, provided it only has index
+children.  Any index with non-index object children will be assumed to only
+reside in one cache.
+
+
+The netfs API to FS-Cache can be found in:
+
+       Documentation/filesystems/caching/netfs-api.txt
+
+The cache backend API to FS-Cache can be found in:
+
+       Documentation/filesystems/caching/backend-api.txt
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
new file mode 100644 (file)
index 0000000..a1a182b
--- /dev/null
@@ -0,0 +1,752 @@
+                       ===============================
+                       FS-CACHE NETWORK FILESYSTEM API
+                       ===============================
+
+There's an API by which a network filesystem can make use of the FS-Cache
+facilities.  This is based around a number of principles:
+
+ (1) Caches can store a number of different object types.  There are two main
+     object types: indices and files.  The first is a special type used by
+     FS-Cache to make finding objects faster and to make retiring of groups of
+     objects easier.
+
+ (2) Every index, file or other object is represented by a cookie.  This cookie
+     may or may not have anything associated with it, but the netfs doesn't
+     need to care.
+
+ (3) Barring the top-level index (one entry per cached netfs), the index
+     hierarchy for each netfs is structured according the whim of the netfs.
+
+This API is declared in <linux/fscache.h>.
+
+This document contains the following sections:
+
+        (1) Network filesystem definition
+        (2) Index definition
+        (3) Object definition
+        (4) Network filesystem (un)registration
+        (5) Cache tag lookup
+        (6) Index registration
+        (7) Data file registration
+        (8) Miscellaneous object registration
+        (9) Setting the data file size
+       (10) Page alloc/read/write
+       (11) Page uncaching
+       (12) Index and data file update
+       (13) Miscellaneous cookie operations
+       (14) Cookie unregistration
+       (15) Index and data file invalidation
+
+
+=============================
+NETWORK FILESYSTEM DEFINITION
+=============================
+
+FS-Cache needs a description of the network filesystem.  This is specified
+using a record of the following structure:
+
+       struct fscache_netfs {
+               uint32_t                        version;
+               const char                      *name;
+               struct fscache_netfs_operations *ops;
+               struct fscache_cookie           *primary_index;
+               ...
+       };
+
+This first three fields should be filled in before registration, and the fourth
+will be filled in by the registration function; any other fields should just be
+ignored and are for internal use only.
+
+The fields are:
+
+ (1) The name of the netfs (used as the key in the toplevel index).
+
+ (2) The version of the netfs (if the name matches but the version doesn't, the
+     entire in-cache hierarchy for this netfs will be scrapped and begun
+     afresh).
+
+ (3) The operations table is defined as follows:
+
+       struct fscache_netfs_operations {
+       };
+
+     Currently there aren't any functions here.
+
+ (4) The cookie representing the primary index will be allocated according to
+     another parameter passed into the registration function.
+
+For example, kAFS (linux/fs/afs/) uses the following definitions to describe
+itself:
+
+       static struct fscache_netfs_operations afs_cache_ops = {
+       };
+
+       struct fscache_netfs afs_cache_netfs = {
+               .version        = 0,
+               .name           = "afs",
+               .ops            = &afs_cache_ops,
+       };
+
+
+================
+INDEX DEFINITION
+================
+
+Indices are used for two purposes:
+
+ (1) To aid the finding of a file based on a series of keys (such as AFS's
+     "cell", "volume ID", "vnode ID").
+
+ (2) To make it easier to discard a subset of all the files cached based around
+     a particular key - for instance to mirror the removal of an AFS volume.
+
+However, since it's unlikely that any two netfs's are going to want to define
+their index hierarchies in quite the same way, FS-Cache tries to impose as few
+restraints as possible on how an index is structured and where it is placed in
+the tree.  The netfs can even mix indices and data files at the same level, but
+it's not recommended.
+
+Each index entry consists of a key of indeterminate length plus some auxilliary
+data, also of indeterminate length.
+
+There are some limits on indices:
+
+ (1) Any index containing non-index objects should be restricted to a single
+     cache.  Any such objects created within an index will be created in the
+     first cache only.  The cache in which an index is created can be
+     controlled by cache tags (see below).
+
+ (2) The entry data must be atomically journallable, so it is limited to about
+     400 bytes at present.  At least 400 bytes will be available.
+
+ (3) The depth of the index tree should be judged with care as the search
+     function is recursive.  Too many layers will run the kernel out of stack.
+
+
+=================
+OBJECT DEFINITION
+=================
+
+To define an object, a structure of the following type should be filled out:
+
+       struct fscache_object_def
+       {
+               uint8_t name[16];
+               uint8_t type;
+
+               struct fscache_cache_tag *(*select_cache)(
+                       const void *parent_netfs_data,
+                       const void *cookie_netfs_data);
+
+               uint16_t (*get_key)(const void *cookie_netfs_data,
+                                   void *buffer,
+                                   uint16_t bufmax);
+
+               void (*get_attr)(const void *cookie_netfs_data,
+                                uint64_t *size);
+
+               uint16_t (*get_aux)(const void *cookie_netfs_data,
+                                   void *buffer,
+                                   uint16_t bufmax);
+
+               fscache_checkaux_t (*check_aux)(void *cookie_netfs_data,
+                                               const void *data,
+                                               uint16_t datalen);
+
+               void (*get_context)(void *cookie_netfs_data, void *context);
+
+               void (*put_context)(void *cookie_netfs_data, void *context);
+
+               void (*mark_pages_cached)(void *cookie_netfs_data,
+                                         struct address_space *mapping,
+                                         struct pagevec *cached_pvec);
+
+               void (*now_uncached)(void *cookie_netfs_data);
+       };
+
+This has the following fields:
+
+ (1) The type of the object [mandatory].
+
+     This is one of the following values:
+
+       (*) FSCACHE_COOKIE_TYPE_INDEX
+
+           This defines an index, which is a special FS-Cache type.
+
+       (*) FSCACHE_COOKIE_TYPE_DATAFILE
+
+           This defines an ordinary data file.
+
+       (*) Any other value between 2 and 255
+
+           This defines an extraordinary object such as an XATTR.
+
+ (2) The name of the object type (NUL terminated unless all 16 chars are used)
+     [optional].
+
+ (3) A function to select the cache in which to store an index [optional].
+
+     This function is invoked when an index needs to be instantiated in a cache
+     during the instantiation of a non-index object.  Only the immediate index
+     parent for the non-index object will be queried.  Any indices above that
+     in the hierarchy may be stored in multiple caches.  This function does not
+     need to be supplied for any non-index object or any index that will only
+     have index children.
+
+     If this function is not supplied or if it returns NULL then the first
+     cache in the parent's list will be chosed, or failing that, the first
+     cache in the master list.
+
+ (4) A function to retrieve an object's key from the netfs [mandatory].
+
+     This function will be called with the netfs data that was passed to the
+     cookie acquisition function and the maximum length of key data that it may
+     provide.  It should write the required key data into the given buffer and
+     return the quantity it wrote.
+
+ (5) A function to retrieve attribute data from the netfs [optional].
+
+     This function will be called with the netfs data that was passed to the
+     cookie acquisition function.  It should return the size of the file if
+     this is a data file.  The size may be used to govern how much cache must
+     be reserved for this file in the cache.
+
+     If the function is absent, a file size of 0 is assumed.
+
+ (6) A function to retrieve auxilliary data from the netfs [optional].
+
+     This function will be called with the netfs data that was passed to the
+     cookie acquisition function and the maximum length of auxilliary data that
+     it may provide.  It should write the auxilliary data into the given buffer
+     and return the quantity it wrote.
+
+     If this function is absent, the auxilliary data length will be set to 0.
+
+     The length of the auxilliary data buffer may be dependent on the key
+     length.  A netfs mustn't rely on being able to provide more than 400 bytes
+     for both.
+
+ (7) A function to check the auxilliary data [optional].
+
+     This function will be called to check that a match found in the cache for
+     this object is valid.  For instance with AFS it could check the auxilliary
+     data against the data version number returned by the server to determine
+     whether the index entry in a cache is still valid.
+
+     If this function is absent, it will be assumed that matching objects in a
+     cache are always valid.
+
+     If present, the function should return one of the following values:
+
+       (*) FSCACHE_CHECKAUX_OKAY               - the entry is okay as is
+       (*) FSCACHE_CHECKAUX_NEEDS_UPDATE       - the entry requires update
+       (*) FSCACHE_CHECKAUX_OBSOLETE           - the entry should be deleted
+
+     This function can also be used to extract data from the auxilliary data in
+     the cache and copy it into the netfs's structures.
+
+ (8) A pair of functions to manage contexts for the completion callback
+     [optional].
+
+     The cache read/write functions are passed a context which is then passed
+     to the I/O completion callback function.  To ensure this context remains
+     valid until after the I/O completion is called, two functions may be
+     provided: one to get an extra reference on the context, and one to drop a
+     reference to it.
+
+     If the context is not used or is a type of object that won't go out of
+     scope, then these functions are not required.  These functions are not
+     required for indices as indices may not contain data.  These functions may
+     be called in interrupt context and so may not sleep.
+
+ (9) A function to mark a page as retaining cache metadata [mandatory].
+
+     This is called by the cache to indicate that it is retaining in-memory
+     information for this page and that the netfs should uncache the page when
+     it has finished.  This does not indicate whether there's data on the disk
+     or not.  Note that several pages at once may be presented for marking.
+
+     kAFS and NFS use the PG_private bit on the page structure for this, but
+     that may not be appropriate in all cases.
+
+     This function is not required for indices as they're not permitted data.
+
+(10) A function to unmark all the pages retaining cache metadata [mandatory].
+
+     This is called by FS-Cache to indicate that a backing store is being
+     unbound from a cookie and that all the marks on the pages should be
+     cleared to prevent confusion.  Note that the cache will have torn down all
+     its tracking information so that the pages don't need to be explicitly
+     uncached.
+
+     This function is not required for indices as they're not permitted data.
+
+
+===================================
+NETWORK FILESYSTEM (UN)REGISTRATION
+===================================
+
+The first step is to declare the network filesystem to the cache.  This also
+involves specifying the layout of the primary index (for AFS, this would be the
+"cell" level).
+
+The registration function is:
+
+       int fscache_register_netfs(struct fscache_netfs *netfs);
+
+It just takes a pointer to the netfs definition.  It returns 0 or an error as
+appropriate.
+
+For kAFS, registration is done as follows:
+
+       ret = fscache_register_netfs(&afs_cache_netfs);
+
+The last step is, of course, unregistration:
+
+       void fscache_unregister_netfs(struct fscache_netfs *netfs);
+
+
+================
+CACHE TAG LOOKUP
+================
+
+FS-Cache permits the use of more than one cache.  To permit particular index
+subtrees to be bound to particular caches, the second step is to look up cache
+representation tags.  This step is optional; it can be left entirely up to
+FS-Cache as to which cache should be used.  The problem with doing that is that
+FS-Cache will always pick the first cache that was registered.
+
+To get the representation for a named tag:
+
+       struct fscache_cache_tag *fscache_lookup_cache_tag(const char *name);
+
+This takes a text string as the name and returns a representation of a tag.  It
+will never return an error.  It may return a dummy tag, however, if it runs out
+of memory; this will inhibit caching with this tag.
+
+Any representation so obtained must be released by passing it to this function:
+
+       void fscache_release_cache_tag(struct fscache_cache_tag *tag);
+
+The tag will be retrieved by FS-Cache when it calls the object definition
+operation select_cache().
+
+
+==================
+INDEX REGISTRATION
+==================
+
+The third step is to inform FS-Cache about part of an index hierarchy that can
+be used to locate files.  This is done by requesting a cookie for each index in
+the path to the file:
+
+       struct fscache_cookie *
+       fscache_acquire_cookie(struct fscache_cookie *parent,
+                              struct fscache_object_def *def,
+                              void *netfs_data);
+
+This function creates an index entry in the index represented by parent,
+filling in the index entry by calling the operations pointed to by def.
+
+Note that this function never returns an error - all errors are handled
+internally.  It may also return NULL to indicate no cookie.  It is quite
+acceptable to pass this token back to this function as the parent to another
+acquisition (or even to the relinquish cookie, read page and write page
+functions - see below).
+
+Note also that no indices are actually created in a cache until a non-index
+object needs to be created somewhere down the hierarchy.  Furthermore, an index
+may be created in several different caches independently at different times.
+This is all handled transparently, and the netfs doesn't see any of it.
+
+For example, with AFS, a cell would be added to the primary index.  This index
+entry would have a dependent inode containing a volume location index for the
+volume mappings within this cell:
+
+       cell->cache =
+               fscache_acquire_cookie(afs_cache_netfs.primary_index,
+                                      &afs_cell_cache_index_def,
+                                      cell);
+
+Then when a volume location was accessed, it would be entered into the cell's
+index and an inode would be allocated that acts as a volume type and hash chain
+combination:
+
+       vlocation->cache =
+               fscache_acquire_cookie(cell->cache,
+                                      &afs_vlocation_cache_index_def,
+                                      vlocation);
+
+And then a particular flavour of volume (R/O for example) could be added to
+that index, creating another index for vnodes (AFS inode equivalents):
+
+       volume->cache =
+               fscache_acquire_cookie(vlocation->cache,
+                                      &afs_volume_cache_index_def,
+                                      volume);
+
+
+======================
+DATA FILE REGISTRATION
+======================
+
+The fourth step is to request a data file be created in the cache.  This is
+identical to index cookie acquisition.  The only difference is that the type in
+the object definition should be something other than index type.
+
+       vnode->cache =
+               fscache_acquire_cookie(volume->cache,
+                                      &afs_vnode_cache_object_def,
+                                      vnode);
+
+
+=================================
+MISCELLANEOUS OBJECT REGISTRATION
+=================================
+
+An optional step is to request an object of miscellaneous type be created in
+the cache.  This is almost identical to index cookie acquisition.  The only
+difference is that the type in the object definition should be something other
+than index type.  Whilst the parent object could be an index, it's more likely
+it would be some other type of object such as a data file.
+
+       xattr->cache =
+               fscache_acquire_cookie(vnode->cache,
+                                      &afs_xattr_cache_object_def,
+                                      xattr);
+
+Miscellaneous objects might be used to store extended attributes or directory
+entries for example.
+
+
+==========================
+SETTING THE DATA FILE SIZE
+==========================
+
+The fifth step is to set the size of the file.  This doesn't automatically
+reserve any space in the cache, but permits the cache to adjust its metadata
+for data tracking appropriately:
+
+       int fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size);
+
+The cache will return -ENOBUFS if there is no backing cache or if there is no
+space to allocate any extra metadata required in the cache.
+
+Note that attempts to read or write data pages in the cache over this size may
+be rebuffed with -ENOBUFS.
+
+
+=====================
+PAGE READ/ALLOC/WRITE
+=====================
+
+And the sixth step is to store and retrieve pages in the cache.  There are
+three functions that are used to do this.
+
+Note:
+
+ (1) A page should not be re-read or re-allocated without uncaching it first.
+
+ (2) A read or allocated page must be uncached when the netfs page is released
+     from the pagecache.
+
+ (3) A page should only be written to the cache if previous read or allocated.
+
+This permits the cache to maintain its page tracking in proper order.
+
+
+PAGE READ
+---------
+
+Firstly, the netfs should ask FS-Cache to examine the caches and read the
+contents cached for a particular page of a particular file if present, or else
+allocate space to store the contents if not:
+
+       typedef
+       void (*fscache_rw_complete_t)(struct page *page,
+                                     void *context,
+                                     int error);
+
+       int fscache_read_or_alloc_page(struct fscache_cookie *cookie,
+                                      struct page *page,
+                                      fscache_rw_complete_t end_io_func,
+                                      void *end_io_data,
+                                      gfp_t gfp);
+
+The cookie argument must specify a cookie for an object that isn't an index,
+the page specified will have the data loaded into it (and is also used to
+specify the page number), and the gfp argument is used to control how any
+memory allocations made are satisfied.
+
+If the cookie indicates the inode is not cached:
+
+ (1) The function will return -ENOBUFS.
+
+Else if there's a copy of the page resident in the cache:
+
+ (1) The mark_pages_cached() cookie operation will be called on that page.
+
+ (2) The function will submit a request to read the data from the cache's
+     backing device directly into the page specified.
+
+ (3) The function will return 0.
+
+ (4) When the read is complete, end_io_func() will be invoked with:
+
+     (*) The netfs data supplied when the cookie was created.
+
+     (*) The page descriptor.
+
+     (*) The context argument passed to the above function.  This will be
+        maintained with the get_context/put_context functions mentioned above.
+
+     (*) An argument that's 0 on success or negative for an error code.
+
+     If an error occurs, it should be assumed that the page contains no usable
+     data.
+
+     end_io_func() will be called in process context if the read is results in
+     an error, but it might be called in interrupt context if the read is
+     successful.
+
+Otherwise, if there's not a copy available in cache, but the cache may be able
+to store the page:
+
+ (1) The mark_pages_cached() cookie operation will be called on that page.
+
+ (2) A block may be reserved in the cache and attached to the object at the
+     appropriate place.
+
+ (3) The function will return -ENODATA.
+
+This function may also return -ENOMEM or -EINTR, in which case it won't have
+read any data from the cache.
+
+
+PAGE ALLOCATE
+-------------
+
+Alternatively, if there's not expected to be any data in the cache for a page
+because the file has been extended, a block can simply be allocated instead:
+
+       int fscache_alloc_page(struct fscache_cookie *cookie,
+                              struct page *page,
+                              gfp_t gfp);
+
+This is similar to the fscache_read_or_alloc_page() function, except that it
+never reads from the cache.  It will return 0 if a block has been allocated,
+rather than -ENODATA as the other would.  One or the other must be performed
+before writing to the cache.
+
+The mark_pages_cached() cookie operation will be called on the page if
+successful.
+
+
+PAGE WRITE
+----------
+
+Secondly, if the netfs changes the contents of the page (either due to an
+initial download or if a user performs a write), then the page should be
+written back to the cache:
+
+       int fscache_write_page(struct fscache_cookie *cookie,
+                              struct page *page,
+                              fscache_rw_complete_t end_io_func,
+                              void *context,
+                              gfp_t gfp);
+
+The cookie argument must specify a data file cookie, the page specified should
+contain the data to be written (and is also used to specify the page number),
+and the gfp argument is used to control how any memory allocations made are
+satisfied.
+
+The page must have first been read or allocated successfully and must not have
+been uncached before writing is performed.
+
+If the cookie indicates the inode is not cached then:
+
+ (1) The function will return -ENOBUFS.
+
+Else if space can be allocated in the cache to hold this page:
+
+ (1) The function will submit a request to write the data to cache's backing
+     device directly from the page specified.
+
+ (2) The function will return 0.
+
+ (3) When the write is complete the end_io_func() will be invoked with:
+
+     (*) The netfs data supplied when the cookie was created.
+
+     (*) The page descriptor.
+
+     (*) The context argument passed to the function.  This will be maintained
+        with the get_context/put_context functions mentioned above.
+
+     (*) An argument that's 0 on success or negative for an error.
+
+     If an error occurs, it can be assumed that the page has not been written
+     to the cache, and that either there's a block containing the old data or
+     no block at all in the cache.
+
+     end_io_func() might be called in interrupt context.
+
+Else if there's no space available in the cache, -ENOBUFS will be returned.
+
+
+MULTIPLE PAGE READ
+------------------
+
+A facility is provided to read several pages at once, as requested by the
+readpages() address space operation:
+
+       int fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
+                                       struct address_space *mapping,
+                                       struct list_head *pages,
+                                       int *nr_pages,
+                                       fscache_rw_complete_t end_io_func,
+                                       void *context,
+                                       gfp_t gfp);
+
+This works in a similar way to fscache_read_or_alloc_page(), except:
+
+ (1) Any page it can retrieve data for is removed from pages and nr_pages and
+     dispatched for reading to the disk.  Reads of adjacent pages on disk may
+     be merged for greater efficiency.
+
+ (2) The mark_pages_cached() cookie operation will be called on several pages
+     at once if they're being read or allocated.
+
+ (3) If there was an general error, then that error will be returned.
+
+     Else if some pages couldn't be allocated or read, then -ENOBUFS will be
+     returned.
+
+     Else if some pages couldn't be read but were allocated, then -ENODATA will
+     be returned.
+
+     Otherwise, if all pages had reads dispatched, then 0 will be returned, the
+     list will be empty and *nr_pages will be 0.
+
+ (4) end_io_func will be called once for each page being read as the reads
+     complete.  It will be called in process context if error != 0, but it may
+     be called in interrupt context if there is no error.
+
+Note that a return of -ENODATA, -ENOBUFS or any other error does not preclude
+some of the pages being read and some being allocated.  Those pages will have
+been marked appropriately and will need uncaching.
+
+
+==============
+PAGE UNCACHING
+==============
+
+To uncache a page, this function should be called:
+
+       void fscache_uncache_page(struct fscache_cookie *cookie,
+                                 struct page *page);
+
+This function permits the cache to release any in-memory representation it
+might be holding for this netfs page.  This function must be called once for
+each page on which the read or write page functions above have been called to
+make sure the cache's in-memory tracking information gets torn down.
+
+Note that pages can't be explicitly deleted from the a data file.  The whole
+data file must be retired (see the relinquish cookie function below).
+
+Furthermore, note that this does not cancel the asynchronous read or write
+operation started by the read/alloc and write functions.
+
+There is another unbinding operation similar to the above that takes a set of
+pages to unbind in one go:
+
+       void fscache_uncache_pagevec(struct fscache_cookie *cookie,
+                                    struct pagevec *pagevec);
+
+
+==========================
+INDEX AND DATA FILE UPDATE
+==========================
+
+To request an update of the index data for an index or other object, the
+following function should be called:
+
+       void fscache_update_cookie(struct fscache_cookie *cookie);
+
+This function will refer back to the netfs_data pointer stored in the cookie by
+the acquisition function to obtain the data to write into each revised index
+entry.  The update method in the parent index definition will be called to
+transfer the data.
+
+Note that partial updates may happen automatically at other times, such as when
+data blocks are added to a data file object.
+
+
+===============================
+MISCELLANEOUS COOKIE OPERATIONS
+===============================
+
+There are a number of operations that can be used to control cookies:
+
+ (*) Cookie pinning:
+
+       int fscache_pin_cookie(struct fscache_cookie *cookie);
+       void fscache_unpin_cookie(struct fscache_cookie *cookie);
+
+     These operations permit data cookies to be pinned into the cache and to
+     have the pinning removed.  They are not permitted on index cookies.
+
+     The pinning function will return 0 if successful, -ENOBUFS in the cookie
+     isn't backed by a cache, -EOPNOTSUPP if the cache doesn't support pinning,
+     -ENOSPC if there isn't enough space to honour the operation, -ENOMEM or
+     -EIO if there's any other problem.
+
+ (*) Data space reservation:
+
+       int fscache_reserve_space(struct fscache_cookie *cookie, loff_t size);
+
+     This permits a netfs to request cache space be reserved to store up to the
+     given amount of a file.  It is permitted to ask for more than the current
+     size of the file to allow for future file expansion.
+
+     If size is given as zero then the reservation will be cancelled.
+
+     The function will return 0 if successful, -ENOBUFS in the cookie isn't
+     backed by a cache, -EOPNOTSUPP if the cache doesn't support reservations,
+     -ENOSPC if there isn't enough space to honour the operation, -ENOMEM or
+     -EIO if there's any other problem.
+
+     Note that this doesn't pin an object in a cache; it can still be culled to
+     make space if it's not in use.
+
+
+=====================
+COOKIE UNREGISTRATION
+=====================
+
+To get rid of a cookie, this function should be called.
+
+       void fscache_relinquish_cookie(struct fscache_cookie *cookie,
+                                      int retire);
+
+If retire is non-zero, then the object will be marked for recycling, and all
+copies of it will be removed from all active caches in which it is present.
+Not only that but all child objects will also be retired.
+
+If retire is zero, then the object may be available again when next the
+acquisition function is called.  Retirement here will overrule the pinning on a
+cookie.
+
+One very important note - relinquish must NOT be called for a cookie unless all
+the cookies for "child" indices, objects and pages have been relinquished
+first.
+
+
+================================
+INDEX AND DATA FILE INVALIDATION
+================================
+
+There is no direct way to invalidate an index subtree or a data file.  To do
+this, the caller should relinquish and retire the cookie they have, and then
+acquire a new one.
diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt
new file mode 100644 (file)
index 0000000..d6788da
--- /dev/null
@@ -0,0 +1,479 @@
+relay interface (formerly relayfs)
+==================================
+
+The relay interface provides a means for kernel applications to
+efficiently log and transfer large quantities of data from the kernel
+to userspace via user-defined 'relay channels'.
+
+A 'relay channel' is a kernel->user data relay mechanism implemented
+as a set of per-cpu kernel buffers ('channel buffers'), each
+represented as a regular file ('relay file') in user space.  Kernel
+clients write into the channel buffers using efficient write
+functions; these automatically log into the current cpu's channel
+buffer.  User space applications mmap() or read() from the relay files
+and retrieve the data as it becomes available.  The relay files
+themselves are files created in a host filesystem, e.g. debugfs, and
+are associated with the channel buffers using the API described below.
+
+The format of the data logged into the channel buffers is completely
+up to the kernel client; the relay interface does however provide
+hooks which allow kernel clients to impose some structure on the
+buffer data.  The relay interface doesn't implement any form of data
+filtering - this also is left to the kernel client.  The purpose is to
+keep things as simple as possible.
+
+This document provides an overview of the relay interface API.  The
+details of the function parameters are documented along with the
+functions in the relay interface code - please see that for details.
+
+Semantics
+=========
+
+Each relay channel has one buffer per CPU, each buffer has one or more
+sub-buffers.  Messages are written to the first sub-buffer until it is
+too full to contain a new message, in which case it it is written to
+the next (if available).  Messages are never split across sub-buffers.
+At this point, userspace can be notified so it empties the first
+sub-buffer, while the kernel continues writing to the next.
+
+When notified that a sub-buffer is full, the kernel knows how many
+bytes of it are padding i.e. unused space occurring because a complete
+message couldn't fit into a sub-buffer.  Userspace can use this
+knowledge to copy only valid data.
+
+After copying it, userspace can notify the kernel that a sub-buffer
+has been consumed.
+
+A relay channel can operate in a mode where it will overwrite data not
+yet collected by userspace, and not wait for it to be consumed.
+
+The relay channel itself does not provide for communication of such
+data between userspace and kernel, allowing the kernel side to remain
+simple and not impose a single interface on userspace.  It does
+provide a set of examples and a separate helper though, described
+below.
+
+The read() interface both removes padding and internally consumes the
+read sub-buffers; thus in cases where read(2) is being used to drain
+the channel buffers, special-purpose communication between kernel and
+user isn't necessary for basic operation.
+
+One of the major goals of the relay interface is to provide a low
+overhead mechanism for conveying kernel data to userspace.  While the
+read() interface is easy to use, it's not as efficient as the mmap()
+approach; the example code attempts to make the tradeoff between the
+two approaches as small as possible.
+
+klog and relay-apps example code
+================================
+
+The relay interface itself is ready to use, but to make things easier,
+a couple simple utility functions and a set of examples are provided.
+
+The relay-apps example tarball, available on the relay sourceforge
+site, contains a set of self-contained examples, each consisting of a
+pair of .c files containing boilerplate code for each of the user and
+kernel sides of a relay application.  When combined these two sets of
+boilerplate code provide glue to easily stream data to disk, without
+having to bother with mundane housekeeping chores.
+
+The 'klog debugging functions' patch (klog.patch in the relay-apps
+tarball) provides a couple of high-level logging functions to the
+kernel which allow writing formatted text or raw data to a channel,
+regardless of whether a channel to write into exists or not, or even
+whether the relay interface is compiled into the kernel or not.  These
+functions allow you to put unconditional 'trace' statements anywhere
+in the kernel or kernel modules; only when there is a 'klog handler'
+registered will data actually be logged (see the klog and kleak
+examples for details).
+
+It is of course possible to use the relay interface from scratch,
+i.e. without using any of the relay-apps example code or klog, but
+you'll have to implement communication between userspace and kernel,
+allowing both to convey the state of buffers (full, empty, amount of
+padding).  The read() interface both removes padding and internally
+consumes the read sub-buffers; thus in cases where read(2) is being
+used to drain the channel buffers, special-purpose communication
+between kernel and user isn't necessary for basic operation.  Things
+such as buffer-full conditions would still need to be communicated via
+some channel though.
+
+klog and the relay-apps examples can be found in the relay-apps
+tarball on http://relayfs.sourceforge.net
+
+The relay interface user space API
+==================================
+
+The relay interface implements basic file operations for user space
+access to relay channel buffer data.  Here are the file operations
+that are available and some comments regarding their behavior:
+
+open()     enables user to open an _existing_ channel buffer.
+
+mmap()      results in channel buffer being mapped into the caller's
+           memory space. Note that you can't do a partial mmap - you
+           must map the entire file, which is NRBUF * SUBBUFSIZE.
+
+read()      read the contents of a channel buffer.  The bytes read are
+           'consumed' by the reader, i.e. they won't be available
+           again to subsequent reads.  If the channel is being used
+           in no-overwrite mode (the default), it can be read at any
+           time even if there's an active kernel writer.  If the
+           channel is being used in overwrite mode and there are
+           active channel writers, results may be unpredictable -
+           users should make sure that all logging to the channel has
+           ended before using read() with overwrite mode.  Sub-buffer
+           padding is automatically removed and will not be seen by
+           the reader.
+
+sendfile()  transfer data from a channel buffer to an output file
+           descriptor. Sub-buffer padding is automatically removed
+           and will not be seen by the reader.
+
+poll()      POLLIN/POLLRDNORM/POLLERR supported.  User applications are
+           notified when sub-buffer boundaries are crossed.
+
+close()     decrements the channel buffer's refcount.  When the refcount
+           reaches 0, i.e. when no process or kernel client has the
+           buffer open, the channel buffer is freed.
+
+In order for a user application to make use of relay files, the
+host filesystem must be mounted.  For example,
+
+       mount -t debugfs debugfs /debug
+
+NOTE:   the host filesystem doesn't need to be mounted for kernel
+       clients to create or use channels - it only needs to be
+       mounted when user space applications need access to the buffer
+       data.
+
+
+The relay interface kernel API
+==============================
+
+Here's a summary of the API the relay interface provides to in-kernel clients:
+
+TBD(curr. line MT:/API/)
+  channel management functions:
+
+    relay_open(base_filename, parent, subbuf_size, n_subbufs,
+               callbacks)
+    relay_close(chan)
+    relay_flush(chan)
+    relay_reset(chan)
+
+  channel management typically called on instigation of userspace:
+
+    relay_subbufs_consumed(chan, cpu, subbufs_consumed)
+
+  write functions:
+
+    relay_write(chan, data, length)
+    __relay_write(chan, data, length)
+    relay_reserve(chan, length)
+
+  callbacks:
+
+    subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
+    buf_mapped(buf, filp)
+    buf_unmapped(buf, filp)
+    create_buf_file(filename, parent, mode, buf, is_global)
+    remove_buf_file(dentry)
+
+  helper functions:
+
+    relay_buf_full(buf)
+    subbuf_start_reserve(buf, length)
+
+
+Creating a channel
+------------------
+
+relay_open() is used to create a channel, along with its per-cpu
+channel buffers.  Each channel buffer will have an associated file
+created for it in the host filesystem, which can be and mmapped or
+read from in user space.  The files are named basename0...basenameN-1
+where N is the number of online cpus, and by default will be created
+in the root of the filesystem (if the parent param is NULL).  If you
+want a directory structure to contain your relay files, you should
+create it using the host filesystem's directory creation function,
+e.g. debugfs_create_dir(), and pass the parent directory to
+relay_open().  Users are responsible for cleaning up any directory
+structure they create, when the channel is closed - again the host
+filesystem's directory removal functions should be used for that,
+e.g. debugfs_remove().
+
+In order for a channel to be created and the host filesystem's files
+associated with its channel buffers, the user must provide definitions
+for two callback functions, create_buf_file() and remove_buf_file().
+create_buf_file() is called once for each per-cpu buffer from
+relay_open() and allows the user to create the file which will be used
+to represent the corresponding channel buffer.  The callback should
+return the dentry of the file created to represent the channel buffer.
+remove_buf_file() must also be defined; it's responsible for deleting
+the file(s) created in create_buf_file() and is called during
+relay_close().
+
+Here are some typical definitions for these callbacks, in this case
+using debugfs:
+
+/*
+ * create_buf_file() callback.  Creates relay file in debugfs.
+ */
+static struct dentry *create_buf_file_handler(const char *filename,
+                                              struct dentry *parent,
+                                              int mode,
+                                              struct rchan_buf *buf,
+                                              int *is_global)
+{
+        return debugfs_create_file(filename, mode, parent, buf,
+                                  &relay_file_operations);
+}
+
+/*
+ * remove_buf_file() callback.  Removes relay file from debugfs.
+ */
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+        debugfs_remove(dentry);
+
+        return 0;
+}
+
+/*
+ * relay interface callbacks
+ */
+static struct rchan_callbacks relay_callbacks =
+{
+        .create_buf_file = create_buf_file_handler,
+        .remove_buf_file = remove_buf_file_handler,
+};
+
+And an example relay_open() invocation using them:
+
+  chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks);
+
+If the create_buf_file() callback fails, or isn't defined, channel
+creation and thus relay_open() will fail.
+
+The total size of each per-cpu buffer is calculated by multiplying the
+number of sub-buffers by the sub-buffer size passed into relay_open().
+The idea behind sub-buffers is that they're basically an extension of
+double-buffering to N buffers, and they also allow applications to
+easily implement random-access-on-buffer-boundary schemes, which can
+be important for some high-volume applications.  The number and size
+of sub-buffers is completely dependent on the application and even for
+the same application, different conditions will warrant different
+values for these parameters at different times.  Typically, the right
+values to use are best decided after some experimentation; in general,
+though, it's safe to assume that having only 1 sub-buffer is a bad
+idea - you're guaranteed to either overwrite data or lose events
+depending on the channel mode being used.
+
+The create_buf_file() implementation can also be defined in such a way
+as to allow the creation of a single 'global' buffer instead of the
+default per-cpu set.  This can be useful for applications interested
+mainly in seeing the relative ordering of system-wide events without
+the need to bother with saving explicit timestamps for the purpose of
+merging/sorting per-cpu files in a postprocessing step.
+
+To have relay_open() create a global buffer, the create_buf_file()
+implementation should set the value of the is_global outparam to a
+non-zero value in addition to creating the file that will be used to
+represent the single buffer.  In the case of a global buffer,
+create_buf_file() and remove_buf_file() will be called only once.  The
+normal channel-writing functions, e.g. relay_write(), can still be
+used - writes from any cpu will transparently end up in the global
+buffer - but since it is a global buffer, callers should make sure
+they use the proper locking for such a buffer, either by wrapping
+writes in a spinlock, or by copying a write function from relay.h and
+creating a local version that internally does the proper locking.
+
+Channel 'modes'
+---------------
+
+relay channels can be used in either of two modes - 'overwrite' or
+'no-overwrite'.  The mode is entirely determined by the implementation
+of the subbuf_start() callback, as described below.  The default if no
+subbuf_start() callback is defined is 'no-overwrite' mode.  If the
+default mode suits your needs, and you plan to use the read()
+interface to retrieve channel data, you can ignore the details of this
+section, as it pertains mainly to mmap() implementations.
+
+In 'overwrite' mode, also known as 'flight recorder' mode, writes
+continuously cycle around the buffer and will never fail, but will
+unconditionally overwrite old data regardless of whether it's actually
+been consumed.  In no-overwrite mode, writes will fail, i.e. data will
+be lost, if the number of unconsumed sub-buffers equals the total
+number of sub-buffers in the channel.  It should be clear that if
+there is no consumer or if the consumer can't consume sub-buffers fast
+enough, data will be lost in either case; the only difference is
+whether data is lost from the beginning or the end of a buffer.
+
+As explained above, a relay channel is made of up one or more
+per-cpu channel buffers, each implemented as a circular buffer
+subdivided into one or more sub-buffers.  Messages are written into
+the current sub-buffer of the channel's current per-cpu buffer via the
+write functions described below.  Whenever a message can't fit into
+the current sub-buffer, because there's no room left for it, the
+client is notified via the subbuf_start() callback that a switch to a
+new sub-buffer is about to occur.  The client uses this callback to 1)
+initialize the next sub-buffer if appropriate 2) finalize the previous
+sub-buffer if appropriate and 3) return a boolean value indicating
+whether or not to actually move on to the next sub-buffer.
+
+To implement 'no-overwrite' mode, the userspace client would provide
+an implementation of the subbuf_start() callback something like the
+following:
+
+static int subbuf_start(struct rchan_buf *buf,
+                        void *subbuf,
+                       void *prev_subbuf,
+                       unsigned int prev_padding)
+{
+       if (prev_subbuf)
+               *((unsigned *)prev_subbuf) = prev_padding;
+
+       if (relay_buf_full(buf))
+               return 0;
+
+       subbuf_start_reserve(buf, sizeof(unsigned int));
+
+       return 1;
+}
+
+If the current buffer is full, i.e. all sub-buffers remain unconsumed,
+the callback returns 0 to indicate that the buffer switch should not
+occur yet, i.e. until the consumer has had a chance to read the
+current set of ready sub-buffers.  For the relay_buf_full() function
+to make sense, the consumer is reponsible for notifying the relay
+interface when sub-buffers have been consumed via
+relay_subbufs_consumed().  Any subsequent attempts to write into the
+buffer will again invoke the subbuf_start() callback with the same
+parameters; only when the consumer has consumed one or more of the
+ready sub-buffers will relay_buf_full() return 0, in which case the
+buffer switch can continue.
+
+The implementation of the subbuf_start() callback for 'overwrite' mode
+would be very similar:
+
+static int subbuf_start(struct rchan_buf *buf,
+                        void *subbuf,
+                       void *prev_subbuf,
+                       unsigned int prev_padding)
+{
+       if (prev_subbuf)
+               *((unsigned *)prev_subbuf) = prev_padding;
+
+       subbuf_start_reserve(buf, sizeof(unsigned int));
+
+       return 1;
+}
+
+In this case, the relay_buf_full() check is meaningless and the
+callback always returns 1, causing the buffer switch to occur
+unconditionally.  It's also meaningless for the client to use the
+relay_subbufs_consumed() function in this mode, as it's never
+consulted.
+
+The default subbuf_start() implementation, used if the client doesn't
+define any callbacks, or doesn't define the subbuf_start() callback,
+implements the simplest possible 'no-overwrite' mode, i.e. it does
+nothing but return 0.
+
+Header information can be reserved at the beginning of each sub-buffer
+by calling the subbuf_start_reserve() helper function from within the
+subbuf_start() callback.  This reserved area can be used to store
+whatever information the client wants.  In the example above, room is
+reserved in each sub-buffer to store the padding count for that
+sub-buffer.  This is filled in for the previous sub-buffer in the
+subbuf_start() implementation; the padding value for the previous
+sub-buffer is passed into the subbuf_start() callback along with a
+pointer to the previous sub-buffer, since the padding value isn't
+known until a sub-buffer is filled.  The subbuf_start() callback is
+also called for the first sub-buffer when the channel is opened, to
+give the client a chance to reserve space in it.  In this case the
+previous sub-buffer pointer passed into the callback will be NULL, so
+the client should check the value of the prev_subbuf pointer before
+writing into the previous sub-buffer.
+
+Writing to a channel
+--------------------
+
+Kernel clients write data into the current cpu's channel buffer using
+relay_write() or __relay_write().  relay_write() is the main logging
+function - it uses local_irqsave() to protect the buffer and should be
+used if you might be logging from interrupt context.  If you know
+you'll never be logging from interrupt context, you can use
+__relay_write(), which only disables preemption.  These functions
+don't return a value, so you can't determine whether or not they
+failed - the assumption is that you wouldn't want to check a return
+value in the fast logging path anyway, and that they'll always succeed
+unless the buffer is full and no-overwrite mode is being used, in
+which case you can detect a failed write in the subbuf_start()
+callback by calling the relay_buf_full() helper function.
+
+relay_reserve() is used to reserve a slot in a channel buffer which
+can be written to later.  This would typically be used in applications
+that need to write directly into a channel buffer without having to
+stage data in a temporary buffer beforehand.  Because the actual write
+may not happen immediately after the slot is reserved, applications
+using relay_reserve() can keep a count of the number of bytes actually
+written, either in space reserved in the sub-buffers themselves or as
+a separate array.  See the 'reserve' example in the relay-apps tarball
+at http://relayfs.sourceforge.net for an example of how this can be
+done.  Because the write is under control of the client and is
+separated from the reserve, relay_reserve() doesn't protect the buffer
+at all - it's up to the client to provide the appropriate
+synchronization when using relay_reserve().
+
+Closing a channel
+-----------------
+
+The client calls relay_close() when it's finished using the channel.
+The channel and its associated buffers are destroyed when there are no
+longer any references to any of the channel buffers.  relay_flush()
+forces a sub-buffer switch on all the channel buffers, and can be used
+to finalize and process the last sub-buffers before the channel is
+closed.
+
+Misc
+----
+
+Some applications may want to keep a channel around and re-use it
+rather than open and close a new channel for each use.  relay_reset()
+can be used for this purpose - it resets a channel to its initial
+state without reallocating channel buffer memory or destroying
+existing mappings.  It should however only be called when it's safe to
+do so, i.e. when the channel isn't currently being written to.
+
+Finally, there are a couple of utility callbacks that can be used for
+different purposes.  buf_mapped() is called whenever a channel buffer
+is mmapped from user space and buf_unmapped() is called when it's
+unmapped.  The client can use this notification to trigger actions
+within the kernel application, such as enabling/disabling logging to
+the channel.
+
+
+Resources
+=========
+
+For news, example code, mailing list, etc. see the relay interface homepage:
+
+    http://relayfs.sourceforge.net
+
+
+Credits
+=======
+
+The ideas and specs for the relay interface came about as a result of
+discussions on tracing involving the following:
+
+Michel Dagenais                <michel.dagenais@polymtl.ca>
+Richard Moore          <richardj_moore@uk.ibm.com>
+Bob Wisniewski         <bob@watson.ibm.com>
+Karim Yaghmour         <karim@opersys.com>
+Tom Zanussi            <zanussi@us.ibm.com>
+
+Also thanks to Hubertus Franke for a lot of useful suggestions and bug
+reports.
diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru
new file mode 100644 (file)
index 0000000..b2c0d61
--- /dev/null
@@ -0,0 +1,87 @@
+Kernel driver abituguru
+=======================
+
+Supported chips:
+  * Abit uGuru revision 1-3 (Hardware Monitor part only)
+    Prefix: 'abituguru'
+    Addresses scanned: ISA 0x0E0
+    Datasheet: Not available, this driver is based on reverse engineering.
+       A "Datasheet" has been written based on the reverse engineering it
+       should be available in the same dir as this file under the name
+       abituguru-datasheet.
+    Note:
+       The uGuru is a microcontroller with onboard firmware which programs
+       it to behave as a hwmon IC. There are many different revisions of the
+       firmware and thus effectivly many different revisions of the uGuru.
+       Below is an incomplete list with which revisions are used for which
+       Motherboards:
+       uGuru 1.00    ~ 1.24    (AI7, KV8-MAX3, AN7) (1)
+       uGuru 2.0.0.0 ~ 2.0.4.2 (KV8-PRO)
+       uGuru 2.1.0.0 ~ 2.1.2.8 (AS8, AV8, AA8, AG8, AA8XE, AX8)
+       uGuru 2.2.0.0 ~ 2.2.0.6 (AA8 Fatal1ty)
+       uGuru 2.3.0.0 ~ 2.3.0.9 (AN8)
+       uGuru 3.0.0.0 ~ 3.0.1.2 (AW8, AL8, NI8)
+       uGuru 4.xxxxx?          (AT8 32X) (2)
+       1) For revisions 2 and 3 uGuru's the driver can autodetect the
+          sensortype (Volt or Temp) for bank1 sensors, for revision 1 uGuru's
+          this doesnot always work. For these uGuru's the autodection can
+          be overriden with the bank1_types module param. For all 3 known
+          revison 1 motherboards the correct use of this param is:
+          bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1
+          You may also need to specify the fan_sensors option for these boards
+          fan_sensors=5
+       2) The current version of the abituguru driver is known to NOT work
+          on these Motherboards
+
+Authors:
+       Hans de Goede <j.w.r.degoede@hhs.nl>,
+       (Initial reverse engineering done by Olle Sandberg
+        <ollebull@gmail.com>)
+
+
+Module Parameters
+-----------------
+
+* force: bool          Force detection. Note this parameter only causes the
+                       detection to be skipped, if the uGuru can't be read
+                       the module initialization (insmod) will still fail.
+* bank1_types: int[]   Bank1 sensortype autodetection override:
+                         -1 autodetect (default)
+                          0 volt sensor
+                          1 temp sensor
+                          2 not connected
+* fan_sensors: int     Tell the driver how many fan speed sensors there are
+                       on your motherboard. Default: 0 (autodetect).
+* pwms: int            Tell the driver how many fan speed controls (fan
+                       pwms) your motherboard has. Default: 0 (autodetect).
+* verbose: int         How verbose should the driver be? (0-3):
+                          0 normal output
+                          1 + verbose error reporting
+                          2 + sensors type probing info (default)
+                          3 + retryable error reporting
+                       Default: 2 (the driver is still in the testing phase)
+
+Notice if you need any of the first three options above please insmod the
+driver with verbose set to 3 and mail me <j.w.r.degoede@hhs.nl> the output of:
+dmesg | grep abituguru
+
+
+Description
+-----------
+
+This driver supports the hardware monitoring features of the Abit uGuru chip
+found on Abit uGuru featuring motherboards (most modern Abit motherboards).
+
+The uGuru chip in reality is a Winbond W83L950D in disguise (despite Abit
+claiming it is "a new microprocessor designed by the ABIT Engineers").
+Unfortunatly this doesn't help since the W83L950D is a generic
+microcontroller with a custom Abit application running on it.
+
+Despite Abit not releasing any information regarding the uGuru, Olle
+Sandberg <ollebull@gmail.com> has managed to reverse engineer the sensor part
+of the uGuru. Without his work this driver would not have been possible.
+
+Known Issues
+------------
+
+The voltage and frequency control parts of the Abit uGuru are not supported.
diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet
new file mode 100644 (file)
index 0000000..aef5a9b
--- /dev/null
@@ -0,0 +1,312 @@
+uGuru datasheet
+===============
+
+First of all, what I know about uGuru is no fact based on any help, hints or
+datasheet from Abit. The data I have got on uGuru have I assembled through
+my weak knowledge in "backwards engineering".
+And just for the record, you may have noticed uGuru isn't a chip developed by
+Abit, as they claim it to be. It's realy just an microprocessor (uC) created by
+Winbond (W83L950D). And no, reading the manual for this specific uC or
+mailing  Windbond for help won't give any usefull data about uGuru, as it is
+the program inside the uC that is responding to calls.
+
+Olle Sandberg <ollebull@gmail.com>, 2005-05-25
+
+
+Original version by Olle Sandberg who did the heavy lifting of the initial
+reverse engineering. This version has been almost fully rewritten for clarity
+and extended with write support and info on more databanks, the write support
+is once again reverse engineered by Olle the additional databanks have been
+reverse engineered by me. I would like to express my thanks to Olle, this
+document and the Linux driver could not have been written without his efforts.
+
+Note: because of the lack of specs only the sensors part of the uGuru is
+described here and not the CPU / RAM / etc voltage & frequency control.
+
+Hans de Goede <j.w.r.degoede@hhs.nl>, 28-01-2006
+
+
+Detection
+=========
+
+As far as known the uGuru is always placed at and using the (ISA) I/O-ports
+0xE0 and 0xE4, so we don't have to scan any port-range, just check what the two
+ports are holding for detection. We will refer to 0xE0 as CMD (command-port)
+and 0xE4 as DATA because Abit refers to them with these names.
+
+If DATA holds 0x00 or 0x08 and CMD holds 0x00 or 0xAC an uGuru could be
+present. We have to check for two different values at data-port, because
+after a reboot uGuru will hold 0x00 here, but if the driver is removed and
+later on attached again data-port will hold 0x08, more about this later.
+
+After wider testing of the Linux kernel driver some variants of the uGuru have
+turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also
+have to test CMD for two different values. On these uGuru's DATA will initally
+hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read
+first!
+
+To be really sure an uGuru is present a test read of one or more register
+sets should be done.
+
+
+Reading / Writing
+=================
+
+Addressing
+----------
+
+The uGuru has a number of different addressing levels. The first addressing
+level we will call banks. A bank holds data for one or more sensors. The data
+in a bank for a sensor is one or more bytes large.
+
+The number of bytes is fixed for a given bank, you should always read or write
+that many bytes, reading / writing more will fail, the results when writing
+less then the number of bytes for a given bank are undetermined.
+
+See below for all known bank addresses, numbers of sensors in that bank,
+number of bytes data per sensor and contents/meaning of those bytes.
+
+Although both this document and the kernel driver have kept the sensor
+terminoligy for the addressing within a bank this is not 100% correct, in
+bank 0x24 for example the addressing within the bank selects a PWM output not
+a sensor.
+
+Notice that some banks have both a read and a write address this is how the
+uGuru determines if a read from or a write to the bank is taking place, thus
+when reading you should always use the read address and when writing the
+write address. The write address is always one (1) more then the read address.
+
+
+uGuru ready
+-----------
+
+Before you can read from or write to the uGuru you must first put the uGuru
+in "ready" mode.
+
+To put the uGuru in ready mode first write 0x00 to DATA and then wait for DATA
+to hold 0x09, DATA should read 0x09 within 250 read cycles.
+
+Next CMD _must_ be read and should hold 0xAC, usually CMD will hold 0xAC the
+first read but sometimes it takes a while before CMD holds 0xAC and thus it
+has to be read a number of times (max 50).
+
+After reading CMD, DATA should hold 0x08 which means that the uGuru is ready
+for input. As above DATA will usually hold 0x08 the first read but not always.
+This step can be skipped, but it is undetermined what happens if the uGuru has
+not yet reported 0x08 at DATA and you proceed with writing a bank address.
+
+
+Sending bank and sensor addresses to the uGuru
+----------------------------------------------
+
+First the uGuru must be in "ready" mode as described above, DATA should hold
+0x08 indicating that the uGuru wants input, in this case the bank address.
+
+Next write the bank address to DATA. After the bank address has been written
+wait for to DATA to hold 0x08 again indicating that it wants / is ready for
+more input (max 250 reads).
+
+Once DATA holds 0x08 again write the sensor address to CMD.
+
+
+Reading
+-------
+
+First send the bank and sensor addresses as described above.
+Then for each byte of data you want to read wait for DATA to hold 0x01
+which indicates that the uGuru is ready to be read (max 250 reads) and once
+DATA holds 0x01 read the byte from CMD.
+
+Once all bytes have been read data will hold 0x09, but there is no reason to
+test for this. Notice that the number of bytes is bank address dependent see
+above and below.
+
+After completing a successfull read it is advised to put the uGuru back in
+ready mode, so that it is ready for the next read / write cycle. This way
+if your program / driver is unloaded and later loaded again the detection
+algorithm described above will still work.
+
+
+
+Writing
+-------
+
+First send the bank and sensor addresses as described above.
+Then for each byte of data you want to write wait for DATA to hold 0x00
+which indicates that the uGuru is ready to be written (max 250 reads) and
+once DATA holds 0x00 write the byte to CMD.
+
+Once all bytes have been written wait for DATA to hold 0x01 (max 250 reads)
+don't ask why this is the way it is.
+
+Once DATA holds 0x01 read CMD it should hold 0xAC now.
+
+After completing a successfull write it is advised to put the uGuru back in
+ready mode, so that it is ready for the next read / write cycle. This way
+if your program / driver is unloaded and later loaded again the detection
+algorithm described above will still work.
+
+
+Gotchas
+-------
+
+After wider testing of the Linux kernel driver some variants of the uGuru have
+turned up which do not hold 0x08 at DATA within 250 reads after writing the
+bank address. With these versions this happens quite frequent, using larger
+timeouts doesn't help, they just go offline for a second or 2, doing some
+internal callibration or whatever. Your code should be prepared to handle
+this and in case of no response in this specific case just goto sleep for a
+while and then retry.
+
+
+Address Map
+===========
+
+Bank 0x20 Alarms (R)
+--------------------
+This bank contains 0 sensors, iow the sensor address is ignored (but must be
+written) just use 0. Bank 0x20 contains 3 bytes:
+
+Byte 0:
+This byte holds the alarm flags for sensor 0-7 of Sensor Bank1, with bit 0
+corresponding to sensor 0, 1 to 1, etc.
+
+Byte 1:
+This byte holds the alarm flags for sensor 8-15 of Sensor Bank1, with bit 0
+corresponding to sensor 8, 1 to 9, etc.
+
+Byte 2:
+This byte holds the alarm flags for sensor 0-5 of Sensor Bank2, with bit 0
+corresponding to sensor 0, 1 to 1, etc.
+
+
+Bank 0x21 Sensor Bank1 Values / Readings (R)
+--------------------------------------------
+This bank contains 16 sensors, for each sensor it contains 1 byte.
+So far the following sensors are known to be available on all motherboards:
+Sensor  0 CPU temp
+Sensor  1 SYS temp
+Sensor  3 CPU core volt
+Sensor  4 DDR volt
+Sensor 10 DDR Vtt volt
+Sensor 15 PWM temp
+
+Byte 0:
+This byte holds the reading from the sensor. Sensors in Bank1 can be both
+volt and temp sensors, this is motherboard specific. The uGuru however does
+seem to know (be programmed with) what kindoff sensor is attached see Sensor
+Bank1 Settings description.
+
+Volt sensors use a linear scale, a reading 0 corresponds with 0 volt and a
+reading of 255 with 3494 mV. The sensors for higher voltages however are
+connected through a division circuit. The currently known division circuits
+in use result in ranges of: 0-4361mV, 0-6248mV or 0-14510mV. 3.3 volt sources
+use the 0-4361mV range, 5 volt the 0-6248mV and 12 volt the 0-14510mV .
+
+Temp sensors also use a linear scale, a reading of 0 corresponds with 0 degree
+Celsius and a reading of 255 with a reading of 255 degrees Celsius.
+
+
+Bank 0x22 Sensor Bank1 Settings (R)
+Bank 0x23 Sensor Bank1 Settings (W)
+-----------------------------------
+
+This bank contains 16 sensors, for each sensor it contains 3 bytes. Each
+set of 3 bytes contains the settings for the sensor with the same sensor
+address in Bank 0x21 .
+
+Byte 0:
+Alarm behaviour for the selected sensor. A 1 enables the described behaviour.
+Bit 0: Give an alarm if measured temp is over the warning threshold    (RW) *
+Bit 1: Give an alarm if measured volt is over the max threshold                (RW) **
+Bit 2: Give an alarm if measured volt is under the min threshold       (RW) **
+Bit 3: Beep if alarm                                                   (RW)
+Bit 4: 1 if alarm cause measured temp is over the warning threshold    (R)
+Bit 5: 1 if alarm cause measured volt is over the max threshold                (R)
+Bit 6: 1 if alarm cause measured volt is under the min threshold       (R)
+Bit 7: Volt sensor: Shutdown if alarm persist for more then 4 seconds  (RW)
+       Temp sensor: Shutdown if temp is over the shutdown threshold    (RW)
+
+*  This bit is only honored/used by the uGuru if a temp sensor is connected
+** This bit is only honored/used by the uGuru if a volt sensor is connected
+Note with some trickery this can be used to find out what kinda sensor is
+detected see the Linux kernel driver for an example with many comments on
+how todo this.
+
+Byte 1:
+Temp sensor: warning threshold  (scale as bank 0x21)
+Volt sensor: min threshold      (scale as bank 0x21)
+
+Byte 2:
+Temp sensor: shutdown threshold (scale as bank 0x21)
+Volt sensor: max threshold      (scale as bank 0x21)
+
+
+Bank 0x24 PWM outputs for FAN's (R)
+Bank 0x25 PWM outputs for FAN's (W)
+-----------------------------------
+
+This bank contains 3 "sensors", for each sensor it contains 5 bytes.
+Sensor 0 usually controls the CPU fan
+Sensor 1 usually controls the NB (or chipset for single chip) fan
+Sensor 2 usually controls the System fan
+
+Byte 0:
+Flag 0x80 to enable control, Fan runs at 100% when disabled.
+low nibble (temp)sensor address at bank 0x21 used for control.
+
+Byte 1:
+0-255 = 0-12v (linear), specify voltage at which fan will rotate when under
+low threshold temp (specified in byte 3)
+
+Byte 2:
+0-255 = 0-12v (linear), specify voltage at which fan will rotate when above
+high threshold temp (specified in byte 4)
+
+Byte 3:
+Low threshold temp  (scale as bank 0x21)
+
+byte 4:
+High threshold temp (scale as bank 0x21)
+
+
+Bank 0x26 Sensors Bank2 Values / Readings (R)
+---------------------------------------------
+
+This bank contains 6 sensors (AFAIK), for each sensor it contains 1 byte.
+So far the following sensors are known to be available on all motherboards:
+Sensor 0: CPU fan speed
+Sensor 1: NB (or chipset for single chip) fan speed
+Sensor 2: SYS fan speed
+
+Byte 0:
+This byte holds the reading from the sensor. 0-255 = 0-15300 (linear)
+
+
+Bank 0x27 Sensors Bank2 Settings (R)
+Bank 0x28 Sensors Bank2 Settings (W)
+------------------------------------
+
+This bank contains 6 sensors (AFAIK), for each sensor it contains 2 bytes.
+
+Byte 0:
+Alarm behaviour for the selected sensor. A 1 enables the described behaviour.
+Bit 0: Give an alarm if measured rpm is under the min threshold        (RW)
+Bit 3: Beep if alarm                                           (RW)
+Bit 7: Shutdown if alarm persist for more then 4 seconds       (RW)
+
+Byte 1:
+min threshold (scale as bank 0x26)
+
+
+Warning for the adventerous
+===========================
+
+A word of caution to those who want to experiment and see if they can figure
+the voltage / clock programming out, I tried reading and only reading banks
+0-0x30 with the reading code used for the sensor banks (0x20-0x28) and this
+resulted in a _permanent_ reprogramming of the voltages, luckily I had the
+sensors part configured so that it would shutdown my system on any out of spec
+voltages which proprably safed my computer (after a reboot I managed to
+immediatly enter the bios and reload the defaults). This probably means that
+the read/write cycle for the non sensor part is different from the sensor part.
diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70
new file mode 100644 (file)
index 0000000..2bdd3fe
--- /dev/null
@@ -0,0 +1,31 @@
+Kernel driver lm70
+==================
+
+Supported chip:
+  * National Semiconductor LM70
+    Datasheet: http://www.national.com/pf/LM/LM70.html
+
+Author:
+        Kaiwan N Billimoria <kaiwan@designergraphix.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM70
+temperature sensor.
+
+The LM70 temperature sensor chip supports a single temperature sensor.
+It communicates with a host processor (or microcontroller) via an
+SPI/Microwire Bus interface.
+
+Communication with the LM70 is simple: when the temperature is to be sensed,
+the driver accesses the LM70 using SPI communication: 16 SCLK cycles
+comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's
+complement digital temperature (sent via the SIO line), is available in the
+driver for interpretation. This driver makes use of the kernel's in-core
+SPI support.
+
+Thanks to
+---------
+Jean Delvare <khali@linux-fr.org> for mentoring the hwmon-side driver
+development.
diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192
new file mode 100644 (file)
index 0000000..45d6453
--- /dev/null
@@ -0,0 +1,102 @@
+Kernel driver smsc47m192
+========================
+
+Supported chips:
+  * SMSC LPC47M192 and LPC47M997
+    Prefix: 'smsc47m192'
+    Addresses scanned: I2C 0x2c - 0x2d
+    Datasheet: The datasheet for LPC47M192 is publicly available from
+               http://www.smsc.com/
+               The LPC47M997 is compatible for hardware monitoring.
+
+Author: Hartmut Rick <linux@rick.claranet.de>
+        Special thanks to Jean Delvare for careful checking
+        of the code and many helpful comments and suggestions.
+
+
+Description
+-----------
+
+This driver implements support for the hardware sensor capabilities
+of the SMSC LPC47M192 and LPC47M997 Super-I/O chips.
+
+These chips support 3 temperature channels and 8 voltage inputs
+as well as CPU voltage VID input.
+
+They do also have fan monitoring and control capabilities, but the
+these features are accessed via ISA bus and are not supported by this
+driver. Use the 'smsc47m1' driver for fan monitoring and control.
+
+Voltages and temperatures are measured by an 8-bit ADC, the resolution
+of the temperatures is 1 bit per degree C.
+Voltages are scaled such that the nominal voltage corresponds to
+192 counts, i.e. 3/4 of the full range. Thus the available range for
+each voltage channel is 0V ... 255/192*(nominal voltage), the resolution
+is 1 bit per (nominal voltage)/192.
+Both voltage and temperature values are scaled by 1000, the sys files
+show voltages in mV and temperatures in units of 0.001 degC.
+
+The +12V analog voltage input channel (in4_input) is multiplexed with
+bit 4 of the encoded CPU voltage. This means that you either get
+a +12V voltage measurement or a 5 bit CPU VID, but not both.
+The default setting is to use the pin as 12V input, and use only 4 bit VID.
+This driver assumes that the information in the configuration register
+is correct, i.e. that the BIOS has updated the configuration if
+the motherboard has this input wired to VID4.
+
+The temperature and voltage readings are updated once every 1.5 seconds.
+Reading them more often repeats the same values.
+
+
+sysfs interface
+---------------
+
+in0_input      - +2.5V voltage input
+in1_input      - CPU voltage input (nominal 2.25V)
+in2_input      - +3.3V voltage input
+in3_input      - +5V voltage input
+in4_input      - +12V voltage input (may be missing if used as VID4)
+in5_input      - Vcc voltage input (nominal 3.3V)
+                 This is the supply voltage of the sensor chip itself.
+in6_input      - +1.5V voltage input
+in7_input      - +1.8V voltage input
+
+in[0-7]_min,
+in[0-7]_max    - lower and upper alarm thresholds for in[0-7]_input reading
+
+                 All voltages are read and written in mV.
+
+in[0-7]_alarm  - alarm flags for voltage inputs
+                 These files read '1' in case of alarm, '0' otherwise.
+
+temp1_input    - chip temperature measured by on-chip diode
+temp[2-3]_input        - temperature measured by external diodes (one of these would
+                 typically be wired to the diode inside the CPU)
+
+temp[1-3]_min,
+temp[1-3]_max  - lower and upper alarm thresholds for temperatures
+
+temp[1-3]_offset - temperature offset registers
+                 The chip adds the offsets stored in these registers to
+                 the corresponding temperature readings.
+                 Note that temp1 and temp2 offsets share the same register,
+                 they cannot both be different from zero at the same time.
+                 Writing a non-zero number to one of them will reset the other
+                 offset to zero.
+
+                 All temperatures and offsets are read and written in
+                 units of 0.001 degC.
+
+temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm,
+                 '0' otherwise.
+temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3.
+                 A fault is detected if the two pins for the corresponding
+                 sensor are open or shorted, or any of the two is shorted
+                 to ground or Vcc. '1' indicates a diode fault.
+
+cpu0_vid       - CPU voltage as received from the CPU
+
+vrm            - CPU VID standard used for decoding CPU voltage
+
+                 The *_min, *_max, *_offset and vrm files can be read and
+                 written, all others are read-only.
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
new file mode 100644 (file)
index 0000000..83a3836
--- /dev/null
@@ -0,0 +1,113 @@
+Kernel driver w83791d
+=====================
+
+Supported chips:
+  * Winbond W83791D
+    Prefix: 'w83791d'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf
+
+Author: Charles Spirakis <bezaur@gmail.com>
+
+This driver was derived from the w83781d.c and w83792d.c source files.
+
+Credits:
+  w83781d.c:
+    Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>,
+    and Mark Studebaker <mdsxyz123@yahoo.com>
+  w83792d.c:
+    Chunhao Huang <DZShen@Winbond.com.tw>,
+    Rudolf Marek <r.marek@sh.cvut.cz>
+
+Module Parameters
+-----------------
+
+* init boolean
+  (default 0)
+  Use 'init=1' to have the driver do extra software initializations.
+  The default behavior is to do the minimum initialization possible
+  and depend on the BIOS to properly setup the chip. If you know you
+  have a w83791d and you're having problems, try init=1 before trying
+  reset=1.
+
+* reset boolean
+  (default 0)
+  Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default
+  behavior is no chip reset to preserve BIOS settings.
+
+* force_subclients=bus,caddr,saddr,saddr
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
+  to force the subclients of chip 0x2f on bus 0 to i2c addresses
+  0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for the Winbond W83791D chip.
+
+Detection of the chip can sometimes be foiled because it can be in an
+internal state that allows no clean access (Bank with ID register is not
+currently selected). If you know the address of the chip, use a 'force'
+parameter; this will put it into a more well-behaved state first.
+
+The driver implements three temperature sensors, five fan rotation speed
+sensors, and ten voltage sensors.
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
+the temperature gets higher than the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3
+and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more
+range or accuracy.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+Alarms are provided as output from a "realtime status register". The
+following bits are defined:
+
+bit - alarm on:
+0  - Vcore
+1  - VINR0
+2  - +3.3VIN
+3  - 5VDD
+4  - temp1
+5  - temp2
+6  - fan1
+7  - fan2
+8  - +12VIN
+9  - -12VIN
+10 - -5VIN
+11 - fan3
+12 - chassis
+13 - temp3
+14 - VINR1
+15 - reserved
+16 - tart1
+17 - tart2
+18 - tart3
+19 - VSB
+20 - VBAT
+21 - fan4
+22 - fan5
+23 - reserved
+
+When an alarm goes off, you can be warned by a beeping signal through your
+computer speaker. It is possible to enable all beeping globally, or only
+the beeping for some alarms.
+
+The driver only reads the chip values each 3 seconds; reading them more
+often will do no harm, but will return 'old' values.
+
+W83791D TODO:
+---------------
+Provide a patch for per-file alarms as discussed on the mailing list
+Provide a patch for smart-fan control (still need appropriate motherboard/fans)
diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores
new file mode 100644 (file)
index 0000000..cfcebb1
--- /dev/null
@@ -0,0 +1,51 @@
+Kernel driver i2c-ocores
+
+Supported adapters:
+  * OpenCores.org I2C controller by Richard Herveille (see datasheet link)
+    Datasheet: http://www.opencores.org/projects.cgi/web/i2c/overview
+
+Author: Peter Korsgaard <jacmet@sunsite.dk>
+
+Description
+-----------
+
+i2c-ocores is an i2c bus driver for the OpenCores.org I2C controller
+IP core by Richard Herveille.
+
+Usage
+-----
+
+i2c-ocores uses the platform bus, so you need to provide a struct
+platform_device with the base address and interrupt number. The
+dev.platform_data of the device should also point to a struct
+ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
+distance between registers and the input clock speed.
+
+E.G. something like:
+
+static struct resource ocores_resources[] = {
+       [0] = {
+               .start  = MYI2C_BASEADDR,
+               .end    = MYI2C_BASEADDR + 8,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = MYI2C_IRQ,
+               .end    = MYI2C_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct ocores_i2c_platform_data myi2c_data = {
+       .regstep        = 2,            /* two bytes between registers */
+       .clock_khz      = 50000,        /* input clock of 50MHz */
+};
+
+static struct platform_device myi2c = {
+       .name                   = "ocores-i2c",
+       .dev = {
+               .platform_data  = &myi2c_data,
+       },
+       .num_resources          = ARRAY_SIZE(ocores_resources),
+       .resource               = ocores_resources,
+};
diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt
new file mode 100644 (file)
index 0000000..38f9a52
--- /dev/null
@@ -0,0 +1,208 @@
+                MEMORY ATTRIBUTE ALIASING ON IA-64
+
+                          Bjorn Helgaas
+                      <bjorn.helgaas@hp.com>
+                           May 4, 2006
+
+
+MEMORY ATTRIBUTES
+
+    Itanium supports several attributes for virtual memory references.
+    The attribute is part of the virtual translation, i.e., it is
+    contained in the TLB entry.  The ones of most interest to the Linux
+    kernel are:
+
+       WB              Write-back (cacheable)
+       UC              Uncacheable
+       WC              Write-coalescing
+
+    System memory typically uses the WB attribute.  The UC attribute is
+    used for memory-mapped I/O devices.  The WC attribute is uncacheable
+    like UC is, but writes may be delayed and combined to increase
+    performance for things like frame buffers.
+
+    The Itanium architecture requires that we avoid accessing the same
+    page with both a cacheable mapping and an uncacheable mapping[1].
+
+    The design of the chipset determines which attributes are supported
+    on which regions of the address space.  For example, some chipsets
+    support either WB or UC access to main memory, while others support
+    only WB access.
+
+MEMORY MAP
+
+    Platform firmware describes the physical memory map and the
+    supported attributes for each region.  At boot-time, the kernel uses
+    the EFI GetMemoryMap() interface.  ACPI can also describe memory
+    devices and the attributes they support, but Linux/ia64 currently
+    doesn't use this information.
+
+    The kernel uses the efi_memmap table returned from GetMemoryMap() to
+    learn the attributes supported by each region of physical address
+    space.  Unfortunately, this table does not completely describe the
+    address space because some machines omit some or all of the MMIO
+    regions from the map.
+
+    The kernel maintains another table, kern_memmap, which describes the
+    memory Linux is actually using and the attribute for each region.
+    This contains only system memory; it does not contain MMIO space.
+
+    The kern_memmap table typically contains only a subset of the system
+    memory described by the efi_memmap.  Linux/ia64 can't use all memory
+    in the system because of constraints imposed by the identity mapping
+    scheme.
+
+    The efi_memmap table is preserved unmodified because the original
+    boot-time information is required for kexec.
+
+KERNEL IDENTITY MAPPINGS
+
+    Linux/ia64 identity mappings are done with large pages, currently
+    either 16MB or 64MB, referred to as "granules."  Cacheable mappings
+    are speculative[2], so the processor can read any location in the
+    page at any time, independent of the programmer's intentions.  This
+    means that to avoid attribute aliasing, Linux can create a cacheable
+    identity mapping only when the entire granule supports cacheable
+    access.
+
+    Therefore, kern_memmap contains only full granule-sized regions that
+    can referenced safely by an identity mapping.
+
+    Uncacheable mappings are not speculative, so the processor will
+    generate UC accesses only to locations explicitly referenced by
+    software.  This allows UC identity mappings to cover granules that
+    are only partially populated, or populated with a combination of UC
+    and WB regions.
+
+USER MAPPINGS
+
+    User mappings are typically done with 16K or 64K pages.  The smaller
+    page size allows more flexibility because only 16K or 64K has to be
+    homogeneous with respect to memory attributes.
+
+POTENTIAL ATTRIBUTE ALIASING CASES
+
+    There are several ways the kernel creates new mappings:
+
+    mmap of /dev/mem
+
+       This uses remap_pfn_range(), which creates user mappings.  These
+       mappings may be either WB or UC.  If the region being mapped
+       happens to be in kern_memmap, meaning that it may also be mapped
+       by a kernel identity mapping, the user mapping must use the same
+       attribute as the kernel mapping.
+
+       If the region is not in kern_memmap, the user mapping should use
+       an attribute reported as being supported in the EFI memory map.
+
+       Since the EFI memory map does not describe MMIO on some
+       machines, this should use an uncacheable mapping as a fallback.
+
+    mmap of /sys/class/pci_bus/.../legacy_mem
+
+       This is very similar to mmap of /dev/mem, except that legacy_mem
+       only allows mmap of the one megabyte "legacy MMIO" area for a
+       specific PCI bus.  Typically this is the first megabyte of
+       physical address space, but it may be different on machines with
+       several VGA devices.
+
+       "X" uses this to access VGA frame buffers.  Using legacy_mem
+       rather than /dev/mem allows multiple instances of X to talk to
+       different VGA cards.
+
+       The /dev/mem mmap constraints apply.
+
+       However, since this is for mapping legacy MMIO space, WB access
+       does not make sense.  This matters on machines without legacy
+       VGA support: these machines may have WB memory for the entire
+       first megabyte (or even the entire first granule).
+
+       On these machines, we could mmap legacy_mem as WB, which would
+       be safe in terms of attribute aliasing, but X has no way of
+       knowing that it is accessing regular memory, not a frame buffer,
+       so the kernel should fail the mmap rather than doing it with WB.
+
+    read/write of /dev/mem
+
+       This uses copy_from_user(), which implicitly uses a kernel
+       identity mapping.  This is obviously safe for things in
+       kern_memmap.
+
+       There may be corner cases of things that are not in kern_memmap,
+       but could be accessed this way.  For example, registers in MMIO
+       space are not in kern_memmap, but could be accessed with a UC
+       mapping.  This would not cause attribute aliasing.  But
+       registers typically can be accessed only with four-byte or
+       eight-byte accesses, and the copy_from_user() path doesn't allow
+       any control over the access size, so this would be dangerous.
+
+    ioremap()
+
+       This returns a kernel identity mapping for use inside the
+       kernel.
+
+       If the region is in kern_memmap, we should use the attribute
+       specified there.  Otherwise, if the EFI memory map reports that
+       the entire granule supports WB, we should use that (granules
+       that are partially reserved or occupied by firmware do not appear
+       in kern_memmap).  Otherwise, we should use a UC mapping.
+
+PAST PROBLEM CASES
+
+    mmap of various MMIO regions from /dev/mem by "X" on Intel platforms
+
+      The EFI memory map may not report these MMIO regions.
+
+      These must be allowed so that X will work.  This means that
+      when the EFI memory map is incomplete, every /dev/mem mmap must
+      succeed.  It may create either WB or UC user mappings, depending
+      on whether the region is in kern_memmap or the EFI memory map.
+
+    mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
+
+      See https://bugzilla.novell.com/show_bug.cgi?id=140858.
+
+      The EFI memory map reports the following attributes:
+        0x00000-0x9FFFF WB only
+        0xA0000-0xBFFFF UC only (VGA frame buffer)
+        0xC0000-0xFFFFF WB only
+
+      This mmap is done with user pages, not kernel identity mappings,
+      so it is safe to use WB mappings.
+
+      The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
+      which will use a granule-sized UC mapping covering 0-0xFFFFF.  This
+      granule covers some WB-only memory, but since UC is non-speculative,
+      the processor will never generate an uncacheable reference to the
+      WB-only areas unless the driver explicitly touches them.
+
+    mmap of 0x0-0xFFFFF legacy_mem by "X"
+
+      If the EFI memory map reports this entire range as WB, there
+      is no VGA MMIO hole, and the mmap should fail or be done with
+      a WB mapping.
+
+      There's no easy way for X to determine whether the 0xA0000-0xBFFFF
+      region is a frame buffer or just memory, so I think it's best to
+      just fail this mmap request rather than using a WB mapping.  As
+      far as I know, there's no need to map legacy_mem with WB
+      mappings.
+
+      Otherwise, a UC mapping of the entire region is probably safe.
+      The VGA hole means the region will not be in kern_memmap.  The
+      HP sx1000 chipset doesn't support UC access to the memory surrounding
+      the VGA hole, but X doesn't need that area anyway and should not
+      reference it.
+
+    mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
+
+      The EFI memory map reports the following attributes:
+        0x00000-0xFFFFF WB only (no VGA MMIO hole)
+
+      This is a special case of the previous case, and the mmap should
+      fail for the same reason as above.
+
+NOTES
+
+    [1] SDM rev 2.2, vol 2, sec 4.4.1.
+    [2] SDM rev 2.2, vol 2, sec 4.4.6.
diff --git a/Documentation/irqflags-tracing.txt b/Documentation/irqflags-tracing.txt
new file mode 100644 (file)
index 0000000..6a44487
--- /dev/null
@@ -0,0 +1,57 @@
+IRQ-flags state tracing
+
+started by Ingo Molnar <mingo@redhat.com>
+
+the "irq-flags tracing" feature "traces" hardirq and softirq state, in
+that it gives interested subsystems an opportunity to be notified of
+every hardirqs-off/hardirqs-on, softirqs-off/softirqs-on event that
+happens in the kernel.
+
+CONFIG_TRACE_IRQFLAGS_SUPPORT is needed for CONFIG_PROVE_SPIN_LOCKING
+and CONFIG_PROVE_RW_LOCKING to be offered by the generic lock debugging
+code. Otherwise only CONFIG_PROVE_MUTEX_LOCKING and
+CONFIG_PROVE_RWSEM_LOCKING will be offered on an architecture - these
+are locking APIs that are not used in IRQ context. (the one exception
+for rwsems is worked around)
+
+architecture support for this is certainly not in the "trivial"
+category, because lots of lowlevel assembly code deal with irq-flags
+state changes. But an architecture can be irq-flags-tracing enabled in a
+rather straightforward and risk-free manner.
+
+Architectures that want to support this need to do a couple of
+code-organizational changes first:
+
+- move their irq-flags manipulation code from their asm/system.h header
+  to asm/irqflags.h
+
+- rename local_irq_disable()/etc to raw_local_irq_disable()/etc. so that
+  the linux/irqflags.h code can inject callbacks and can construct the
+  real local_irq_disable()/etc APIs.
+
+- add and enable TRACE_IRQFLAGS_SUPPORT in their arch level Kconfig file
+
+and then a couple of functional changes are needed as well to implement
+irq-flags-tracing support:
+
+- in lowlevel entry code add (build-conditional) calls to the
+  trace_hardirqs_off()/trace_hardirqs_on() functions. The lock validator
+  closely guards whether the 'real' irq-flags matches the 'virtual'
+  irq-flags state, and complains loudly (and turns itself off) if the
+  two do not match. Usually most of the time for arch support for
+  irq-flags-tracing is spent in this state: look at the lockdep
+  complaint, try to figure out the assembly code we did not cover yet,
+  fix and repeat. Once the system has booted up and works without a
+  lockdep complaint in the irq-flags-tracing functions arch support is
+  complete.
+- if the architecture has non-maskable interrupts then those need to be
+  excluded from the irq-tracing [and lock validation] mechanism via
+  lockdep_off()/lockdep_on().
+
+in general there is no risk from having an incomplete irq-flags-tracing
+implementation in an architecture: lockdep will detect that and will
+turn itself off. I.e. the lock validator will still be reliable. There
+should be no crashes due to irq-tracing bugs. (except if the assembly
+changes break other code by modifying conditions or registers that
+shouldnt be)
+
diff --git a/Documentation/lockdep-design.txt b/Documentation/lockdep-design.txt
new file mode 100644 (file)
index 0000000..00d9360
--- /dev/null
@@ -0,0 +1,197 @@
+Runtime locking correctness validator
+=====================================
+
+started by Ingo Molnar <mingo@redhat.com>
+additions by Arjan van de Ven <arjan@linux.intel.com>
+
+Lock-class
+----------
+
+The basic object the validator operates upon is a 'class' of locks.
+
+A class of locks is a group of locks that are logically the same with
+respect to locking rules, even if the locks may have multiple (possibly
+tens of thousands of) instantiations. For example a lock in the inode
+struct is one class, while each inode has its own instantiation of that
+lock class.
+
+The validator tracks the 'state' of lock-classes, and it tracks
+dependencies between different lock-classes. The validator maintains a
+rolling proof that the state and the dependencies are correct.
+
+Unlike an lock instantiation, the lock-class itself never goes away: when
+a lock-class is used for the first time after bootup it gets registered,
+and all subsequent uses of that lock-class will be attached to this
+lock-class.
+
+State
+-----
+
+The validator tracks lock-class usage history into 5 separate state bits:
+
+- 'ever held in hardirq context'                    [ == hardirq-safe   ]
+- 'ever held in softirq context'                    [ == softirq-safe   ]
+- 'ever held with hardirqs enabled'                 [ == hardirq-unsafe ]
+- 'ever held with softirqs and hardirqs enabled'    [ == softirq-unsafe ]
+
+- 'ever used'                                       [ == !unused        ]
+
+Single-lock state rules:
+------------------------
+
+A softirq-unsafe lock-class is automatically hardirq-unsafe as well. The
+following states are exclusive, and only one of them is allowed to be
+set for any lock-class:
+
+ <hardirq-safe> and <hardirq-unsafe>
+ <softirq-safe> and <softirq-unsafe>
+
+The validator detects and reports lock usage that violate these
+single-lock state rules.
+
+Multi-lock dependency rules:
+----------------------------
+
+The same lock-class must not be acquired twice, because this could lead
+to lock recursion deadlocks.
+
+Furthermore, two locks may not be taken in different order:
+
+ <L1> -> <L2>
+ <L2> -> <L1>
+
+because this could lead to lock inversion deadlocks. (The validator
+finds such dependencies in arbitrary complexity, i.e. there can be any
+other locking sequence between the acquire-lock operations, the
+validator will still track all dependencies between locks.)
+
+Furthermore, the following usage based lock dependencies are not allowed
+between any two lock-classes:
+
+   <hardirq-safe>   ->  <hardirq-unsafe>
+   <softirq-safe>   ->  <softirq-unsafe>
+
+The first rule comes from the fact the a hardirq-safe lock could be
+taken by a hardirq context, interrupting a hardirq-unsafe lock - and
+thus could result in a lock inversion deadlock. Likewise, a softirq-safe
+lock could be taken by an softirq context, interrupting a softirq-unsafe
+lock.
+
+The above rules are enforced for any locking sequence that occurs in the
+kernel: when acquiring a new lock, the validator checks whether there is
+any rule violation between the new lock and any of the held locks.
+
+When a lock-class changes its state, the following aspects of the above
+dependency rules are enforced:
+
+- if a new hardirq-safe lock is discovered, we check whether it
+  took any hardirq-unsafe lock in the past.
+
+- if a new softirq-safe lock is discovered, we check whether it took
+  any softirq-unsafe lock in the past.
+
+- if a new hardirq-unsafe lock is discovered, we check whether any
+  hardirq-safe lock took it in the past.
+
+- if a new softirq-unsafe lock is discovered, we check whether any
+  softirq-safe lock took it in the past.
+
+(Again, we do these checks too on the basis that an interrupt context
+could interrupt _any_ of the irq-unsafe or hardirq-unsafe locks, which
+could lead to a lock inversion deadlock - even if that lock scenario did
+not trigger in practice yet.)
+
+Exception: Nested data dependencies leading to nested locking
+-------------------------------------------------------------
+
+There are a few cases where the Linux kernel acquires more than one
+instance of the same lock-class. Such cases typically happen when there
+is some sort of hierarchy within objects of the same type. In these
+cases there is an inherent "natural" ordering between the two objects
+(defined by the properties of the hierarchy), and the kernel grabs the
+locks in this fixed order on each of the objects.
+
+An example of such an object hieararchy that results in "nested locking"
+is that of a "whole disk" block-dev object and a "partition" block-dev
+object; the partition is "part of" the whole device and as long as one
+always takes the whole disk lock as a higher lock than the partition
+lock, the lock ordering is fully correct. The validator does not
+automatically detect this natural ordering, as the locking rule behind
+the ordering is not static.
+
+In order to teach the validator about this correct usage model, new
+versions of the various locking primitives were added that allow you to
+specify a "nesting level". An example call, for the block device mutex,
+looks like this:
+
+enum bdev_bd_mutex_lock_class
+{
+       BD_MUTEX_NORMAL,
+       BD_MUTEX_WHOLE,
+       BD_MUTEX_PARTITION
+};
+
+ mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION);
+
+In this case the locking is done on a bdev object that is known to be a
+partition.
+
+The validator treats a lock that is taken in such a nested fasion as a
+separate (sub)class for the purposes of validation.
+
+Note: When changing code to use the _nested() primitives, be careful and
+check really thoroughly that the hiearchy is correctly mapped; otherwise
+you can get false positives or false negatives.
+
+Proof of 100% correctness:
+--------------------------
+
+The validator achieves perfect, mathematical 'closure' (proof of locking
+correctness) in the sense that for every simple, standalone single-task
+locking sequence that occured at least once during the lifetime of the
+kernel, the validator proves it with a 100% certainty that no
+combination and timing of these locking sequences can cause any class of
+lock related deadlock. [*]
+
+I.e. complex multi-CPU and multi-task locking scenarios do not have to
+occur in practice to prove a deadlock: only the simple 'component'
+locking chains have to occur at least once (anytime, in any
+task/context) for the validator to be able to prove correctness. (For
+example, complex deadlocks that would normally need more than 3 CPUs and
+a very unlikely constellation of tasks, irq-contexts and timings to
+occur, can be detected on a plain, lightly loaded single-CPU system as
+well!)
+
+This radically decreases the complexity of locking related QA of the
+kernel: what has to be done during QA is to trigger as many "simple"
+single-task locking dependencies in the kernel as possible, at least
+once, to prove locking correctness - instead of having to trigger every
+possible combination of locking interaction between CPUs, combined with
+every possible hardirq and softirq nesting scenario (which is impossible
+to do in practice).
+
+[*] assuming that the validator itself is 100% correct, and no other
+    part of the system corrupts the state of the validator in any way.
+    We also assume that all NMI/SMM paths [which could interrupt
+    even hardirq-disabled codepaths] are correct and do not interfere
+    with the validator. We also assume that the 64-bit 'chain hash'
+    value is unique for every lock-chain in the system. Also, lock
+    recursion must not be higher than 20.
+
+Performance:
+------------
+
+The above rules require _massive_ amounts of runtime checking. If we did
+that for every lock taken and for every irqs-enable event, it would
+render the system practically unusably slow. The complexity of checking
+is O(N^2), so even with just a few hundred lock-classes we'd have to do
+tens of thousands of checks for every event.
+
+This problem is solved by checking any given 'locking scenario' (unique
+sequence of locks taken after each other) only once. A simple stack of
+held locks is maintained, and a lightweight 64-bit hash value is
+calculated, which hash is unique for every lock chain. The hash value,
+when the chain is validated for the first time, is then put into a hash
+table, which hash-table can be checked in a lockfree manner. If the
+locking chain occurs again later on, the hash table tells us that we
+dont have to validate the chain again.
diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt
new file mode 100644 (file)
index 0000000..4ccdbca
--- /dev/null
@@ -0,0 +1,143 @@
+/proc/sys/net/ipv4/vs/* Variables:
+
+am_droprate - INTEGER
+        default 10
+
+        It sets the always mode drop rate, which is used in the mode 3
+        of the drop_rate defense.
+
+amemthresh - INTEGER
+        default 1024
+
+        It sets the available memory threshold (in pages), which is
+        used in the automatic modes of defense. When there is no
+        enough available memory, the respective strategy will be
+        enabled and the variable is automatically set to 2, otherwise
+        the strategy is disabled and the variable is  set  to 1.
+
+cache_bypass - BOOLEAN
+        0 - disabled (default)
+        not 0 - enabled
+
+        If it is enabled, forward packets to the original destination
+        directly when no cache server is available and destination
+        address is not local (iph->daddr is RTN_UNICAST). It is mostly
+        used in transparent web cache cluster.
+
+debug_level - INTEGER
+       0          - transmission error messages (default)
+       1          - non-fatal error messages
+       2          - configuration
+       3          - destination trash
+       4          - drop entry
+       5          - service lookup
+       6          - scheduling
+       7          - connection new/expire, lookup and synchronization
+       8          - state transition
+       9          - binding destination, template checks and applications
+       10         - IPVS packet transmission
+       11         - IPVS packet handling (ip_vs_in/ip_vs_out)
+       12 or more - packet traversal
+
+       Only available when IPVS is compiled with the CONFIG_IPVS_DEBUG
+
+       Higher debugging levels include the messages for lower debugging
+       levels, so setting debug level 2, includes level 0, 1 and 2
+       messages. Thus, logging becomes more and more verbose the higher
+       the level.
+
+drop_entry - INTEGER
+        0  - disabled (default)
+
+        The drop_entry defense is to randomly drop entries in the
+        connection hash table, just in order to collect back some
+        memory for new connections. In the current code, the
+        drop_entry procedure can be activated every second, then it
+        randomly scans 1/32 of the whole and drops entries that are in
+        the SYN-RECV/SYNACK state, which should be effective against
+        syn-flooding attack.
+
+        The valid values of drop_entry are from 0 to 3, where 0 means
+        that this strategy is always disabled, 1 and 2 mean automatic
+        modes (when there is no enough available memory, the strategy
+        is enabled and the variable is automatically set to 2,
+        otherwise the strategy is disabled and the variable is set to
+        1), and 3 means that that the strategy is always enabled.
+
+drop_packet - INTEGER
+        0  - disabled (default)
+
+        The drop_packet defense is designed to drop 1/rate packets
+        before forwarding them to real servers. If the rate is 1, then
+        drop all the incoming packets.
+
+        The value definition is the same as that of the drop_entry. In
+        the automatic mode, the rate is determined by the follow
+        formula: rate = amemthresh / (amemthresh - available_memory)
+        when available memory is less than the available memory
+        threshold. When the mode 3 is set, the always mode drop rate
+        is controlled by the /proc/sys/net/ipv4/vs/am_droprate.
+
+expire_nodest_conn - BOOLEAN
+        0 - disabled (default)
+        not 0 - enabled
+
+        The default value is 0, the load balancer will silently drop
+        packets when its destination server is not available. It may
+        be useful, when user-space monitoring program deletes the
+        destination server (because of server overload or wrong
+        detection) and add back the server later, and the connections
+        to the server can continue.
+
+        If this feature is enabled, the load balancer will expire the
+        connection immediately when a packet arrives and its
+        destination server is not available, then the client program
+        will be notified that the connection is closed. This is
+        equivalent to the feature some people requires to flush
+        connections when its destination is not available.
+
+expire_quiescent_template - BOOLEAN
+       0 - disabled (default)
+       not 0 - enabled
+
+       When set to a non-zero value, the load balancer will expire
+       persistent templates when the destination server is quiescent.
+       This may be useful, when a user makes a destination server
+       quiescent by setting its weight to 0 and it is desired that
+       subsequent otherwise persistent connections are sent to a
+       different destination server.  By default new persistent
+       connections are allowed to quiescent destination servers.
+
+       If this feature is enabled, the load balancer will expire the
+       persistence template if it is to be used to schedule a new
+       connection and the destination server is quiescent.
+
+nat_icmp_send - BOOLEAN
+        0 - disabled (default)
+        not 0 - enabled
+
+        It controls sending icmp error messages (ICMP_DEST_UNREACH)
+        for VS/NAT when the load balancer receives packets from real
+        servers but the connection entries don't exist.
+
+secure_tcp - INTEGER
+        0  - disabled (default)
+
+        The secure_tcp defense is to use a more complicated state
+        transition table and some possible short timeouts of each
+        state. In the VS/NAT, it delays the entering the ESTABLISHED
+        until the real server starts to send data and ACK packet
+        (after 3-way handshake).
+
+        The value definition is the same as that of drop_entry or
+        drop_packet.
+
+sync_threshold - INTEGER
+        default 3
+
+        It sets synchronization threshold, which is the minimum number
+        of incoming packets that a connection needs to receive before
+        the connection will be synchronized. A connection will be
+        synchronized, every time the number of its incoming packets
+        modulus 50 equals the threshold. The range of the threshold is
+        from 0 to 49.
diff --git a/Documentation/pcmcia/crc32hash.c b/Documentation/pcmcia/crc32hash.c
new file mode 100644 (file)
index 0000000..cbc36d2
--- /dev/null
@@ -0,0 +1,32 @@
+/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */
+/* Usage example:
+$ ./crc32hash "Dual Speed"
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+unsigned int crc32(unsigned char const *p, unsigned int len)
+{
+       int i;
+       unsigned int crc = 0;
+       while (len--) {
+               crc ^= *p++;
+               for (i = 0; i < 8; i++)
+                       crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
+       }
+       return crc;
+}
+
+int main(int argc, char **argv) {
+       unsigned int result;
+       if (argc != 2) {
+               printf("no string passed as argument\n");
+               return -1;
+       }
+       result = crc32(argv[1], strlen(argv[1]));
+       printf("0x%x\n", result);
+       return 0;
+}
diff --git a/Documentation/pi-futex.txt b/Documentation/pi-futex.txt
new file mode 100644 (file)
index 0000000..5d61dac
--- /dev/null
@@ -0,0 +1,121 @@
+Lightweight PI-futexes
+----------------------
+
+We are calling them lightweight for 3 reasons:
+
+ - in the user-space fastpath a PI-enabled futex involves no kernel work
+   (or any other PI complexity) at all. No registration, no extra kernel
+   calls - just pure fast atomic ops in userspace.
+
+ - even in the slowpath, the system call and scheduling pattern is very
+   similar to normal futexes.
+
+ - the in-kernel PI implementation is streamlined around the mutex
+   abstraction, with strict rules that keep the implementation
+   relatively simple: only a single owner may own a lock (i.e. no
+   read-write lock support), only the owner may unlock a lock, no
+   recursive locking, etc.
+
+Priority Inheritance - why?
+---------------------------
+
+The short reply: user-space PI helps achieving/improving determinism for
+user-space applications. In the best-case, it can help achieve
+determinism and well-bound latencies. Even in the worst-case, PI will
+improve the statistical distribution of locking related application
+delays.
+
+The longer reply:
+-----------------
+
+Firstly, sharing locks between multiple tasks is a common programming
+technique that often cannot be replaced with lockless algorithms. As we
+can see it in the kernel [which is a quite complex program in itself],
+lockless structures are rather the exception than the norm - the current
+ratio of lockless vs. locky code for shared data structures is somewhere
+between 1:10 and 1:100. Lockless is hard, and the complexity of lockless
+algorithms often endangers to ability to do robust reviews of said code.
+I.e. critical RT apps often choose lock structures to protect critical
+data structures, instead of lockless algorithms. Furthermore, there are
+cases (like shared hardware, or other resource limits) where lockless
+access is mathematically impossible.
+
+Media players (such as Jack) are an example of reasonable application
+design with multiple tasks (with multiple priority levels) sharing
+short-held locks: for example, a highprio audio playback thread is
+combined with medium-prio construct-audio-data threads and low-prio
+display-colory-stuff threads. Add video and decoding to the mix and
+we've got even more priority levels.
+
+So once we accept that synchronization objects (locks) are an
+unavoidable fact of life, and once we accept that multi-task userspace
+apps have a very fair expectation of being able to use locks, we've got
+to think about how to offer the option of a deterministic locking
+implementation to user-space.
+
+Most of the technical counter-arguments against doing priority
+inheritance only apply to kernel-space locks. But user-space locks are
+different, there we cannot disable interrupts or make the task
+non-preemptible in a critical section, so the 'use spinlocks' argument
+does not apply (user-space spinlocks have the same priority inversion
+problems as other user-space locking constructs). Fact is, pretty much
+the only technique that currently enables good determinism for userspace
+locks (such as futex-based pthread mutexes) is priority inheritance:
+
+Currently (without PI), if a high-prio and a low-prio task shares a lock
+[this is a quite common scenario for most non-trivial RT applications],
+even if all critical sections are coded carefully to be deterministic
+(i.e. all critical sections are short in duration and only execute a
+limited number of instructions), the kernel cannot guarantee any
+deterministic execution of the high-prio task: any medium-priority task
+could preempt the low-prio task while it holds the shared lock and
+executes the critical section, and could delay it indefinitely.
+
+Implementation:
+---------------
+
+As mentioned before, the userspace fastpath of PI-enabled pthread
+mutexes involves no kernel work at all - they behave quite similarly to
+normal futex-based locks: a 0 value means unlocked, and a value==TID
+means locked. (This is the same method as used by list-based robust
+futexes.) Userspace uses atomic ops to lock/unlock these mutexes without
+entering the kernel.
+
+To handle the slowpath, we have added two new futex ops:
+
+  FUTEX_LOCK_PI
+  FUTEX_UNLOCK_PI
+
+If the lock-acquire fastpath fails, [i.e. an atomic transition from 0 to
+TID fails], then FUTEX_LOCK_PI is called. The kernel does all the
+remaining work: if there is no futex-queue attached to the futex address
+yet then the code looks up the task that owns the futex [it has put its
+own TID into the futex value], and attaches a 'PI state' structure to
+the futex-queue. The pi_state includes an rt-mutex, which is a PI-aware,
+kernel-based synchronization object. The 'other' task is made the owner
+of the rt-mutex, and the FUTEX_WAITERS bit is atomically set in the
+futex value. Then this task tries to lock the rt-mutex, on which it
+blocks. Once it returns, it has the mutex acquired, and it sets the
+futex value to its own TID and returns. Userspace has no other work to
+perform - it now owns the lock, and futex value contains
+FUTEX_WAITERS|TID.
+
+If the unlock side fastpath succeeds, [i.e. userspace manages to do a
+TID -> 0 atomic transition of the futex value], then no kernel work is
+triggered.
+
+If the unlock fastpath fails (because the FUTEX_WAITERS bit is set),
+then FUTEX_UNLOCK_PI is called, and the kernel unlocks the futex on the
+behalf of userspace - and it also unlocks the attached
+pi_state->rt_mutex and thus wakes up any potential waiters.
+
+Note that under this approach, contrary to previous PI-futex approaches,
+there is no prior 'registration' of a PI-futex. [which is not quite
+possible anyway, due to existing ABI properties of pthread mutexes.]
+
+Also, under this scheme, 'robustness' and 'PI' are two orthogonal
+properties of futexes, and all four combinations are possible: futex,
+robust-futex, PI-futex, robust+PI-futex.
+
+More details about priority inheritance can be found in
+Documentation/rtmutex.txt.
diff --git a/Documentation/rt-mutex-design.txt b/Documentation/rt-mutex-design.txt
new file mode 100644 (file)
index 0000000..c472ffa
--- /dev/null
@@ -0,0 +1,781 @@
+#
+# Copyright (c) 2006 Steven Rostedt
+# Licensed under the GNU Free Documentation License, Version 1.2
+#
+
+RT-mutex implementation design
+------------------------------
+
+This document tries to describe the design of the rtmutex.c implementation.
+It doesn't describe the reasons why rtmutex.c exists. For that please see
+Documentation/rt-mutex.txt.  Although this document does explain problems
+that happen without this code, but that is in the concept to understand
+what the code actually is doing.
+
+The goal of this document is to help others understand the priority
+inheritance (PI) algorithm that is used, as well as reasons for the
+decisions that were made to implement PI in the manner that was done.
+
+
+Unbounded Priority Inversion
+----------------------------
+
+Priority inversion is when a lower priority process executes while a higher
+priority process wants to run.  This happens for several reasons, and
+most of the time it can't be helped.  Anytime a high priority process wants
+to use a resource that a lower priority process has (a mutex for example),
+the high priority process must wait until the lower priority process is done
+with the resource.  This is a priority inversion.  What we want to prevent
+is something called unbounded priority inversion.  That is when the high
+priority process is prevented from running by a lower priority process for
+an undetermined amount of time.
+
+The classic example of unbounded priority inversion is were you have three
+processes, let's call them processes A, B, and C, where A is the highest
+priority process, C is the lowest, and B is in between. A tries to grab a lock
+that C owns and must wait and lets C run to release the lock. But in the
+meantime, B executes, and since B is of a higher priority than C, it preempts C,
+but by doing so, it is in fact preempting A which is a higher priority process.
+Now there's no way of knowing how long A will be sleeping waiting for C
+to release the lock, because for all we know, B is a CPU hog and will
+never give C a chance to release the lock.  This is called unbounded priority
+inversion.
+
+Here's a little ASCII art to show the problem.
+
+   grab lock L1 (owned by C)
+     |
+A ---+
+        C preempted by B
+          |
+C    +----+
+
+B         +-------->
+                B now keeps A from running.
+
+
+Priority Inheritance (PI)
+-------------------------
+
+There are several ways to solve this issue, but other ways are out of scope
+for this document.  Here we only discuss PI.
+
+PI is where a process inherits the priority of another process if the other
+process blocks on a lock owned by the current process.  To make this easier
+to understand, let's use the previous example, with processes A, B, and C again.
+
+This time, when A blocks on the lock owned by C, C would inherit the priority
+of A.  So now if B becomes runnable, it would not preempt C, since C now has
+the high priority of A.  As soon as C releases the lock, it loses its
+inherited priority, and A then can continue with the resource that C had.
+
+Terminology
+-----------
+
+Here I explain some terminology that is used in this document to help describe
+the design that is used to implement PI.
+
+PI chain - The PI chain is an ordered series of locks and processes that cause
+           processes to inherit priorities from a previous process that is
+           blocked on one of its locks.  This is described in more detail
+           later in this document.
+
+mutex    - In this document, to differentiate from locks that implement
+           PI and spin locks that are used in the PI code, from now on
+           the PI locks will be called a mutex.
+
+lock     - In this document from now on, I will use the term lock when
+           referring to spin locks that are used to protect parts of the PI
+           algorithm.  These locks disable preemption for UP (when
+           CONFIG_PREEMPT is enabled) and on SMP prevents multiple CPUs from
+           entering critical sections simultaneously.
+
+spin lock - Same as lock above.
+
+waiter   - A waiter is a struct that is stored on the stack of a blocked
+           process.  Since the scope of the waiter is within the code for
+           a process being blocked on the mutex, it is fine to allocate
+           the waiter on the process's stack (local variable).  This
+           structure holds a pointer to the task, as well as the mutex that
+           the task is blocked on.  It also has the plist node structures to
+           place the task in the waiter_list of a mutex as well as the
+           pi_list of a mutex owner task (described below).
+
+           waiter is sometimes used in reference to the task that is waiting
+           on a mutex. This is the same as waiter->task.
+
+waiters  - A list of processes that are blocked on a mutex.
+
+top waiter - The highest priority process waiting on a specific mutex.
+
+top pi waiter - The highest priority process waiting on one of the mutexes
+                that a specific process owns.
+
+Note:  task and process are used interchangeably in this document, mostly to
+       differentiate between two processes that are being described together.
+
+
+PI chain
+--------
+
+The PI chain is a list of processes and mutexes that may cause priority
+inheritance to take place.  Multiple chains may converge, but a chain
+would never diverge, since a process can't be blocked on more than one
+mutex at a time.
+
+Example:
+
+   Process:  A, B, C, D, E
+   Mutexes:  L1, L2, L3, L4
+
+   A owns: L1
+           B blocked on L1
+           B owns L2
+                  C blocked on L2
+                  C owns L3
+                         D blocked on L3
+                         D owns L4
+                                E blocked on L4
+
+The chain would be:
+
+   E->L4->D->L3->C->L2->B->L1->A
+
+To show where two chains merge, we could add another process F and
+another mutex L5 where B owns L5 and F is blocked on mutex L5.
+
+The chain for F would be:
+
+   F->L5->B->L1->A
+
+Since a process may own more than one mutex, but never be blocked on more than
+one, the chains merge.
+
+Here we show both chains:
+
+   E->L4->D->L3->C->L2-+
+                       |
+                       +->B->L1->A
+                       |
+                 F->L5-+
+
+For PI to work, the processes at the right end of these chains (or we may
+also call it the Top of the chain) must be equal to or higher in priority
+than the processes to the left or below in the chain.
+
+Also since a mutex may have more than one process blocked on it, we can
+have multiple chains merge at mutexes.  If we add another process G that is
+blocked on mutex L2:
+
+  G->L2->B->L1->A
+
+And once again, to show how this can grow I will show the merging chains
+again.
+
+   E->L4->D->L3->C-+
+                   +->L2-+
+                   |     |
+                 G-+     +->B->L1->A
+                         |
+                   F->L5-+
+
+
+Plist
+-----
+
+Before I go further and talk about how the PI chain is stored through lists
+on both mutexes and processes, I'll explain the plist.  This is similar to
+the struct list_head functionality that is already in the kernel.
+The implementation of plist is out of scope for this document, but it is
+very important to understand what it does.
+
+There are a few differences between plist and list, the most important one
+being that plist is a priority sorted linked list.  This means that the
+priorities of the plist are sorted, such that it takes O(1) to retrieve the
+highest priority item in the list.  Obviously this is useful to store processes
+based on their priorities.
+
+Another difference, which is important for implementation, is that, unlike
+list, the head of the list is a different element than the nodes of a list.
+So the head of the list is declared as struct plist_head and nodes that will
+be added to the list are declared as struct plist_node.
+
+
+Mutex Waiter List
+-----------------
+
+Every mutex keeps track of all the waiters that are blocked on itself. The mutex
+has a plist to store these waiters by priority.  This list is protected by
+a spin lock that is located in the struct of the mutex. This lock is called
+wait_lock.  Since the modification of the waiter list is never done in
+interrupt context, the wait_lock can be taken without disabling interrupts.
+
+
+Task PI List
+------------
+
+To keep track of the PI chains, each process has its own PI list.  This is
+a list of all top waiters of the mutexes that are owned by the process.
+Note that this list only holds the top waiters and not all waiters that are
+blocked on mutexes owned by the process.
+
+The top of the task's PI list is always the highest priority task that
+is waiting on a mutex that is owned by the task.  So if the task has
+inherited a priority, it will always be the priority of the task that is
+at the top of this list.
+
+This list is stored in the task structure of a process as a plist called
+pi_list.  This list is protected by a spin lock also in the task structure,
+called pi_lock.  This lock may also be taken in interrupt context, so when
+locking the pi_lock, interrupts must be disabled.
+
+
+Depth of the PI Chain
+---------------------
+
+The maximum depth of the PI chain is not dynamic, and could actually be
+defined.  But is very complex to figure it out, since it depends on all
+the nesting of mutexes.  Let's look at the example where we have 3 mutexes,
+L1, L2, and L3, and four separate functions func1, func2, func3 and func4.
+The following shows a locking order of L1->L2->L3, but may not actually
+be directly nested that way.
+
+void func1(void)
+{
+       mutex_lock(L1);
+
+       /* do anything */
+
+       mutex_unlock(L1);
+}
+
+void func2(void)
+{
+       mutex_lock(L1);
+       mutex_lock(L2);
+
+       /* do something */
+
+       mutex_unlock(L2);
+       mutex_unlock(L1);
+}
+
+void func3(void)
+{
+       mutex_lock(L2);
+       mutex_lock(L3);
+
+       /* do something else */
+
+       mutex_unlock(L3);
+       mutex_unlock(L2);
+}
+
+void func4(void)
+{
+       mutex_lock(L3);
+
+       /* do something again */
+
+       mutex_unlock(L3);
+}
+
+Now we add 4 processes that run each of these functions separately.
+Processes A, B, C, and D which run functions func1, func2, func3 and func4
+respectively, and such that D runs first and A last.  With D being preempted
+in func4 in the "do something again" area, we have a locking that follows:
+
+D owns L3
+       C blocked on L3
+       C owns L2
+              B blocked on L2
+              B owns L1
+                     A blocked on L1
+
+And thus we have the chain A->L1->B->L2->C->L3->D.
+
+This gives us a PI depth of 4 (four processes), but looking at any of the
+functions individually, it seems as though they only have at most a locking
+depth of two.  So, although the locking depth is defined at compile time,
+it still is very difficult to find the possibilities of that depth.
+
+Now since mutexes can be defined by user-land applications, we don't want a DOS
+type of application that nests large amounts of mutexes to create a large
+PI chain, and have the code holding spin locks while looking at a large
+amount of data.  So to prevent this, the implementation not only implements
+a maximum lock depth, but also only holds at most two different locks at a
+time, as it walks the PI chain.  More about this below.
+
+
+Mutex owner and flags
+---------------------
+
+The mutex structure contains a pointer to the owner of the mutex.  If the
+mutex is not owned, this owner is set to NULL.  Since all architectures
+have the task structure on at least a four byte alignment (and if this is
+not true, the rtmutex.c code will be broken!), this allows for the two
+least significant bits to be used as flags.  This part is also described
+in Documentation/rt-mutex.txt, but will also be briefly described here.
+
+Bit 0 is used as the "Pending Owner" flag.  This is described later.
+Bit 1 is used as the "Has Waiters" flags.  This is also described later
+  in more detail, but is set whenever there are waiters on a mutex.
+
+
+cmpxchg Tricks
+--------------
+
+Some architectures implement an atomic cmpxchg (Compare and Exchange).  This
+is used (when applicable) to keep the fast path of grabbing and releasing
+mutexes short.
+
+cmpxchg is basically the following function performed atomically:
+
+unsigned long _cmpxchg(unsigned long *A, unsigned long *B, unsigned long *C)
+{
+        unsigned long T = *A;
+        if (*A == *B) {
+                *A = *C;
+        }
+        return T;
+}
+#define cmpxchg(a,b,c) _cmpxchg(&a,&b,&c)
+
+This is really nice to have, since it allows you to only update a variable
+if the variable is what you expect it to be.  You know if it succeeded if
+the return value (the old value of A) is equal to B.
+
+The macro rt_mutex_cmpxchg is used to try to lock and unlock mutexes. If
+the architecture does not support CMPXCHG, then this macro is simply set
+to fail every time.  But if CMPXCHG is supported, then this will
+help out extremely to keep the fast path short.
+
+The use of rt_mutex_cmpxchg with the flags in the owner field help optimize
+the system for architectures that support it.  This will also be explained
+later in this document.
+
+
+Priority adjustments
+--------------------
+
+The implementation of the PI code in rtmutex.c has several places that a
+process must adjust its priority.  With the help of the pi_list of a
+process this is rather easy to know what needs to be adjusted.
+
+The functions implementing the task adjustments are rt_mutex_adjust_prio,
+__rt_mutex_adjust_prio (same as the former, but expects the task pi_lock
+to already be taken), rt_mutex_get_prio, and rt_mutex_setprio.
+
+rt_mutex_getprio and rt_mutex_setprio are only used in __rt_mutex_adjust_prio.
+
+rt_mutex_getprio returns the priority that the task should have.  Either the
+task's own normal priority, or if a process of a higher priority is waiting on
+a mutex owned by the task, then that higher priority should be returned.
+Since the pi_list of a task holds an order by priority list of all the top
+waiters of all the mutexes that the task owns, rt_mutex_getprio simply needs
+to compare the top pi waiter to its own normal priority, and return the higher
+priority back.
+
+(Note:  if looking at the code, you will notice that the lower number of
+        prio is returned.  This is because the prio field in the task structure
+        is an inverse order of the actual priority.  So a "prio" of 5 is
+        of higher priority than a "prio" of 10.)
+
+__rt_mutex_adjust_prio examines the result of rt_mutex_getprio, and if the
+result does not equal the task's current priority, then rt_mutex_setprio
+is called to adjust the priority of the task to the new priority.
+Note that rt_mutex_setprio is defined in kernel/sched.c to implement the
+actual change in priority.
+
+It is interesting to note that __rt_mutex_adjust_prio can either increase
+or decrease the priority of the task.  In the case that a higher priority
+process has just blocked on a mutex owned by the task, __rt_mutex_adjust_prio
+would increase/boost the task's priority.  But if a higher priority task
+were for some reason to leave the mutex (timeout or signal), this same function
+would decrease/unboost the priority of the task.  That is because the pi_list
+always contains the highest priority task that is waiting on a mutex owned
+by the task, so we only need to compare the priority of that top pi waiter
+to the normal priority of the given task.
+
+
+High level overview of the PI chain walk
+----------------------------------------
+
+The PI chain walk is implemented by the function rt_mutex_adjust_prio_chain.
+
+The implementation has gone through several iterations, and has ended up
+with what we believe is the best.  It walks the PI chain by only grabbing
+at most two locks at a time, and is very efficient.
+
+The rt_mutex_adjust_prio_chain can be used either to boost or lower process
+priorities.
+
+rt_mutex_adjust_prio_chain is called with a task to be checked for PI
+(de)boosting (the owner of a mutex that a process is blocking on), a flag to
+check for deadlocking, the mutex that the task owns, and a pointer to a waiter
+that is the process's waiter struct that is blocked on the mutex (although this
+parameter may be NULL for deboosting).
+
+For this explanation, I will not mention deadlock detection. This explanation
+will try to stay at a high level.
+
+When this function is called, there are no locks held.  That also means
+that the state of the owner and lock can change when entered into this function.
+
+Before this function is called, the task has already had rt_mutex_adjust_prio
+performed on it.  This means that the task is set to the priority that it
+should be at, but the plist nodes of the task's waiter have not been updated
+with the new priorities, and that this task may not be in the proper locations
+in the pi_lists and wait_lists that the task is blocked on.  This function
+solves all that.
+
+A loop is entered, where task is the owner to be checked for PI changes that
+was passed by parameter (for the first iteration).  The pi_lock of this task is
+taken to prevent any more changes to the pi_list of the task.  This also
+prevents new tasks from completing the blocking on a mutex that is owned by this
+task.
+
+If the task is not blocked on a mutex then the loop is exited.  We are at
+the top of the PI chain.
+
+A check is now done to see if the original waiter (the process that is blocked
+on the current mutex) is the top pi waiter of the task.  That is, is this
+waiter on the top of the task's pi_list.  If it is not, it either means that
+there is another process higher in priority that is blocked on one of the
+mutexes that the task owns, or that the waiter has just woken up via a signal
+or timeout and has left the PI chain.  In either case, the loop is exited, since
+we don't need to do any more changes to the priority of the current task, or any
+task that owns a mutex that this current task is waiting on.  A priority chain
+walk is only needed when a new top pi waiter is made to a task.
+
+The next check sees if the task's waiter plist node has the priority equal to
+the priority the task is set at.  If they are equal, then we are done with
+the loop.  Remember that the function started with the priority of the
+task adjusted, but the plist nodes that hold the task in other processes
+pi_lists have not been adjusted.
+
+Next, we look at the mutex that the task is blocked on. The mutex's wait_lock
+is taken.  This is done by a spin_trylock, because the locking order of the
+pi_lock and wait_lock goes in the opposite direction. If we fail to grab the
+lock, the pi_lock is released, and we restart the loop.
+
+Now that we have both the pi_lock of the task as well as the wait_lock of
+the mutex the task is blocked on, we update the task's waiter's plist node
+that is located on the mutex's wait_list.
+
+Now we release the pi_lock of the task.
+
+Next the owner of the mutex has its pi_lock taken, so we can update the
+task's entry in the owner's pi_list.  If the task is the highest priority
+process on the mutex's wait_list, then we remove the previous top waiter
+from the owner's pi_list, and replace it with the task.
+
+Note: It is possible that the task was the current top waiter on the mutex,
+      in which case the task is not yet on the pi_list of the waiter.  This
+      is OK, since plist_del does nothing if the plist node is not on any
+      list.
+
+If the task was not the top waiter of the mutex, but it was before we
+did the priority updates, that means we are deboosting/lowering the
+task.  In this case, the task is removed from the pi_list of the owner,
+and the new top waiter is added.
+
+Lastly, we unlock both the pi_lock of the task, as well as the mutex's
+wait_lock, and continue the loop again.  On the next iteration of the
+loop, the previous owner of the mutex will be the task that will be
+processed.
+
+Note: One might think that the owner of this mutex might have changed
+      since we just grab the mutex's wait_lock. And one could be right.
+      The important thing to remember is that the owner could not have
+      become the task that is being processed in the PI chain, since
+      we have taken that task's pi_lock at the beginning of the loop.
+      So as long as there is an owner of this mutex that is not the same
+      process as the tasked being worked on, we are OK.
+
+      Looking closely at the code, one might be confused.  The check for the
+      end of the PI chain is when the task isn't blocked on anything or the
+      task's waiter structure "task" element is NULL.  This check is
+      protected only by the task's pi_lock.  But the code to unlock the mutex
+      sets the task's waiter structure "task" element to NULL with only
+      the protection of the mutex's wait_lock, which was not taken yet.
+      Isn't this a race condition if the task becomes the new owner?
+
+      The answer is No!  The trick is the spin_trylock of the mutex's
+      wait_lock.  If we fail that lock, we release the pi_lock of the
+      task and continue the loop, doing the end of PI chain check again.
+
+      In the code to release the lock, the wait_lock of the mutex is held
+      the entire time, and it is not let go when we grab the pi_lock of the
+      new owner of the mutex.  So if the switch of a new owner were to happen
+      after the check for end of the PI chain and the grabbing of the
+      wait_lock, the unlocking code would spin on the new owner's pi_lock
+      but never give up the wait_lock.  So the PI chain loop is guaranteed to
+      fail the spin_trylock on the wait_lock, release the pi_lock, and
+      try again.
+
+      If you don't quite understand the above, that's OK. You don't have to,
+      unless you really want to make a proof out of it ;)
+
+
+Pending Owners and Lock stealing
+--------------------------------
+
+One of the flags in the owner field of the mutex structure is "Pending Owner".
+What this means is that an owner was chosen by the process releasing the
+mutex, but that owner has yet to wake up and actually take the mutex.
+
+Why is this important?  Why can't we just give the mutex to another process
+and be done with it?
+
+The PI code is to help with real-time processes, and to let the highest
+priority process run as long as possible with little latencies and delays.
+If a high priority process owns a mutex that a lower priority process is
+blocked on, when the mutex is released it would be given to the lower priority
+process.  What if the higher priority process wants to take that mutex again.
+The high priority process would fail to take that mutex that it just gave up
+and it would need to boost the lower priority process to run with full
+latency of that critical section (since the low priority process just entered
+it).
+
+There's no reason a high priority process that gives up a mutex should be
+penalized if it tries to take that mutex again.  If the new owner of the
+mutex has not woken up yet, there's no reason that the higher priority process
+could not take that mutex away.
+
+To solve this, we introduced Pending Ownership and Lock Stealing.  When a
+new process is given a mutex that it was blocked on, it is only given
+pending ownership.  This means that it's the new owner, unless a higher
+priority process comes in and tries to grab that mutex.  If a higher priority
+process does come along and wants that mutex, we let the higher priority
+process "steal" the mutex from the pending owner (only if it is still pending)
+and continue with the mutex.
+
+
+Taking of a mutex (The walk through)
+------------------------------------
+
+OK, now let's take a look at the detailed walk through of what happens when
+taking a mutex.
+
+The first thing that is tried is the fast taking of the mutex.  This is
+done when we have CMPXCHG enabled (otherwise the fast taking automatically
+fails).  Only when the owner field of the mutex is NULL can the lock be
+taken with the CMPXCHG and nothing else needs to be done.
+
+If there is contention on the lock, whether it is owned or pending owner
+we go about the slow path (rt_mutex_slowlock).
+
+The slow path function is where the task's waiter structure is created on
+the stack.  This is because the waiter structure is only needed for the
+scope of this function.  The waiter structure holds the nodes to store
+the task on the wait_list of the mutex, and if need be, the pi_list of
+the owner.
+
+The wait_lock of the mutex is taken since the slow path of unlocking the
+mutex also takes this lock.
+
+We then call try_to_take_rt_mutex.  This is where the architecture that
+does not implement CMPXCHG would always grab the lock (if there's no
+contention).
+
+try_to_take_rt_mutex is used every time the task tries to grab a mutex in the
+slow path.  The first thing that is done here is an atomic setting of
+the "Has Waiters" flag of the mutex's owner field.  Yes, this could really
+be false, because if the the mutex has no owner, there are no waiters and
+the current task also won't have any waiters.  But we don't have the lock
+yet, so we assume we are going to be a waiter.  The reason for this is to
+play nice for those architectures that do have CMPXCHG.  By setting this flag
+now, the owner of the mutex can't release the mutex without going into the
+slow unlock path, and it would then need to grab the wait_lock, which this
+code currently holds.  So setting the "Has Waiters" flag forces the owner
+to synchronize with this code.
+
+Now that we know that we can't have any races with the owner releasing the
+mutex, we check to see if we can take the ownership.  This is done if the
+mutex doesn't have a owner, or if we can steal the mutex from a pending
+owner.  Let's look at the situations we have here.
+
+  1) Has owner that is pending
+  ----------------------------
+
+  The mutex has a owner, but it hasn't woken up and the mutex flag
+  "Pending Owner" is set.  The first check is to see if the owner isn't the
+  current task.  This is because this function is also used for the pending
+  owner to grab the mutex.  When a pending owner wakes up, it checks to see
+  if it can take the mutex, and this is done if the owner is already set to
+  itself.  If so, we succeed and leave the function, clearing the "Pending
+  Owner" bit.
+
+  If the pending owner is not current, we check to see if the current priority is
+  higher than the pending owner.  If not, we fail the function and return.
+
+  There's also something special about a pending owner.  That is a pending owner
+  is never blocked on a mutex.  So there is no PI chain to worry about.  It also
+  means that if the mutex doesn't have any waiters, there's no accounting needed
+  to update the pending owner's pi_list, since we only worry about processes
+  blocked on the current mutex.
+
+  If there are waiters on this mutex, and we just stole the ownership, we need
+  to take the top waiter, remove it from the pi_list of the pending owner, and
+  add it to the current pi_list.  Note that at this moment, the pending owner
+  is no longer on the list of waiters.  This is fine, since the pending owner
+  would add itself back when it realizes that it had the ownership stolen
+  from itself.  When the pending owner tries to grab the mutex, it will fail
+  in try_to_take_rt_mutex if the owner field points to another process.
+
+  2) No owner
+  -----------
+
+  If there is no owner (or we successfully stole the lock), we set the owner
+  of the mutex to current, and set the flag of "Has Waiters" if the current
+  mutex actually has waiters, or we clear the flag if it doesn't.  See, it was
+  OK that we set that flag early, since now it is cleared.
+
+  3) Failed to grab ownership
+  ---------------------------
+
+  The most interesting case is when we fail to take ownership. This means that
+  there exists an owner, or there's a pending owner with equal or higher
+  priority than the current task.
+
+We'll continue on the failed case.
+
+If the mutex has a timeout, we set up a timer to go off to break us out
+of this mutex if we failed to get it after a specified amount of time.
+
+Now we enter a loop that will continue to try to take ownership of the mutex, or
+fail from a timeout or signal.
+
+Once again we try to take the mutex.  This will usually fail the first time
+in the loop, since it had just failed to get the mutex.  But the second time
+in the loop, this would likely succeed, since the task would likely be
+the pending owner.
+
+If the mutex is TASK_INTERRUPTIBLE a check for signals and timeout is done
+here.
+
+The waiter structure has a "task" field that points to the task that is blocked
+on the mutex.  This field can be NULL the first time it goes through the loop
+or if the task is a pending owner and had it's mutex stolen.  If the "task"
+field is NULL then we need to set up the accounting for it.
+
+Task blocks on mutex
+--------------------
+
+The accounting of a mutex and process is done with the waiter structure of
+the process.  The "task" field is set to the process, and the "lock" field
+to the mutex.  The plist nodes are initialized to the processes current
+priority.
+
+Since the wait_lock was taken at the entry of the slow lock, we can safely
+add the waiter to the wait_list.  If the current process is the highest
+priority process currently waiting on this mutex, then we remove the
+previous top waiter process (if it exists) from the pi_list of the owner,
+and add the current process to that list.  Since the pi_list of the owner
+has changed, we call rt_mutex_adjust_prio on the owner to see if the owner
+should adjust its priority accordingly.
+
+If the owner is also blocked on a lock, and had its pi_list changed
+(or deadlock checking is on), we unlock the wait_lock of the mutex and go ahead
+and run rt_mutex_adjust_prio_chain on the owner, as described earlier.
+
+Now all locks are released, and if the current process is still blocked on a
+mutex (waiter "task" field is not NULL), then we go to sleep (call schedule).
+
+Waking up in the loop
+---------------------
+
+The schedule can then wake up for a few reasons.
+  1) we were given pending ownership of the mutex.
+  2) we received a signal and was TASK_INTERRUPTIBLE
+  3) we had a timeout and was TASK_INTERRUPTIBLE
+
+In any of these cases, we continue the loop and once again try to grab the
+ownership of the mutex.  If we succeed, we exit the loop, otherwise we continue
+and on signal and timeout, will exit the loop, or if we had the mutex stolen
+we just simply add ourselves back on the lists and go back to sleep.
+
+Note: For various reasons, because of timeout and signals, the steal mutex
+      algorithm needs to be careful. This is because the current process is
+      still on the wait_list. And because of dynamic changing of priorities,
+      especially on SCHED_OTHER tasks, the current process can be the
+      highest priority task on the wait_list.
+
+Failed to get mutex on Timeout or Signal
+----------------------------------------
+
+If a timeout or signal occurred, the waiter's "task" field would not be
+NULL and the task needs to be taken off the wait_list of the mutex and perhaps
+pi_list of the owner.  If this process was a high priority process, then
+the rt_mutex_adjust_prio_chain needs to be executed again on the owner,
+but this time it will be lowering the priorities.
+
+
+Unlocking the Mutex
+-------------------
+
+The unlocking of a mutex also has a fast path for those architectures with
+CMPXCHG.  Since the taking of a mutex on contention always sets the
+"Has Waiters" flag of the mutex's owner, we use this to know if we need to
+take the slow path when unlocking the mutex.  If the mutex doesn't have any
+waiters, the owner field of the mutex would equal the current process and
+the mutex can be unlocked by just replacing the owner field with NULL.
+
+If the owner field has the "Has Waiters" bit set (or CMPXCHG is not available),
+the slow unlock path is taken.
+
+The first thing done in the slow unlock path is to take the wait_lock of the
+mutex.  This synchronizes the locking and unlocking of the mutex.
+
+A check is made to see if the mutex has waiters or not.  On architectures that
+do not have CMPXCHG, this is the location that the owner of the mutex will
+determine if a waiter needs to be awoken or not.  On architectures that
+do have CMPXCHG, that check is done in the fast path, but it is still needed
+in the slow path too.  If a waiter of a mutex woke up because of a signal
+or timeout between the time the owner failed the fast path CMPXCHG check and
+the grabbing of the wait_lock, the mutex may not have any waiters, thus the
+owner still needs to make this check. If there are no waiters than the mutex
+owner field is set to NULL, the wait_lock is released and nothing more is
+needed.
+
+If there are waiters, then we need to wake one up and give that waiter
+pending ownership.
+
+On the wake up code, the pi_lock of the current owner is taken.  The top
+waiter of the lock is found and removed from the wait_list of the mutex
+as well as the pi_list of the current owner.  The task field of the new
+pending owner's waiter structure is set to NULL, and the owner field of the
+mutex is set to the new owner with the "Pending Owner" bit set, as well
+as the "Has Waiters" bit if there still are other processes blocked on the
+mutex.
+
+The pi_lock of the previous owner is released, and the new pending owner's
+pi_lock is taken.  Remember that this is the trick to prevent the race
+condition in rt_mutex_adjust_prio_chain from adding itself as a waiter
+on the mutex.
+
+We now clear the "pi_blocked_on" field of the new pending owner, and if
+the mutex still has waiters pending, we add the new top waiter to the pi_list
+of the pending owner.
+
+Finally we unlock the pi_lock of the pending owner and wake it up.
+
+
+Contact
+-------
+
+For updates on this document, please email Steven Rostedt <rostedt@goodmis.org>
+
+
+Credits
+-------
+
+Author:  Steven Rostedt <rostedt@goodmis.org>
+
+Reviewers:  Ingo Molnar, Thomas Gleixner, Thomas Duetsch, and Randy Dunlap
+
+Updates
+-------
+
+This document was originally written for 2.6.17-rc3-mm1
diff --git a/Documentation/rt-mutex.txt b/Documentation/rt-mutex.txt
new file mode 100644 (file)
index 0000000..243393d
--- /dev/null
@@ -0,0 +1,79 @@
+RT-mutex subsystem with PI support
+----------------------------------
+
+RT-mutexes with priority inheritance are used to support PI-futexes,
+which enable pthread_mutex_t priority inheritance attributes
+(PTHREAD_PRIO_INHERIT). [See Documentation/pi-futex.txt for more details
+about PI-futexes.]
+
+This technology was developed in the -rt tree and streamlined for
+pthread_mutex support.
+
+Basic principles:
+-----------------
+
+RT-mutexes extend the semantics of simple mutexes by the priority
+inheritance protocol.
+
+A low priority owner of a rt-mutex inherits the priority of a higher
+priority waiter until the rt-mutex is released. If the temporarily
+boosted owner blocks on a rt-mutex itself it propagates the priority
+boosting to the owner of the other rt_mutex it gets blocked on. The
+priority boosting is immediately removed once the rt_mutex has been
+unlocked.
+
+This approach allows us to shorten the block of high-prio tasks on
+mutexes which protect shared resources. Priority inheritance is not a
+magic bullet for poorly designed applications, but it allows
+well-designed applications to use userspace locks in critical parts of
+an high priority thread, without losing determinism.
+
+The enqueueing of the waiters into the rtmutex waiter list is done in
+priority order. For same priorities FIFO order is chosen. For each
+rtmutex, only the top priority waiter is enqueued into the owner's
+priority waiters list. This list too queues in priority order. Whenever
+the top priority waiter of a task changes (for example it timed out or
+got a signal), the priority of the owner task is readjusted. [The
+priority enqueueing is handled by "plists", see include/linux/plist.h
+for more details.]
+
+RT-mutexes are optimized for fastpath operations and have no internal
+locking overhead when locking an uncontended mutex or unlocking a mutex
+without waiters. The optimized fastpath operations require cmpxchg
+support. [If that is not available then the rt-mutex internal spinlock
+is used]
+
+The state of the rt-mutex is tracked via the owner field of the rt-mutex
+structure:
+
+rt_mutex->owner holds the task_struct pointer of the owner. Bit 0 and 1
+are used to keep track of the "owner is pending" and "rtmutex has
+waiters" state.
+
+ owner         bit1    bit0
+ NULL          0       0       mutex is free (fast acquire possible)
+ NULL          0       1       invalid state
+ NULL          1       0       Transitional state*
+ NULL          1       1       invalid state
+ taskpointer   0       0       mutex is held (fast release possible)
+ taskpointer   0       1       task is pending owner
+ taskpointer   1       0       mutex is held and has waiters
+ taskpointer   1       1       task is pending owner and mutex has waiters
+
+Pending-ownership handling is a performance optimization:
+pending-ownership is assigned to the first (highest priority) waiter of
+the mutex, when the mutex is released. The thread is woken up and once
+it starts executing it can acquire the mutex. Until the mutex is taken
+by it (bit 0 is cleared) a competing higher priority thread can "steal"
+the mutex which puts the woken up thread back on the waiters list.
+
+The pending-ownership optimization is especially important for the
+uninterrupted workflow of high-prio tasks which repeatedly
+takes/releases locks that have lower-prio waiters. Without this
+optimization the higher-prio thread would ping-pong to the lower-prio
+task [because at unlock time we always assign a new owner].
+
+(*) The "mutex has waiters" bit gets set to take the lock. If the lock
+doesn't already have an owner, this bit is quickly cleared if there are
+no waiters.  So this is a transitional state to synchronize with looking
+at the owner field of the mutex and the mutex owner releasing the lock.
diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt
new file mode 100644 (file)
index 0000000..d28a312
--- /dev/null
@@ -0,0 +1,92 @@
+HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop)
+
+Controller Register Map
+-------------------------
+
+The controller IOP is accessed via PCI BAR0.
+
+     BAR0 offset    Register
+            0x10    Inbound Message Register 0
+            0x14    Inbound Message Register 1
+            0x18    Outbound Message Register 0
+            0x1C    Outbound Message Register 1
+            0x20    Inbound Doorbell Register
+            0x24    Inbound Interrupt Status Register
+            0x28    Inbound Interrupt Mask Register
+            0x30    Outbound Interrupt Status Register
+            0x34    Outbound Interrupt Mask Register
+            0x40    Inbound Queue Port
+            0x44    Outbound Queue Port
+
+
+I/O Request Workflow
+----------------------
+
+All queued requests are handled via inbound/outbound queue port.
+A request packet can be allocated in either IOP or host memory.
+
+To send a request to the controller:
+
+    - Get a free request packet by reading the inbound queue port or
+      allocate a free request in host DMA coherent memory.
+
+      The value returned from the inbound queue port is an offset
+      relative to the IOP BAR0.
+
+      Requests allocated in host memory must be aligned on 32-bytes boundary.
+
+    - Fill the packet.
+
+    - Post the packet to IOP by writing it to inbound queue. For requests
+      allocated in IOP memory, write the offset to inbound queue port. For
+      requests allocated in host memory, write (0x80000000|(bus_addr>>5))
+      to the inbound queue port.
+
+    - The IOP process the request. When the request is completed, it
+      will be put into outbound queue. An outbound interrupt will be
+      generated.
+
+      For requests allocated in IOP memory, the request offset is posted to
+      outbound queue.
+
+      For requests allocated in host memory, (0x80000000|(bus_addr>>5))
+      is posted to the outbound queue. If IOP_REQUEST_FLAG_OUTPUT_CONTEXT
+      flag is set in the request, the low 32-bit context value will be
+      posted instead.
+
+    - The host read the outbound queue and complete the request.
+
+      For requests allocated in IOP memory, the host driver free the request
+      by writing it to the outbound queue.
+
+Non-queued requests (reset/flush etc) can be sent via inbound message
+register 0. An outbound message with the same value indicates the completion
+of an inbound message.
+
+
+User-level Interface
+---------------------
+
+The driver exposes following sysfs attributes:
+
+     NAME                 R/W    Description
+     driver-version        R     driver version string
+     firmware-version      R     firmware version string
+
+The driver registers char device "hptiop" to communicate with HighPoint RAID
+management software. Its ioctl routine acts as a general binary interface 
+between the IOP firmware and HighPoint RAID management software. New management
+functions can be implemented in application/firmware without modification
+in driver code.
+
+
+-----------------------------------------------------------------------------
+Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved.
+
+  This file is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  linux@highpoint-tech.com
+  http://www.highpoint-tech.com
diff --git a/Documentation/utrace.txt b/Documentation/utrace.txt
new file mode 100644 (file)
index 0000000..73858ed
--- /dev/null
@@ -0,0 +1,455 @@
+DRAFT DRAFT DRAFT      WORK IN PROGRESS        DRAFT DRAFT DRAFT
+
+This is work in progress and likely to change.
+
+
+       Roland McGrath <roland@redhat.com>
+
+---
+
+               User Debugging Data & Event Rendezvous
+               ---- --------- ---- - ----- ----------
+
+See linux/utrace.h for all the declarations used here.
+See also linux/tracehook.h for the utrace_regset declarations.
+
+The UTRACE is infrastructure code for tracing and controlling user
+threads.  This is the foundation for writing tracing engines, which
+can be loadable kernel modules.  The UTRACE interfaces provide three
+basic facilities:
+
+* Thread event reporting
+
+  Tracing engines can request callbacks for events of interest in
+  the thread: signals, system calls, exit, exec, clone, etc.
+
+* Core thread control
+
+  Tracing engines can prevent a thread from running (keeping it in
+  TASK_TRACED state), or make it single-step or block-step (when
+  hardware supports it).  Engines can cause a thread to abort system
+  calls, they change the behaviors of signals, and they can inject
+  signal-style actions at will.
+
+* Thread machine state access
+
+  Tracing engines can read and write a thread's registers and
+  similar per-thread CPU state.
+
+
+       Tracing engines
+       ------- -------
+
+The basic actors in UTRACE are the thread and the tracing engine.
+A tracing engine is some body of code that calls into the utrace_*
+interfaces, represented by a struct utrace_engine_ops.  (Usually it's a
+kernel module, though the legacy ptrace support is a tracing engine
+that is not in a kernel module.)  The UTRACE interface operates on
+individual threads (struct task_struct).  If an engine wants to
+treat several threads as a group, that is up to its higher-level
+code.  Using the UTRACE starts out by attaching an engine to a thread.
+
+       struct utrace_attached_engine *
+       utrace_attach(struct task_struct *target, int flags,
+                     const struct utrace_engine_ops *ops, unsigned long data);
+
+Calling utrace_attach is what sets up a tracing engine to trace a
+thread.  Use UTRACE_ATTACH_CREATE in flags, and pass your engine's ops.
+Check the return value with IS_ERR.  If successful, it returns a
+struct pointer that is the handle used in all other utrace_* calls.
+The data argument is stored in the utrace_attached_engine structure,
+for your code to use however it wants.
+
+       void utrace_detach(struct task_struct *target,
+                          struct utrace_attached_engine *engine);
+
+The utrace_detach call removes an engine from a thread.
+No more callbacks will be made after this returns.
+
+
+An attached engine does nothing by default.
+An engine makes something happen by setting its flags.
+
+       void utrace_set_flags(struct task_struct *target,
+                             struct utrace_attached_engine *engine,
+                             unsigned long flags);
+
+
+       Action Flags
+       ------ -----
+
+There are two kinds of flags that an attached engine can set: event
+flags, and action flags.  Event flags register interest in particular
+events; when an event happens and an engine has the right event flag
+set, it gets a callback.  Action flags change the normal behavior of
+the thread.  The action flags available are:
+
+       UTRACE_ACTION_QUIESCE
+
+               The thread will stay quiescent (see below).
+               As long as any engine asserts the QUIESCE action flag,
+               the thread will not resume running in user mode.
+               (Usually it will be in TASK_TRACED state.)
+               Nothing will wake the thread up except for SIGKILL
+               (and implicit SIGKILLs such as a core dump in
+               another thread sharing the same address space, or a
+               group exit or fatal signal in another thread in the
+               same thread group).
+
+       UTRACE_ACTION_SINGLESTEP
+
+               When the thread runs, it will run one instruction
+               and then trap.  (Exiting a system call or entering a
+               signal handler is considered "an instruction" for this.)
+               This can be used only if ARCH_HAS_SINGLE_STEP #define'd
+               by <asm/tracehook.h> and evaluates to nonzero.
+
+       UTRACE_ACTION_BLOCKSTEP
+
+               When the thread runs, it will run until the next branch,
+               and then trap.  (Exiting a system call or entering a
+               signal handler is considered a branch for this.)
+               When the SINGLESTEP flag is set, BLOCKSTEP has no effect.
+               This is only available on some machines (actually none yet).
+               This can be used only if ARCH_HAS_BLOCK_STEP #define'd
+               by <asm/tracehook.h> and evaluates to nonzero.
+
+       UTRACE_ACTION_NOREAP
+
+               When the thread exits or stops for job control, its
+               parent process will not receive a SIGCHLD and the
+               parent's wait calls will not wake up or report the
+               child as dead.  A well-behaved tracing engine does not
+               want to interfere with the parent's normal notifications.
+               This is provided mainly for the ptrace compatibility
+               code to implement the traditional behavior.
+
+Event flags are specified using the macro UTRACE_EVENT(TYPE).
+Each event type is associated with a report_* callback in struct
+utrace_engine_ops.  A tracing engine can leave unused callbacks NULL.
+The only callbacks required are those used by the event flags it sets.
+
+Many engines can be attached to each thread.  When a thread has an
+event, each engine gets a report_* callback if it has set the event flag
+for that event type.  Engines are called in the order they attached.
+
+Each callback takes arguments giving the details of the particular
+event.  The first two arguments two every callback are the struct
+utrace_attached_engine and struct task_struct pointers for the engine
+and the thread producing the event.  Usually this will be the current
+thread that is running the callback functions.
+
+The return value of report_* callbacks is a bitmask.  Some bits are
+common to all callbacks, and some are particular to that callback and
+event type.  The value zero (UTRACE_ACTION_RESUME) always means the
+simplest thing: do what would have happened with no tracing engine here.
+These are the flags that can be set in any report_* return value:
+
+       UTRACE_ACTION_NEWSTATE
+
+               Update the action state flags, described above.  Those
+               bits from the return value (UTRACE_ACTION_STATE_MASK)
+               replace those bits in the engine's flags.  This has the
+               same effect as calling utrace_set_flags, but is a more
+               efficient short-cut.  To change the event flags, you must
+               call utrace_set_flags.
+
+       UTRACE_ACTION_DETACH
+
+               Detach this engine.  This has the effect of calling
+               utrace_detach, but is a more efficient short-cut.
+
+       UTRACE_ACTION_HIDE
+
+               Hide this event from other tracing engines.  This is
+               only appropriate to do when the event was induced by
+               some action of this engine, such as a breakpoint trap.
+               Some events cannot be hidden, since every engine has to
+               know about them: exit, death, reap.
+
+The return value bits in UTRACE_ACTION_OP_MASK indicate a change to the
+normal behavior of the event taking place.  If zero, the thread does
+whatever that event normally means.  For report_signal, other values
+control the disposition of the signal.
+
+
+       Quiescence
+       ----------
+
+To control another thread and access its state, it must be "quiescent".
+This means that it is stopped and won't start running again while we access
+it.  A quiescent thread is stopped in a place close to user mode, where the
+user state can be accessed safely; either it's about to return to user
+mode, or it's just entered the kernel from user mode, or it has already
+finished exiting (TASK_ZOMBIE).  Setting the UTRACE_ACTION_QUIESCE action
+flag will force the attached thread to become quiescent soon.  After
+setting the flag, an engine must wait for an event callback when the thread
+becomes quiescent.  The thread may be running on another CPU, or may be in
+an uninterruptible wait.  When it is ready to be examined, it will make
+callbacks to engines that set the UTRACE_EVENT(QUIESCE) event flag.
+
+As long as some engine has UTRACE_ACTION_QUIESCE set, then the thread will
+remain stopped.  SIGKILL will wake it up, but it will not run user code.
+When the flag is cleared via utrace_set_flags or a callback return value,
+the thread starts running again.
+
+During the event callbacks (report_*), the thread in question makes the
+callback from a safe place.  It is not quiescent, but it can safely access
+its own state.  Callbacks can access thread state directly without setting
+the QUIESCE action flag.  If a callback does want to prevent the thread
+from resuming normal execution, it *must* use the QUIESCE action state
+rather than simply blocking; see "Core Events & Callbacks", below.
+
+
+       Thread control
+       ------ -------
+
+These calls must be made on a quiescent thread (or the current thread):
+
+       int utrace_inject_signal(struct task_struct *target,
+                                struct utrace_attached_engine *engine,
+                                u32 action, siginfo_t *info,
+                                const struct k_sigaction *ka);
+
+Cause a specified signal delivery in the target thread.  This is not
+like kill, which generates a signal to be dequeued and delivered later.
+Injection directs the thread to deliver a signal now, before it next
+resumes in user mode or dequeues any other pending signal.  It's as if
+the tracing engine intercepted a signal event and its report_signal
+callback returned the action argument as its value (see below).  The
+info and ka arguments serve the same purposes as their counterparts in
+a report_signal callback.
+
+       const struct utrace_regset *
+       utrace_regset(struct task_struct *target,
+                     struct utrace_attached_engine *engine,
+                     const struct utrace_regset_view *view,
+                     int which);
+
+Get access to machine state for the thread.  The struct utrace_regset_view
+indicates a view of machine state, corresponding to a user mode
+architecture personality (such as 32-bit or 64-bit versions of a machine).
+The which argument selects one of the register sets available in that view.
+The utrace_regset call must be made before accessing any machine state,
+each time the thread has been running and has then become quiescent.
+It ensures that the thread's state is ready to be accessed, and returns
+the struct utrace_regset giving its accessor functions.
+
+XXX needs front ends for argument checks, export utrace_native_view
+
+
+       Core Events & Callbacks
+       ---- ------ - ---------
+
+Event reporting callbacks have details particular to the event type, but
+are all called in similar environments and have the same constraints.
+Callbacks are made from safe spots, where no locks are held, no special
+resources are pinned, and the user-mode state of the thread is accessible.
+So, callback code has a pretty free hand.  But to be a good citizen,
+callback code should never block for long periods.  It is fine to block in
+kmalloc and the like, but never wait for i/o or for user mode to do
+something.  If you need the thread to wait, set UTRACE_ACTION_QUIESCE and
+return from the callback quickly.  When your i/o finishes or whatever, you
+can use utrace_set_flags to resume the thread.
+
+Well-behaved callbacks are important to maintain two essential properties
+of the interface.  The first of these is that unrelated tracing engines not
+interfere with each other.  If your engine's event callback does not return
+quickly, then another engine won't get the event notification in a timely
+manner.  The second important property is that tracing be as noninvasive as
+possible to the normal operation of the system overall and of the traced
+thread in particular.  That is, attached tracing engines should not perturb
+a thread's behavior, except to the extent that changing its user-visible
+state is explicitly what you want to do.  (Obviously some perturbation is
+unavoidable, primarily timing changes, ranging from small delays due to the
+overhead of tracing, to arbitrary pauses in user code execution when a user
+stops a thread with a debugger for examination.  When doing asynchronous
+utrace_attach to a thread doing a system call, more troublesome side
+effects are possible.)  Even when you explicitly want the pertrubation of
+making the traced thread block, just blocking directly in your callback has
+more unwanted effects.  For example, the CLONE event callbacks are called
+when the new child thread has been created but not yet started running; the
+child can never be scheduled until the CLONE tracing callbacks return.
+(This allows engines tracing the parent to attach to the child.)  If a
+CLONE event callback blocks the parent thread, it also prevents the child
+thread from running (even to process a SIGKILL).  If what you want is to
+make both the parent and child block, then use utrace_attach on the child
+and then set the QUIESCE action state flag on both threads.  A more crucial
+problem with blocking in callbacks is that it can prevent SIGKILL from
+working.  A thread that is blocking due to UTRACE_ACTION_QUIESCE will still
+wake up and die immediately when sent a SIGKILL, as all threads should.
+Relying on the utrace infrastructure rather than on private synchronization
+calls in event callbacks is an important way to help keep tracing robustly
+noninvasive.
+
+
+EVENT(REAP)            Dead thread has been reaped
+Callback:
+       void (*report_reap)(struct utrace_attached_engine *engine,
+                           struct task_struct *tsk);
+
+This means the parent called wait, or else this was a detached thread or
+a process whose parent ignores SIGCHLD.  This cannot happen while the
+UTRACE_ACTION_NOREAP flag is set.  This is the only callback you are
+guaranteed to get (if you set the flag).
+
+Unlike other callbacks, this can be called from the parent's context
+rather than from the traced thread itself--it must not delay the parent by
+blocking.  This callback is different from all others, it returns void.
+Once you get this callback, your engine is automatically detached and you
+cannot access this thread or use this struct utrace_attached_engine handle
+any longer.  This is the place to clean up your data structures and
+synchronize with your code that might try to make utrace_* calls using this
+engine data structure.  The struct is still valid during this callback,
+but will be freed soon after it returns (via RCU).
+
+In all other callbacks, the return value is as described above.
+The common UTRACE_ACTION_* flags in the return value are always observed.
+Unless otherwise specified below, other bits in the return value are ignored.
+
+
+EVENT(QUIESCE)         Thread is quiescent
+Callback:
+       u32 (*report_quiesce)(struct utrace_attached_engine *engine,
+                             struct task_struct *tsk);
+
+This is the least interesting callback.  It happens at any safe spot,
+including after any other event callback.  This lets the tracing engine
+know that it is safe to access the thread's state, or to report to users
+that it has stopped running user code.
+
+EVENT(CLONE)           Thread is creating a child
+Callback:
+       u32 (*report_clone)(struct utrace_attached_engine *engine,
+                           struct task_struct *parent,
+                           unsigned long clone_flags,
+                           struct task_struct *child);
+
+A clone/clone2/fork/vfork system call has succeeded in creating a new
+thread or child process.  The new process is fully formed, but not yet
+running.  During this callback, other tracing engines are prevented from
+using utrace_attach asynchronously on the child, so that engines tracing
+the parent get the first opportunity to attach.  After this callback
+returns, the child will start and the parent's system call will return.
+If CLONE_VFORK is set, the parent will block before returning.
+
+EVENT(VFORK_DONE)      Finished waiting for CLONE_VFORK child
+Callback:
+       u32 (*report_vfork_done)(struct utrace_attached_engine *engine,
+                                struct task_struct *parent, pid_t child_pid);
+
+Event reported for parent using CLONE_VFORK or vfork system call.
+The child has died or exec'd, so the vfork parent has unblocked
+and is about to return child_pid.
+
+UTRACE_EVENT(EXEC)             Completed exec
+Callback:
+       u32 (*report_exec)(struct utrace_attached_engine *engine,
+                          struct task_struct *tsk,
+                          const struct linux_binprm *bprm,
+                          struct pt_regs *regs);
+
+An execve system call has succeeded and the new program is about to
+start running.  The initial user register state is handy to be tweaked
+directly, or utrace_regset can be used for full machine state access.
+
+UTRACE_EVENT(EXIT)             Thread is exiting
+Callback:
+       u32 (*report_exit)(struct utrace_attached_engine *engine,
+                          struct task_struct *tsk,
+                          long orig_code, long *code);
+
+The thread is exiting and cannot be prevented from doing so, but all its
+state is still live.  The *code value will be the wait result seen by
+the parent, and can be changed by this engine or others.  The orig_code
+value is the real status, not changed by any tracing engine.
+
+UTRACE_EVENT(DEATH)            Thread has finished exiting
+Callback:
+       u32 (*report_death)(struct utrace_attached_engine *engine,
+                           struct task_struct *tsk);
+
+The thread is really dead now.  If the UTRACE_ACTION_NOREAP flag is set
+after this callback, it remains an unreported zombie.  Otherwise, it might
+be reaped by its parent, or self-reap immediately.  Though the actual
+reaping may happen in parallel, a report_reap callback will always be
+ordered after a report_death callback.
+
+UTRACE_EVENT(SYSCALL_ENTRY)    Thread has entered kernel for a system call
+Callback:
+       u32 (*report_syscall_entry)(struct utrace_attached_engine *engine,
+                                   struct task_struct *tsk,
+                                   struct pt_regs *regs);
+
+The system call number and arguments can be seen and modified in the
+registers.  The return value register has -ENOSYS, which will be
+returned for an invalid system call.  The macro tracehook_abort_syscall(regs)
+will abort the system call so that we go immediately to syscall exit,
+and return -ENOSYS (or whatever the register state is changed to).  If
+tracing enginges keep the thread quiescent here, the system call will
+not be performed until it resumes.
+
+UTRACE_EVENT(SYSCALL_EXIT)     Thread is leaving kernel after a system call
+Callback:
+       u32 (*report_syscall_exit)(struct utrace_attached_engine *engine,
+                                  struct task_struct *tsk,
+                                  struct pt_regs *regs);
+
+The return value can be seen and modified in the registers.  If the
+thread is allowed to resume, it will see any pending signals and then
+return to user mode.
+
+UTRACE_EVENT(SIGNAL)           Signal caught by user handler
+UTRACE_EVENT(SIGNAL_IGN)               Signal with no effect (SIG_IGN or default)
+UTRACE_EVENT(SIGNAL_STOP)      Job control stop signal
+UTRACE_EVENT(SIGNAL_TERM)      Fatal termination signal
+UTRACE_EVENT(SIGNAL_CORE)      Fatal core-dump signal
+UTRACE_EVENT_SIGNAL_ALL                All of the above (bitmask)
+Callback:
+       u32 (*report_signal)(struct utrace_attached_engine *engine,
+                            struct task_struct *tsk,
+                            u32 action, siginfo_t *info,
+                            const struct k_sigaction *orig_ka,
+                            struct k_sigaction *return_ka);
+
+There are five types of signal events, but all use the same callback.
+These happen when a thread is dequeuing a signal to be delivered.
+(Not immediately when the signal is sent, and not when the signal is
+blocked.)  No signal event is reported for SIGKILL; no tracing engine
+can prevent it from killing the thread immediately.  The specific
+event types allow an engine to trace signals based on what they do.
+UTRACE_EVENT_SIGNAL_ALL is all of them OR'd together, to trace all
+signals (except SIGKILL).  A subset of these event flags can be used
+e.g. to catch only fatal signals, not handled ones, or to catch only
+core-dump signals, not normal termination signals.
+
+The action argument says what the signal's default disposition is:
+
+       UTRACE_SIGNAL_DELIVER   Run the user handler from sigaction.
+       UTRACE_SIGNAL_IGN       Do nothing, ignore the signal.
+       UTRACE_SIGNAL_TERM      Terminate the process.
+       UTRACE_SIGNAL_CORE      Terminate the process a write a core dump.
+       UTRACE_SIGNAL_STOP      Absolutely stop the process, a la SIGSTOP.
+       UTRACE_SIGNAL_TSTP      Job control stop (no stop if orphaned).
+
+This selection is made from consulting the process's sigaction and the
+default action for the signal number, but may already have been
+changed by an earlier tracing engine (in which case you see its override).
+A return value of UTRACE_ACTION_RESUME means to carry out this action.
+If instead UTRACE_SIGNAL_* bits are in the return value, that overrides
+the normal behavior of the signal.
+
+The signal number and other details of the signal are in info, and
+this data can be changed to make the thread see a different signal.
+A return value of UTRACE_SIGNAL_DELIVER says to follow the sigaction in
+return_ka, which can specify a user handler or SIG_IGN to ignore the
+signal or SIG_DFL to follow the default action for info->si_signo.
+The orig_ka parameter shows the process's sigaction at the time the
+signal was dequeued, and return_ka initially contains this.  Tracing
+engines can modify return_ka to change the effects of delivery.
+For other UTRACE_SIGNAL_* return values, return_ka is ignored.
+
+UTRACE_SIGNAL_HOLD is a flag bit that can be OR'd into the return
+value.  It says to push the signal back on the thread's queue, with
+the signal number and details possibly changed in info.  When the
+thread is allowed to resume, it will dequeue and report it again.
diff --git a/Documentation/video4linux/README.pvrusb2 b/Documentation/video4linux/README.pvrusb2
new file mode 100644 (file)
index 0000000..c73a32c
--- /dev/null
@@ -0,0 +1,212 @@
+
+$Id$
+Mike Isely <isely@pobox.com>
+
+                           pvrusb2 driver
+
+Background:
+
+  This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which
+  is a USB 2.0 hosted TV Tuner.  This driver is a work in progress.
+  Its history started with the reverse-engineering effort by Björn
+  Danielsson <pvrusb2@dax.nu> whose web page can be found here:
+
+    http://pvrusb2.dax.nu/
+
+  From there Aurelien Alleaume <slts@free.fr> began an effort to
+  create a video4linux compatible driver.  I began with Aurelien's
+  last known snapshot and evolved the driver to the state it is in
+  here.
+
+  More information on this driver can be found at:
+
+    http://www.isely.net/pvrusb2.html
+
+
+  This driver has a strong separation of layers.  They are very
+  roughly:
+
+  1a. Low level wire-protocol implementation with the device.
+
+  1b. I2C adaptor implementation and corresponding I2C client drivers
+      implemented elsewhere in V4L.
+
+  1c. High level hardware driver implementation which coordinates all
+      activities that ensure correct operation of the device.
+
+  2.  A "context" layer which manages instancing of driver, setup,
+      tear-down, arbitration, and interaction with high level
+      interfaces appropriately as devices are hotplugged in the
+      system.
+
+  3.  High level interfaces which glue the driver to various published
+      Linux APIs (V4L, sysfs, maybe DVB in the future).
+
+  The most important shearing layer is between the top 2 layers.  A
+  lot of work went into the driver to ensure that any kind of
+  conceivable API can be laid on top of the core driver.  (Yes, the
+  driver internally leverages V4L to do its work but that really has
+  nothing to do with the API published by the driver to the outside
+  world.)  The architecture allows for different APIs to
+  simultaneously access the driver.  I have a strong sense of fairness
+  about APIs and also feel that it is a good design principle to keep
+  implementation and interface isolated from each other.  Thus while
+  right now the V4L high level interface is the most complete, the
+  sysfs high level interface will work equally well for similar
+  functions, and there's no reason I see right now why it shouldn't be
+  possible to produce a DVB high level interface that can sit right
+  alongside V4L.
+
+  NOTE: Complete documentation on the pvrusb2 driver is contained in
+  the html files within the doc directory; these are exactly the same
+  as what is on the web site at the time.  Browse those files
+  (especially the FAQ) before asking questions.
+
+
+Building
+
+  To build these modules essentially amounts to just running "Make",
+  but you need the kernel source tree nearby and you will likely also
+  want to set a few controlling environment variables first in order
+  to link things up with that source tree.  Please see the Makefile
+  here for comments that explain how to do that.
+
+
+Source file list / functional overview:
+
+  (Note: The term "module" used below generally refers to loosely
+  defined functional units within the pvrusb2 driver and bears no
+  relation to the Linux kernel's concept of a loadable module.)
+
+  pvrusb2-audio.[ch] - This is glue logic that resides between this
+    driver and the msp3400.ko I2C client driver (which is found
+    elsewhere in V4L).
+
+  pvrusb2-context.[ch] - This module implements the context for an
+    instance of the driver.  Everything else eventually ties back to
+    or is otherwise instanced within the data structures implemented
+    here.  Hotplugging is ultimately coordinated here.  All high level
+    interfaces tie into the driver through this module.  This module
+    helps arbitrate each interface's access to the actual driver core,
+    and is designed to allow concurrent access through multiple
+    instances of multiple interfaces (thus you can for example change
+    the tuner's frequency through sysfs while simultaneously streaming
+    video through V4L out to an instance of mplayer).
+
+  pvrusb2-debug.h - This header defines a printk() wrapper and a mask
+    of debugging bit definitions for the various kinds of debug
+    messages that can be enabled within the driver.
+
+  pvrusb2-debugifc.[ch] - This module implements a crude command line
+    oriented debug interface into the driver.  Aside from being part
+    of the process for implementing manual firmware extraction (see
+    the pvrusb2 web site mentioned earlier), probably I'm the only one
+    who has ever used this.  It is mainly a debugging aid.
+
+  pvrusb2-eeprom.[ch] - This is glue logic that resides between this
+    driver the tveeprom.ko module, which is itself implemented
+    elsewhere in V4L.
+
+  pvrusb2-encoder.[ch] - This module implements all protocol needed to
+    interact with the Conexant mpeg2 encoder chip within the pvrusb2
+    device.  It is a crude echo of corresponding logic in ivtv,
+    however the design goals (strict isolation) and physical layer
+    (proxy through USB instead of PCI) are enough different that this
+    implementation had to be completely different.
+
+  pvrusb2-hdw-internal.h - This header defines the core data structure
+    in the driver used to track ALL internal state related to control
+    of the hardware.  Nobody outside of the core hardware-handling
+    modules should have any business using this header.  All external
+    access to the driver should be through one of the high level
+    interfaces (e.g. V4L, sysfs, etc), and in fact even those high
+    level interfaces are restricted to the API defined in
+    pvrusb2-hdw.h and NOT this header.
+
+  pvrusb2-hdw.h - This header defines the full internal API for
+    controlling the hardware.  High level interfaces (e.g. V4L, sysfs)
+    will work through here.
+
+  pvrusb2-hdw.c - This module implements all the various bits of logic
+    that handle overall control of a specific pvrusb2 device.
+    (Policy, instantiation, and arbitration of pvrusb2 devices fall
+    within the jurisdiction of pvrusb-context not here).
+
+  pvrusb2-i2c-chips-*.c - These modules implement the glue logic to
+    tie together and configure various I2C modules as they attach to
+    the I2C bus.  There are two versions of this file.  The "v4l2"
+    version is intended to be used in-tree alongside V4L, where we
+    implement just the logic that makes sense for a pure V4L
+    environment.  The "all" version is intended for use outside of
+    V4L, where we might encounter other possibly "challenging" modules
+    from ivtv or older kernel snapshots (or even the support modules
+    in the standalone snapshot).
+
+  pvrusb2-i2c-cmd-v4l1.[ch] - This module implements generic V4L1
+    compatible commands to the I2C modules.  It is here where state
+    changes inside the pvrusb2 driver are translated into V4L1
+    commands that are in turn send to the various I2C modules.
+
+  pvrusb2-i2c-cmd-v4l2.[ch] - This module implements generic V4L2
+    compatible commands to the I2C modules.  It is here where state
+    changes inside the pvrusb2 driver are translated into V4L2
+    commands that are in turn send to the various I2C modules.
+
+  pvrusb2-i2c-core.[ch] - This module provides an implementation of a
+    kernel-friendly I2C adaptor driver, through which other external
+    I2C client drivers (e.g. msp3400, tuner, lirc) may connect and
+    operate corresponding chips within the the pvrusb2 device.  It is
+    through here that other V4L modules can reach into this driver to
+    operate specific pieces (and those modules are in turn driven by
+    glue logic which is coordinated by pvrusb2-hdw, doled out by
+    pvrusb2-context, and then ultimately made available to users
+    through one of the high level interfaces).
+
+  pvrusb2-io.[ch] - This module implements a very low level ring of
+    transfer buffers, required in order to stream data from the
+    device.  This module is *very* low level.  It only operates the
+    buffers and makes no attempt to define any policy or mechanism for
+    how such buffers might be used.
+
+  pvrusb2-ioread.[ch] - This module layers on top of pvrusb2-io.[ch]
+    to provide a streaming API usable by a read() system call style of
+    I/O.  Right now this is the only layer on top of pvrusb2-io.[ch],
+    however the underlying architecture here was intended to allow for
+    other styles of I/O to be implemented with additonal modules, like
+    mmap()'ed buffers or something even more exotic.
+
+  pvrusb2-main.c - This is the top level of the driver.  Module level
+    and USB core entry points are here.  This is our "main".
+
+  pvrusb2-sysfs.[ch] - This is the high level interface which ties the
+    pvrusb2 driver into sysfs.  Through this interface you can do
+    everything with the driver except actually stream data.
+
+  pvrusb2-tuner.[ch] - This is glue logic that resides between this
+    driver and the tuner.ko I2C client driver (which is found
+    elsewhere in V4L).
+
+  pvrusb2-util.h - This header defines some common macros used
+    throughout the driver.  These macros are not really specific to
+    the driver, but they had to go somewhere.
+
+  pvrusb2-v4l2.[ch] - This is the high level interface which ties the
+    pvrusb2 driver into video4linux.  It is through here that V4L
+    applications can open and operate the driver in the usual V4L
+    ways.  Note that **ALL** V4L functionality is published only
+    through here and nowhere else.
+
+  pvrusb2-video-*.[ch] - This is glue logic that resides between this
+    driver and the saa711x.ko I2C client driver (which is found
+    elsewhere in V4L).  Note that saa711x.ko used to be known as
+    saa7115.ko in ivtv.  There are two versions of this; one is
+    selected depending on the particular saa711[5x].ko that is found.
+
+  pvrusb2.h - This header contains compile time tunable parameters
+    (and at the moment the driver has very little that needs to be
+    tuned).
+
+
+  -Mike Isely
+  isely@pobox.com
+
diff --git a/Documentation/video4linux/cx2341x/fw-calling.txt b/Documentation/video4linux/cx2341x/fw-calling.txt
new file mode 100644 (file)
index 0000000..8d21181
--- /dev/null
@@ -0,0 +1,69 @@
+This page describes how to make calls to the firmware api.
+
+How to call
+===========
+
+The preferred calling convention is known as the firmware mailbox. The
+mailboxes are basically a fixed length array that serves as the call-stack.
+
+Firmware mailboxes can be located by searching the encoder and decoder memory
+for a 16 byte signature. That signature will be located on a 256-byte boundary.
+
+Signature:
+0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34,
+0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78
+
+The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are
+reserved for API calls. The second 10 are used by the firmware for event
+notification.
+
+  Index  Name
+  -----  ----
+  0      Flags
+  1      Command
+  2      Return value
+  3      Timeout
+  4-19   Parameter/Result
+
+
+The flags are defined in the following table. The direction is from the
+perspective of the firmware.
+
+  Bit  Direction  Purpose
+  ---  ---------  -------
+  2    O          Firmware has processed the command.
+  1    I          Driver has finished setting the parameters.
+  0    I          Driver is using this mailbox.
+
+
+The command is a 32-bit enumerator. The API specifics may be found in the
+fw-*-api.txt documents.
+
+The return value is a 32-bit enumerator. Only two values are currently defined:
+0=success and -1=command undefined.
+
+There are 16 parameters/results 32-bit fields. The driver populates these fields
+with values for all the parameters required by the call. The driver overwrites
+these fields with result values returned by the call. The API specifics may be
+found in the fw-*-api.txt documents.
+
+The timeout value protects the card from a hung driver thread. If the driver
+doesn't handle the completed call within the timeout specified, the firmware
+will reset that mailbox.
+
+To make an API call, the driver iterates over each mailbox looking for the
+first one available (bit 0 has been cleared). The driver sets that bit, fills
+in the command enumerator, the timeout value and any required parameters. The
+driver then sets the parameter ready bit (bit 1). The firmware scans the
+mailboxes for pending commands, processes them, sets the result code, populates
+the result value array with that call's return values and sets the call
+complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results
+and clear all the flags. If the driver does not perform this task within the
+time set in the timeout register, the firmware will reset that mailbox.
+
+Event notifications are sent from the firmware to the host. The host tells the
+firmware which events it is interested in via an API call. That call tells the
+firmware which notification mailbox to use. The firmware signals the host via
+an interrupt. Only the 16 Results fields are used, the Flags, Command, Return
+value and Timeout words are not used.
+
diff --git a/Documentation/video4linux/cx2341x/fw-decoder-api.txt b/Documentation/video4linux/cx2341x/fw-decoder-api.txt
new file mode 100644 (file)
index 0000000..9df4fb3
--- /dev/null
@@ -0,0 +1,319 @@
+Decoder firmware API description
+================================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_PING_FW
+Enum   0/0x00
+Description
+       This API call does nothing. It may be used to check if the firmware
+       is responding.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_START_PLAYBACK
+Enum   1/0x01
+Description
+       Begin or resume playback.
+Param[0]
+       0 based frame number in GOP to begin playback from.
+Param[1]
+       Specifies the number of muted audio frames to play before normal
+       audio resumes.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_STOP_PLAYBACK
+Enum   2/0x02
+Description
+       Ends playback and clears all decoder buffers. If PTS is not zero,
+       playback stops at specified PTS.
+Param[0]
+       Display 0=last frame, 1=black
+Param[1]
+       PTS low
+Param[2]
+       PTS high
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_PLAYBACK_SPEED
+Enum   3/0x03
+Description
+       Playback stream at speed other than normal. There are two modes of
+       operation:
+           Smooth: host transfers entire stream and firmware drops unused
+                   frames.
+           Coarse: host drops frames based on indexing as required to achieve
+                   desired speed.
+Param[0]
+       Bitmap:
+           0:7  0 normal
+                1 fast only "1.5 times"
+                n nX fast, 1/nX slow
+           30   Framedrop:
+                    '0' during 1.5 times play, every other B frame is dropped
+                    '1' during 1.5 times play, stream is unchanged (bitrate
+                        must not exceed 8mbps)
+           31   Speed:
+                    '0' slow
+                    '1' fast
+Param[1]
+       Direction: 0=forward, 1=reverse
+Param[2]
+       Picture mask:
+           1=I frames
+           3=I, P frames
+           7=I, P, B frames
+Param[3]
+       B frames per GOP (for reverse play only)
+Param[4]
+       Mute audio: 0=disable, 1=enable
+Param[5]
+       Display 0=frame, 1=field
+Param[6]
+       Specifies the number of muted audio frames to play before normal audio
+       resumes.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_STEP_VIDEO
+Enum   5/0x05
+Description
+       Each call to this API steps the playback to the next unit defined below
+       in the current playback direction.
+Param[0]
+       0=frame, 1=top field, 2=bottom field
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_DMA_BLOCK_SIZE
+Enum   8/0x08
+Description
+       Set DMA transfer block size. Counterpart to API 0xC9
+Param[0]
+       DMA transfer block size in bytes. A different size may be specified
+       when issuing the DMA transfer command.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_XFER_INFO
+Enum   9/0x09
+Description
+       This API call may be used to detect an end of stream condtion.
+Result[0]
+       Stream type
+Result[1]
+       Address offset
+Result[2]
+       Maximum bytes to transfer
+Result[3]
+       Buffer fullness
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_DMA_STATUS
+Enum   10/0x0A
+Description
+       Status of the last DMA transfer
+Result[0]
+       Bit 1 set means transfer complete
+       Bit 2 set means DMA error
+       Bit 3 set means linked list error
+Result[1]
+       DMA type: 0=MPEG, 1=OSD, 2=YUV
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SCHED_DMA_FROM_HOST
+Enum   11/0x0B
+Description
+       Setup DMA from host operation. Counterpart to API 0xCC
+Param[0]
+       Memory address of link list
+Param[1]
+       Total # of bytes to transfer
+Param[2]
+       DMA type (0=MPEG, 1=OSD, 2=YUV)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_PAUSE_PLAYBACK
+Enum   13/0x0D
+Description
+       Freeze playback immediately. In this mode, when internal buffers are
+       full, no more data will be accepted and data request IRQs will be
+       masked.
+Param[0]
+       Display: 0=last frame, 1=black
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_HALT_FW
+Enum   14/0x0E
+Description
+       The firmware is halted and no further API calls are serviced until
+       the firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_STANDARD
+Enum   16/0x10
+Description
+       Selects display standard
+Param[0]
+       0=NTSC, 1=PAL
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_VERSION
+Enum   17/0x11
+Description
+       Returns decoder firmware version information
+Result[0]
+       Version bitmask:
+           Bits  0:15 build
+           Bits 16:23 minor
+           Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_STREAM_INPUT
+Enum   20/0x14
+Description
+       Select decoder stream input port
+Param[0]
+       0=memory (default), 1=streaming
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_TIMING_INFO
+Enum   21/0x15
+Description
+       Returns timing information from start of playback
+Result[0]
+       Frame count by decode order
+Result[1]
+       Video PTS bits 0:31 by display order
+Result[2]
+       Video PTS bit 32 by display order
+Result[3]
+       SCR bits 0:31 by display order
+Result[4]
+       SCR bit 32 by display order
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_AUDIO_MODE
+Enum   22/0x16
+Description
+       Select audio mode
+Param[0]
+       Dual mono mode action
+Param[1]
+       Stereo mode action:
+           0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_EVENT_NOTIFICATION
+Enum   23/0x17
+Description
+       Setup firmware to notify the host about a particular event.
+       Counterpart to API 0xD5
+Param[0]
+       Event: 0=Audio mode change between stereo and dual channel
+Param[1]
+       Notification 0=disabled, 1=enabled
+Param[2]
+       Interrupt bit
+Param[3]
+       Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_DISPLAY_BUFFERS
+Enum   24/0x18
+Description
+       Number of display buffers. To decode all frames in reverse playback you
+       must use nine buffers.
+Param[0]
+       0=six buffers, 1=nine buffers
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_EXTRACT_VBI
+Enum   25/0x19
+Description
+       Extracts VBI data
+Param[0]
+       0=extract from extension & user data, 1=extract from private packets
+Result[0]
+       VBI table location
+Result[1]
+       VBI table size
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_DECODER_SOURCE
+Enum   26/0x1A
+Description
+       Selects decoder source. Ensure that the parameters passed to this
+       API match the encoder settings.
+Param[0]
+       Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host
+Param[1]
+       YUV picture width
+Param[2]
+       YUV picture height
+Param[3]
+       Bitmap: see Param[0] of API 0xBD
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_AUDIO_OUTPUT
+Enum   27/0x1B
+Description
+       Select audio output format
+Param[0]
+       Bitmask:
+            0:1  Data size:
+                     '00' 16 bit
+                     '01' 20 bit
+                     '10' 24 bit
+            2:7  Unused
+            8:9  Mode:
+                     '00' 2 channels
+                     '01' 4 channels
+                     '10' 6 channels
+                     '11' 6 channels with one line data mode
+                          (for left justified MSB first mode, 20 bit only)
+           10:11 Unused
+           12:13 Channel format:
+                     '00' right justified MSB first mode
+                     '01' left justified MSB first mode
+                     '10' I2S mode
+           14:15 Unused
+           16:21 Right justify bit count
+           22:31 Unused
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_AV_DELAY
+Enum   28/0x1C
+Description
+       Set audio/video delay in 90Khz ticks
+Param[0]
+       0=A/V in sync, negative=audio lags, positive=video lags
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_PREBUFFERING
+Enum   30/0x1E
+Description
+       Decoder prebuffering, when enabled up to 128KB are buffered for
+       streams <8mpbs or 640KB for streams >8mbps
+Param[0]
+       0=off, 1=on
diff --git a/Documentation/video4linux/cx2341x/fw-dma.txt b/Documentation/video4linux/cx2341x/fw-dma.txt
new file mode 100644 (file)
index 0000000..8123e26
--- /dev/null
@@ -0,0 +1,94 @@
+This page describes the structures and procedures used by the cx2341x DMA
+engine.
+
+Introduction
+============
+
+The cx2341x PCI interface is busmaster capable. This means it has a DMA
+engine to efficiently transfer large volumes of data between the card and main
+memory without requiring help from a CPU. Like most hardware, it must operate
+on contiguous physical memory. This is difficult to come by in large quantities
+on virtual memory machines.
+
+Therefore, it also supports a technique called "scatter-gather". The card can
+transfer multiple buffers in one operation. Instead of allocating one large
+contiguous buffer, the driver can allocate several smaller buffers.
+
+In practice, I've seen the average transfer to be roughly 80K, but transfers
+above 128K were not uncommon, particularly at startup. The 128K figure is
+important, because that is the largest block that the kernel can normally
+allocate. Even still, 128K blocks are hard to come by, so the driver writer is
+urged to choose a smaller block size and learn the scatter-gather technique.
+
+Mailbox #10 is reserved for DMA transfer information.
+
+Flow
+====
+
+This section describes, in general, the order of events when handling DMA
+transfers. Detailed information follows this section.
+
+- The card raises the Encoder interrupt.
+- The driver reads the transfer type, offset and size from Mailbox #10.
+- The driver constructs the scatter-gather array from enough free dma buffers
+  to cover the size.
+- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call.
+- The card raises the DMA Complete interrupt.
+- The driver checks the DMA status register for any errors.
+- The driver post-processes the newly transferred buffers.
+
+NOTE! It is possible that the Encoder and DMA Complete interrupts get raised
+simultaneously. (End of the last, start of the next, etc.)
+
+Mailbox #10
+===========
+
+The Flags, Command, Return Value and Timeout fields are ignored.
+
+Name:       Mailbox #10
+Results[0]: Type: 0: MPEG.
+Results[1]: Offset: The position relative to the card's memory space.
+Results[2]: Size: The exact number of bytes to transfer.
+
+My speculation is that since the StartCapture API has a capture type of "RAW"
+available, that the type field will have other values that correspond to YUV
+and PCM data.
+
+Scatter-Gather Array
+====================
+
+The scatter-gather array is a contiguously allocated block of memory that
+tells the card the source and destination of each data-block to transfer.
+Card "addresses" are derived from the offset supplied by Mailbox #10. Host
+addresses are the physical memory location of the target DMA buffer.
+
+Each S-G array element is a struct of three 32-bit words. The first word is
+the source address, the second is the destination address. Both take up the
+entire 32 bits. The lowest 16 bits of the third word is the transfer byte
+count. The high-bit of the third word is the "last" flag. The last-flag tells
+the card to raise the DMA_DONE interrupt. From hard personal experience, if
+you forget to set this bit, the card will still "work" but the stream will
+most likely get corrupted.
+
+The transfer count must be a multiple of 256. Therefore, the driver will need
+to track how much data in the target buffer is valid and deal with it
+accordingly.
+
+Array Element:
+
+- 32-bit Source Address
+- 32-bit Destination Address
+- 16-bit reserved (high bit is the last flag)
+- 16-bit byte count
+
+DMA Transfer Status
+===================
+
+Register 0x0004 holds the DMA Transfer Status:
+
+Bit
+4   Scatter-Gather array error
+3   DMA write error
+2   DMA read error
+1   write completed
+0   read completed
diff --git a/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/Documentation/video4linux/cx2341x/fw-encoder-api.txt
new file mode 100644 (file)
index 0000000..001c686
--- /dev/null
@@ -0,0 +1,694 @@
+Encoder firmware API description
+================================
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_PING_FW
+Enum   128/0x80
+Description
+       Does nothing. Can be used to check if the firmware is responding.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_START_CAPTURE
+Enum   129/0x81
+Description
+       Commences the capture of video, audio and/or VBI data. All encoding
+       parameters must be initialized prior to this API call. Captures frames
+       continuously or until a predefined number of frames have been captured.
+Param[0]
+       Capture stream type:
+           0=MPEG
+           1=Raw
+           2=Raw passthrough
+           3=VBI
+
+Param[1]
+       Bitmask:
+           Bit 0 when set, captures YUV
+           Bit 1 when set, captures PCM audio
+           Bit 2 when set, captures VBI (same as param[0]=3)
+           Bit 3 when set, the capture destination is the decoder
+               (same as param[0]=2)
+           Bit 4 when set, the capture destination is the host
+       Note: this parameter is only meaningful for RAW capture type.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_STOP_CAPTURE
+Enum   130/0x82
+Description
+       Ends a capture in progress
+Param[0]
+       0=stop at end of GOP (generates IRQ)
+       1=stop immediate (no IRQ)
+Param[1]
+       Stream type to stop, see param[0] of API 0x81
+Param[2]
+       Subtype, see param[1] of API 0x81
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_AUDIO_ID
+Enum   137/0x89
+Description
+       Assigns the transport stream ID of the encoded audio stream
+Param[0]
+       Audio Stream ID
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_VIDEO_ID
+Enum   139/0x8B
+Description
+       Set video transport stream ID
+Param[0]
+       Video stream ID
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_PCR_ID
+Enum   141/0x8D
+Description
+       Assigns the transport stream ID for PCR packets
+Param[0]
+       PCR Stream ID
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_FRAME_RATE
+Enum   143/0x8F
+Description
+       Set video frames per second. Change occurs at start of new GOP.
+Param[0]
+       0=30fps
+       1=25fps
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_FRAME_SIZE
+Enum   145/0x91
+Description
+       Select video stream encoding resolution.
+Param[0]
+       Height in lines. Default 480
+Param[1]
+       Width in pixels. Default 720
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_BIT_RATE
+Enum   149/0x95
+Description
+       Assign average video stream bitrate. Note on the last three params:
+       Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used.
+Param[0]
+       0=variable bitrate, 1=constant bitrate
+Param[1]
+       bitrate in bits per second
+Param[2]
+       peak bitrate in bits per second, divided by 400
+Param[3]
+       Mux bitrate in bits per second, divided by 400. May be 0 (default).
+Param[4]
+       Rate Control VBR Padding
+Param[5]
+       VBV Buffer used by encoder
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_GOP_PROPERTIES
+Enum   151/0x97
+Description
+       Setup the GOP structure
+Param[0]
+       GOP size (maximum is 34)
+Param[1]
+       Number of B frames between the I and P frame, plus 1.
+       For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3
+       Note that GOP size must be a multiple of (B-frames + 1).
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_ASPECT_RATIO
+Enum   153/0x99
+Description
+       Sets the encoding aspect ratio. Changes in the aspect ratio take effect
+       at the start of the next GOP.
+Param[0]
+       '0000' forbidden
+       '0001' 1:1 square
+       '0010' 4:3
+       '0011' 16:9
+       '0100' 2.21:1
+       '0101' reserved
+        ....
+       '1111' reserved
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_DNR_FILTER_MODE
+Enum   155/0x9B
+Description
+       Assign Dynamic Noise Reduction operating mode
+Param[0]
+       Bit0: Spatial filter, set=auto, clear=manual
+       Bit1: Temporal filter, set=auto, clear=manual
+Param[1]
+       Median filter:
+           0=Disabled
+           1=Horizontal
+           2=Vertical
+           3=Horiz/Vert
+           4=Diagonal
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_DNR_FILTER_PROPS
+Enum   157/0x9D
+Description
+       These Dynamic Noise Reduction filter values are only meaningful when
+       the respective filter is set to "manual" (See API 0x9B)
+Param[0]
+       Spatial filter: default 0, range 0:15
+Param[1]
+       Temporal filter: default 0, range 0:31
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_CORING_LEVELS
+Enum   159/0x9F
+Description
+       Assign Dynamic Noise Reduction median filter properties.
+Param[0]
+       Threshold above which the luminance median filter is enabled.
+       Default: 0, range 0:255
+Param[1]
+       Threshold below which the luminance median filter is enabled.
+       Default: 255, range 0:255
+Param[2]
+       Threshold above which the chrominance median filter is enabled.
+       Default: 0, range 0:255
+Param[3]
+       Threshold below which the chrominance median filter is enabled.
+       Default: 255, range 0:255
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_SPATIAL_FILTER_TYPE
+Enum   161/0xA1
+Description
+       Assign spatial prefilter parameters
+Param[0]
+       Luminance filter
+           0=Off
+           1=1D Horizontal
+           2=1D Vertical
+           3=2D H/V Separable (default)
+           4=2D Symmetric non-separable
+Param[1]
+       Chrominance filter
+           0=Off
+           1=1D Horizontal (default)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_3_2_PULLDOWN
+Enum   177/0xB1
+Description
+       3:2 pulldown properties
+Param[0]
+       0=enabled
+       1=disabled
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_VBI_LINE
+Enum   183/0xB7
+Description
+       Selects VBI line number.
+Param[0]
+       Bits 0:4        line number
+       Bit  31         0=top_field, 1=bottom_field
+       Bits 0:31       all set specifies "all lines"
+Param[1]
+       VBI line information features: 0=disabled, 1=enabled
+Param[2]
+       Slicing: 0=None, 1=Closed Caption
+       Almost certainly not implemented. Set to 0.
+Param[3]
+       Luminance samples in this line.
+       Almost certainly not implemented. Set to 0.
+Param[4]
+       Chrominance samples in this line
+       Almost certainly not implemented. Set to 0.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_STREAM_TYPE
+Enum   185/0xB9
+Description
+       Assign stream type
+       Note: Transport stream is not working in recent firmwares.
+       And in older firmwares the timestamps in the TS seem to be
+       unreliable.
+Param[0]
+        0=Program stream
+        1=Transport stream
+        2=MPEG1 stream
+        3=PES A/V stream
+        5=PES Video stream
+        7=PES Audio stream
+       10=DVD stream
+       11=VCD stream
+       12=SVCD stream
+       13=DVD_S1 stream
+       14=DVD_S2 stream
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_OUTPUT_PORT
+Enum   187/0xBB
+Description
+       Assign stream output port. Normally 0 when the data is copied through
+       the PCI bus (DMA), and 1 when the data is streamed to another chip
+       (pvrusb and cx88-blackbird).
+Param[0]
+       0=Memory (default)
+       1=Streaming
+       2=Serial
+Param[1]
+       Unknown, but leaving this to 0 seems to work best. Indications are that
+       this might have to do with USB support, although passing anything but 0
+       onl breaks things.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_AUDIO_PROPERTIES
+Enum   189/0xBD
+Description
+       Set audio stream properties, may be called while encoding is in progress.
+       Note: all bitfields are consistent with ISO11172 documentation except
+       bits 2:3 which ISO docs define as:
+               '11' Layer I
+               '10' Layer II
+               '01' Layer III
+               '00' Undefined
+       This discrepancy may indicate a possible error in the documentation.
+       Testing indicated that only Layer II is actually working, and that
+       the minimum bitrate should be 192 kbps.
+Param[0]
+       Bitmask:
+          0:1  '00' 44.1Khz
+               '01' 48Khz
+               '10' 32Khz
+               '11' reserved
+
+          2:3  '01'=Layer I
+               '10'=Layer II
+
+          4:7  Bitrate:
+                    Index | Layer I     | Layer II
+                    ------+-------------+------------
+                   '0000' | free format | free format
+                   '0001' |  32 kbit/s  |  32 kbit/s
+                   '0010' |  64 kbit/s  |  48 kbit/s
+                   '0011' |  96 kbit/s  |  56 kbit/s
+                   '0100' | 128 kbit/s  |  64 kbit/s
+                   '0101' | 160 kbit/s  |  80 kbit/s
+                   '0110' | 192 kbit/s  |  96 kbit/s
+                   '0111' | 224 kbit/s  | 112 kbit/s
+                   '1000' | 256 kbit/s  | 128 kbit/s
+                   '1001' | 288 kbit/s  | 160 kbit/s
+                   '1010' | 320 kbit/s  | 192 kbit/s
+                   '1011' | 352 kbit/s  | 224 kbit/s
+                   '1100' | 384 kbit/s  | 256 kbit/s
+                   '1101' | 416 kbit/s  | 320 kbit/s
+                   '1110' | 448 kbit/s  | 384 kbit/s
+               Note: For Layer II, not all combinations of total bitrate
+               and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2
+
+          8:9  '00'=Stereo
+               '01'=JointStereo
+               '10'=Dual
+               '11'=Mono
+               Note: testing seems to indicate that Mono and possibly
+               JointStereo are not working (default to stereo).
+               Dual does work, though.
+
+         10:11 Mode Extension used in joint_stereo mode.
+               In Layer I and II they indicate which subbands are in
+               intensity_stereo. All other subbands are coded in stereo.
+                   '00' subbands 4-31 in intensity_stereo, bound==4
+                   '01' subbands 8-31 in intensity_stereo, bound==8
+                   '10' subbands 12-31 in intensity_stereo, bound==12
+                   '11' subbands 16-31 in intensity_stereo, bound==16
+
+         12:13 Emphasis:
+                   '00' None
+                   '01' 50/15uS
+                   '10' reserved
+                   '11' CCITT J.17
+
+         14    CRC:
+                   '0' off
+                   '1' on
+
+         15    Copyright:
+                   '0' off
+                   '1' on
+
+         16    Generation:
+                   '0' copy
+                   '1' original
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_HALT_FW
+Enum   195/0xC3
+Description
+       The firmware is halted and no further API calls are serviced until the
+       firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_VERSION
+Enum   196/0xC4
+Description
+       Returns the version of the encoder firmware.
+Result[0]
+       Version bitmask:
+           Bits  0:15 build
+           Bits 16:23 minor
+           Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_GOP_CLOSURE
+Enum   197/0xC5
+Description
+       Assigns the GOP open/close property.
+Param[0]
+       0=Open
+       1=Closed
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_SEQ_END
+Enum   198/0xC6
+Description
+       Obtains the sequence end code of the encoder's buffer. When a capture
+       is started a number of interrupts are still generated, the last of
+       which will have Result[0] set to 1 and Result[1] will contain the size
+       of the buffer.
+Result[0]
+       State of the transfer (1 if last buffer)
+Result[1]
+       If Result[0] is 1, this contains the size of the last buffer, undefined
+       otherwise.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_PGM_INDEX_INFO
+Enum   199/0xC7
+Description
+       Sets the Program Index Information.
+Param[0]
+       Picture Mask:
+           0=No index capture
+           1=I frames
+           3=I,P frames
+           7=I,P,B frames
+Param[1]
+       Elements requested (up to 400)
+Result[0]
+       Offset in SDF memory of the table.
+Result[1]
+       Number of allocated elements up to a maximum of Param[1]
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_VBI_CONFIG
+Enum   200/0xC8
+Description
+       Configure VBI settings
+Param[0]
+       Bitmap:
+           0    Mode '0' Sliced, '1' Raw
+           1:3  Insertion:
+                    '000' insert in extension & user data
+                    '001' insert in private packets
+                    '010' separate stream and user data
+                    '111' separate stream and private data
+           8:15 Stream ID (normally 0xBD)
+Param[1]
+       Frames per interrupt (max 8). Only valid in raw mode.
+Param[2]
+       Total raw VBI frames. Only valid in raw mode.
+Param[3]
+       Start codes
+Param[4]
+       Stop codes
+Param[5]
+       Lines per frame
+Param[6]
+       Byte per line
+Result[0]
+       Observed frames per interrupt in raw mode only. Rage 1 to Param[1]
+Result[1]
+       Observed number of frames in raw mode. Range 1 to Param[2]
+Result[2]
+       Memory offset to start or raw VBI data
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_DMA_BLOCK_SIZE
+Enum   201/0xC9
+Description
+       Set DMA transfer block size
+Param[0]
+       DMA transfer block size in bytes or frames. When unit is bytes,
+       supported block sizes are 2^7, 2^8 and 2^9 bytes.
+Param[1]
+       Unit: 0=bytes, 1=frames
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_PREV_DMA_INFO_MB_10
+Enum   202/0xCA
+Description
+       Returns information on the previous DMA transfer in conjunction with
+       bit 27 of the interrupt mask. Uses mailbox 10.
+Result[0]
+       Type of stream
+Result[1]
+       Address Offset
+Result[2]
+       Maximum size of transfer
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_PREV_DMA_INFO_MB_9
+Enum   203/0xCB
+Description
+       Returns information on the previous DMA transfer in conjunction with
+       bit 27 of the interrupt mask. Uses mailbox 9.
+Result[0]
+       Status bits:
+           Bit 0 set indicates transfer complete
+           Bit 2 set indicates transfer error
+           Bit 4 set indicates linked list error
+Result[1]
+       DMA type
+Result[2]
+       Presentation Time Stamp bits 0..31
+Result[3]
+       Presentation Time Stamp bit 32
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SCHED_DMA_TO_HOST
+Enum   204/0xCC
+Description
+       Setup DMA to host operation
+Param[0]
+       Memory address of link list
+Param[1]
+       Length of link list (wtf: what units ???)
+Param[2]
+       DMA type (0=MPEG)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_INITIALIZE_INPUT
+Enum   205/0xCD
+Description
+       Initializes the video input
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_FRAME_DROP_RATE
+Enum   208/0xD0
+Description
+       For each frame captured, skip specified number of frames.
+Param[0]
+       Number of frames to skip
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_PAUSE_ENCODER
+Enum   210/0xD2
+Description
+       During a pause condition, all frames are dropped instead of being encoded.
+Param[0]
+       0=Pause encoding
+       1=Continue encoding
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_REFRESH_INPUT
+Enum   211/0xD3
+Description
+       Refreshes the video input
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_COPYRIGHT
+Enum   212/0xD4
+Description
+       Sets stream copyright property
+Param[0]
+       0=Stream is not copyrighted
+       1=Stream is copyrighted
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_EVENT_NOTIFICATION
+Enum   213/0xD5
+Description
+       Setup firmware to notify the host about a particular event. Host must
+       unmask the interrupt bit.
+Param[0]
+       Event (0=refresh encoder input)
+Param[1]
+       Notification 0=disabled 1=enabled
+Param[2]
+       Interrupt bit
+Param[3]
+       Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_NUM_VSYNC_LINES
+Enum   214/0xD6
+Description
+       Depending on the analog video decoder used, this assigns the number
+       of lines for field 1 and 2.
+Param[0]
+       Field 1 number of lines:
+           0x00EF for SAA7114
+           0x00F0 for SAA7115
+           0x0105 for Micronas
+Param[1]
+       Field 2 number of lines:
+           0x00EF for SAA7114
+           0x00F0 for SAA7115
+           0x0106 for Micronas
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_PLACEHOLDER
+Enum   215/0xD7
+Description
+       Provides a mechanism of inserting custom user data in the MPEG stream.
+Param[0]
+       0=extension & user data
+       1=private packet with stream ID 0xBD
+Param[1]
+       Rate at which to insert data, in units of frames (for private packet)
+       or GOPs (for ext. & user data)
+Param[2]
+       Number of data DWORDs (below) to insert
+Param[3]
+       Custom data 0
+Param[4]
+       Custom data 1
+Param[5]
+       Custom data 2
+Param[6]
+       Custom data 3
+Param[7]
+       Custom data 4
+Param[8]
+       Custom data 5
+Param[9]
+       Custom data 6
+Param[10]
+       Custom data 7
+Param[11]
+       Custom data 8
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_MUTE_VIDEO
+Enum   217/0xD9
+Description
+       Video muting
+Param[0]
+       Bit usage:
+        0      '0'=video not muted
+               '1'=video muted, creates frames with the YUV color defined below
+        1:7    Unused
+        8:15   V chrominance information
+       16:23   U chrominance information
+       24:31   Y luminance information
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_MUTE_AUDIO
+Enum   218/0xDA
+Description
+       Audio muting
+Param[0]
+       0=audio not muted
+       1=audio muted (produces silent mpeg audio stream)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_UNKNOWN
+Enum   219/0xDB
+Description
+       Unknown API, it's used by Hauppauge though.
+Param[0]
+       0 This is the value Hauppauge uses, Unknown what it means.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_MISC
+Enum   220/0xDC
+Description
+       Miscellaneous actions. Not known for 100% what it does. It's really a
+       sort of ioctl call. The first parameter is a command number, the second
+       the value.
+Param[0]
+       Command number:
+        1=set initial SCR value when starting encoding.
+        2=set quality mode (apparently some test setting).
+        3=setup advanced VIM protection handling (supposedly only for the cx23416
+          for raw YUV).
+          Actually it looks like this should be 0 for saa7114/5 based card and 1
+          for cx25840 based cards.
+        4=generate artificial PTS timestamps
+        5=USB flush mode
+        6=something to do with the quantization matrix
+        7=set navigation pack insertion for DVD
+        8=enable scene change detection (seems to be a failure)
+        9=set history parameters of the video input module
+       10=set input field order of VIM
+       11=set quantization matrix
+       12=reset audio interface
+       13=set audio volume delay
+       14=set audio delay
+
+Param[1]
+       Command value.
diff --git a/Documentation/video4linux/cx2341x/fw-memory.txt b/Documentation/video4linux/cx2341x/fw-memory.txt
new file mode 100644 (file)
index 0000000..ef0aad3
--- /dev/null
@@ -0,0 +1,141 @@
+This document describes the cx2341x memory map and documents some of the register
+space.
+
+Warning! This information was figured out from searching through the memory and
+registers, this information may not be correct and is certainly not complete, and
+was not derived from anything more than searching through the memory space with
+commands like:
+
+       ivtvctl -O min=0x02000000,max=0x020000ff
+
+So take this as is, I'm always searching for more stuff, it's a large
+register space :-).
+
+Memory Map
+==========
+
+The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0
+(Base Address Register 0). The addresses here are offsets relative to the
+address held in BAR0.
+
+0x00000000-0x00ffffff Encoder memory space
+0x00000000-0x0003ffff Encode.rom
+      ???-???         MPEG buffer(s)
+      ???-???         Raw video capture buffer(s)
+      ???-???         Raw audio capture buffer(s)
+      ???-???         Display buffers (6 or 9)
+
+0x01000000-0x01ffffff Decoder memory space
+0x01000000-0x0103ffff Decode.rom
+      ???-???         MPEG buffers(s)
+0x0114b000-0x0115afff Audio.rom (deprecated?)
+
+0x02000000-0x0200ffff Register Space
+
+Registers
+=========
+
+The registers occupy the 64k space starting at the 0x02000000 offset from BAR0.
+All of these registers are 32 bits wide.
+
+DMA Registers 0x000-0xff:
+
+ 0x00 - Control:
+       0=reset/cancel, 1=read, 2=write, 4=stop
+ 0x04 - DMA status:
+       1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error
+ 0x08 - pci DMA pointer for read link list
+ 0x0c - pci DMA pointer for write link list
+ 0x10 - read/write DMA enable:
+       1=read enable, 2=write enable
+ 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes
+ 0x18 - ??
+ 0x1c - always 0x20 or 32, smaller values slow down DMA transactions
+ 0x20 - always value of 0x780a010a
+ 0x24-0x3c - usually just random values???
+ 0x40 - Interrupt status
+ 0x44 - Write a bit here and shows up in Interrupt status 0x40
+ 0x48 - Interrupt Mask
+ 0x4C - always value of 0xfffdffff,
+       if changed to 0xffffffff DMA write interrupts break.
+ 0x50 - always 0xffffffff
+ 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are
+       3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the
+       interrupt masks???).
+ 0x60-0x7C - random values
+ 0x80 - first write linked list reg, for Encoder Memory addr
+ 0x84 - first write linked list reg, for pci memory addr
+ 0x88 - first write linked list reg, for length of buffer in memory addr
+       (|0x80000000 or this for last link)
+ 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
+       from linked list addr in reg 0x0c, firmware must push through or
+       something.
+ 0xe0 - first (and only) read linked list reg, for pci memory addr
+ 0xe4 - first (and only) read linked list reg, for Decoder memory addr
+ 0xe8 - first (and only) read linked list reg, for length of buffer
+ 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000.
+
+Memory locations for Encoder Buffers 0x700-0x7ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for encoding, have to shift them by <<1 first.
+
+0x07F8: Encoder SDRAM refresh
+0x07FC: Encoder SDRAM pre-charge
+
+Memory locations for Decoder Buffers 0x800-0x8ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for decoding, have to shift them by <<1 first.
+
+0x08F8: Decoder SDRAM refresh
+0x08FC: Decoder SDRAM pre-charge
+
+Other memory locations:
+
+0x2800: Video Display Module control
+0x2D00: AO (audio output?) control
+0x2D24: Bytes Flushed
+0x7000: LSB I2C write clock bit (inverted)
+0x7004: LSB I2C write data bit (inverted)
+0x7008: LSB I2C read clock bit
+0x700c: LSB I2C read data bit
+0x9008: GPIO get input state
+0x900c: GPIO set output state
+0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output)
+0x9050: SPU control
+0x9054: Reset HW blocks
+0x9058: VPU control
+0xA018: Bit6: interrupt pending?
+0xA064: APU command
+
+
+Interrupt Status Register
+=========================
+
+The definition of the bits in the interrupt status register 0x0040, and the
+interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to
+execute.
+
+Bit
+31 Encoder Start Capture
+30 Encoder EOS
+29 Encoder VBI capture
+28 Encoder Video Input Module reset event
+27 Encoder DMA complete
+26
+25 Decoder copy protect detection event
+24 Decoder audio mode change detection event
+23
+22 Decoder data request
+21 Decoder I-Frame? done
+20 Decoder DMA complete
+19 Decoder VBI re-insertion
+18 Decoder DMA err (linked-list bad)
+
+Missing
+Encoder API call completed
+Decoder API call completed
+Encoder API post(?)
+Decoder API post(?)
+Decoder VTRACE event
diff --git a/Documentation/video4linux/cx2341x/fw-osd-api.txt b/Documentation/video4linux/cx2341x/fw-osd-api.txt
new file mode 100644 (file)
index 0000000..da98ae3
--- /dev/null
@@ -0,0 +1,342 @@
+OSD firmware API description
+============================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_FRAMEBUFFER
+Enum   65/0x41
+Description
+       Return base and length of contiguous OSD memory.
+Result[0]
+       OSD base address
+Result[1]
+       OSD length
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_PIXEL_FORMAT
+Enum   66/0x42
+Description
+       Query OSD format
+Result[0]
+       0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_PIXEL_FORMAT
+Enum   67/0x43
+Description
+       Assign pixel format
+Param[0]
+       0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_STATE
+Enum   68/0x44
+Description
+       Query OSD state
+Result[0]
+       Bit  0   0=off, 1=on
+       Bits 1:2 alpha control
+       Bits 3:5 pixel format
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_STATE
+Enum   69/0x45
+Description
+       OSD switch
+Param[0]
+       0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_OSD_COORDS
+Enum   70/0x46
+Description
+       Retrieve coordinates of OSD area blended with video
+Result[0]
+       OSD buffer address
+Result[1]
+       Stride in pixels
+Result[2]
+       Lines in OSD buffer
+Result[3]
+       Horizontal offset in buffer
+Result[4]
+       Vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_OSD_COORDS
+Enum   71/0x47
+Description
+       Assign the coordinates of the OSD area to blend with video
+Param[0]
+       buffer address
+Param[1]
+       buffer stride in pixels
+Param[2]
+       lines in buffer
+Param[3]
+       horizontal offset
+Param[4]
+       vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_SCREEN_COORDS
+Enum   72/0x48
+Description
+       Retrieve OSD screen area coordinates
+Result[0]
+       top left horizontal offset
+Result[1]
+       top left vertical offset
+Result[2]
+       bottom right hotizontal offset
+Result[3]
+       bottom right vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_SCREEN_COORDS
+Enum   73/0x49
+Description
+       Assign the coordinates of the screen area to blend with video
+Param[0]
+       top left horizontal offset
+Param[1]
+       top left vertical offset
+Param[2]
+       bottom left horizontal offset
+Param[3]
+       bottom left vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_GLOBAL_ALPHA
+Enum   74/0x4A
+Description
+       Retrieve OSD global alpha
+Result[0]
+       global alpha: 0=off, 1=on
+Result[1]
+       bits 0:7 global alpha
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_GLOBAL_ALPHA
+Enum   75/0x4B
+Description
+       Update global alpha
+Param[0]
+       global alpha: 0=off, 1=on
+Param[1]
+       global alpha (8 bits)
+Param[2]
+       local alpha: 0=on, 1=off
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_BLEND_COORDS
+Enum   78/0x4C
+Description
+       Move start of blending area within display buffer
+Param[0]
+       horizontal offset in buffer
+Param[1]
+       vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_FLICKER_STATE
+Enum   79/0x4F
+Description
+       Retrieve flicker reduction module state
+Result[0]
+       flicker state: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_FLICKER_STATE
+Enum   80/0x50
+Description
+       Set flicker reduction module state
+Param[0]
+       State: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_BLT_COPY
+Enum   82/0x52
+Description
+       BLT copy
+Param[0]
+'0000'  zero
+'0001' ~destination AND ~source
+'0010' ~destination AND  source
+'0011' ~destination
+'0100'  destination AND ~source
+'0101'                  ~source
+'0110'  destination XOR  source
+'0111' ~destination OR  ~source
+'1000' ~destination AND ~source
+'1001'  destination XNOR source
+'1010'                   source
+'1011' ~destination OR   source
+'1100'  destination
+'1101'  destination OR  ~source
+'1110'  destination OR   source
+'1111'  one
+
+Param[1]
+       Resulting alpha blending
+           '01' source_alpha
+           '10' destination_alpha
+           '11' source_alpha*destination_alpha+1
+                (zero if both source and destination alpha are zero)
+Param[2]
+       '00' output_pixel = source_pixel
+
+       '01' if source_alpha=0:
+                output_pixel = destination_pixel
+            if 256 > source_alpha > 1:
+                output_pixel = ((source_alpha + 1)*source_pixel +
+                                (255 - source_alpha)*destination_pixel)/256
+
+       '10' if destination_alpha=0:
+                output_pixel = source_pixel
+             if 255 > destination_alpha > 0:
+                output_pixel = ((255 - destination_alpha)*source_pixel +
+                                (destination_alpha + 1)*destination_pixel)/256
+
+       '11' if source_alpha=0:
+                source_temp = 0
+            if source_alpha=255:
+                source_temp = source_pixel*256
+            if 255 > source_alpha > 0:
+                source_temp = source_pixel*(source_alpha + 1)
+            if destination_alpha=0:
+                destination_temp = 0
+            if destination_alpha=255:
+                destination_temp = destination_pixel*256
+            if 255 > destination_alpha > 0:
+                destination_temp = destination_pixel*(destination_alpha + 1)
+            output_pixel = (source_temp + destination_temp)/256
+Param[3]
+       width
+Param[4]
+       height
+Param[5]
+       destination pixel mask
+Param[6]
+       destination rectangle start address
+Param[7]
+       destination stride in dwords
+Param[8]
+       source stride in dwords
+Param[9]
+       source rectangle start address
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_BLT_FILL
+Enum   83/0x53
+Description
+       BLT fill color
+Param[0]
+       Same as Param[0] on API 0x52
+Param[1]
+       Same as Param[1] on API 0x52
+Param[2]
+       Same as Param[2] on API 0x52
+Param[3]
+       width
+Param[4]
+       height
+Param[5]
+       destination pixel mask
+Param[6]
+       destination rectangle start address
+Param[7]
+       destination stride in dwords
+Param[8]
+       color fill value
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_BLT_TEXT
+Enum   84/0x54
+Description
+       BLT for 8 bit alpha text source
+Param[0]
+       Same as Param[0] on API 0x52
+Param[1]
+       Same as Param[1] on API 0x52
+Param[2]
+       Same as Param[2] on API 0x52
+Param[3]
+       width
+Param[4]
+       height
+Param[5]
+       destination pixel mask
+Param[6]
+       destination rectangle start address
+Param[7]
+       destination stride in dwords
+Param[8]
+       source stride in dwords
+Param[9]
+       source rectangle start address
+Param[10]
+       color fill value
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_FRAMEBUFFER_WINDOW
+Enum   86/0x56
+Description
+       Positions the main output window on the screen. The coordinates must be
+       such that the entire window fits on the screen.
+Param[0]
+       window width
+Param[1]
+       window height
+Param[2]
+       top left window corner horizontal offset
+Param[3]
+       top left window corner vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_CHROMA_KEY
+Enum   96/0x60
+Description
+       Chroma key switch and color
+Param[0]
+       state: 0=off, 1=on
+Param[1]
+       color
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_ALPHA_CONTENT_INDEX
+Enum   97/0x61
+Description
+       Retrieve alpha content index
+Result[0]
+       alpha content index, Range 0:15
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_ALPHA_CONTENT_INDEX
+Enum   98/0x62
+Description
+       Assign alpha content index
+Param[0]
+       alpha content index, range 0:15
diff --git a/Documentation/video4linux/cx2341x/fw-upload.txt b/Documentation/video4linux/cx2341x/fw-upload.txt
new file mode 100644 (file)
index 0000000..60c502c
--- /dev/null
@@ -0,0 +1,49 @@
+This document describes how to upload the cx2341x firmware to the card.
+
+How to find
+===========
+
+See the web pages of the various projects that uses this chip for information
+on how to obtain the firmware.
+
+The firmware stored in a Windows driver can be detected as follows:
+
+- Each firmware image is 256k bytes.
+- The 1st 32-bit word of the Encoder image is 0x0000da7
+- The 1st 32-bit word of the Decoder image is 0x00003a7
+- The 2nd 32-bit word of both images is 0xaa55bb66
+
+How to load
+===========
+
+- Issue the FWapi command to stop the encoder if it is running. Wait for the
+  command to complete.
+- Issue the FWapi command to stop the decoder if it is running. Wait for the
+  command to complete.
+- Issue the I2C command to the digitizer to stop emitting VSYNC events.
+- Issue the FWapi command to halt the encoder's firmware.
+- Sleep for 10ms.
+- Issue the FWapi command to halt the decoder's firmware.
+- Sleep for 10ms.
+- Write 0x00000000 to register 0x2800 to stop the Video Display Module.
+- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?).
+- Write 0x00000000 to register 0xA064 to ping? the APU.
+- Write 0xFFFFFFFE to register 0x9058 to stop the VPU.
+- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks.
+- Write 0x00000001 to register 0x9050 to stop the SPU.
+- Sleep for 10ms.
+- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us.
+- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us.
+- Sleep for 512ms. (600ms is recommended)
+- Transfer the encoder's firmware image to offset 0 in Encoder memory space.
+- Transfer the decoder's firmware image to offset 0 in Decoder memory space.
+- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to
+  re-enable the SPU.
+- Sleep for 1 second.
+- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058
+  to re-enable the VPU.
+- Sleep for 1 second.
+- Issue status API commands to both firmware images to verify.
+
diff --git a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
new file mode 100644 (file)
index 0000000..93fec32
--- /dev/null
@@ -0,0 +1,54 @@
+The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
+
+GPIO0  GPIO1
+  0        0    TV Audio
+  1        0    FM radio
+  0        1    Line-In
+  1        1    Mono tuner bypass or CD passthru (tuner specific)
+
+GPIO 16(i believe) is tied to the IR port (if present).
+
+------------------------------------------------------------------------------------
+
+>From the data sheet:
+ Register 24'h20004  PCI Interrupt Status
+  bit [18]  IR_SMP_INT Set when 32 input samples have been collected over
+  gpio[16] pin into GP_SAMPLE register.
+
+What's missing from the data sheet:
+
+Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
+compat remote)
+set register 0x35C050 to  0xa80a80
+
+enable sampling
+set register 0x35C054 to 0x5
+
+Of course, enable the IRQ bit 18 in the interrupt mask register .(and
+provide for a handler)
+
+GP_SAMPLE register is at 0x35C058
+
+Bits are then right shifted into the GP_SAMPLE register at the specified
+rate; you get an interrupt when a full DWORD is recieved.
+You need to recover the actual RC5 bits out of the (oversampled) IR sensor
+bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data)  An
+actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
+
+I'm pretty sure when no IR signal is present the receiver is always in a
+marking state(1); but stray light, etc can cause intermittent noise values
+as well.  Remember, this is a free running sample of the IR receiver state
+over time, so don't assume any sample starts at any particular place.
+
+http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
+This data sheet (google search) seems to have a lovely description of the
+RC5 basics
+
+http://users.pandora.be/nenya/electronics/rc5/  and more data
+
+http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
+and even a reference to how to decode a bi-phase data stream.
+
+http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
+still more info
+
diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c
new file mode 100644 (file)
index 0000000..079b628
--- /dev/null
@@ -0,0 +1,192 @@
+/* Simple Video4Linux image grabber. */
+/*
+ *     Video4Linux Driver Test/Example Framegrabbing Program
+ *
+ *     Compile with:
+ *             gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
+ *      Use as:
+ *              v4lgrab >image.ppm
+ *
+ *     Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
+ *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
+ *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#define FILE "/dev/video0"
+
+/* Stole this from tvset.c */
+
+#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
+{                                                                       \
+       switch (format)                                                 \
+       {                                                               \
+               case VIDEO_PALETTE_GREY:                                \
+                       switch (depth)                                  \
+                       {                                               \
+                               case 4:                                 \
+                               case 6:                                 \
+                               case 8:                                 \
+                                       (r) = (g) = (b) = (*buf++ << 8);\
+                                       break;                          \
+                                                                       \
+                               case 16:                                \
+                                       (r) = (g) = (b) =               \
+                                               *((unsigned short *) buf);      \
+                                       buf += 2;                       \
+                                       break;                          \
+                       }                                               \
+                       break;                                          \
+                                                                       \
+                                                                       \
+               case VIDEO_PALETTE_RGB565:                              \
+               {                                                       \
+                       unsigned short tmp = *(unsigned short *)buf;    \
+                       (r) = tmp&0xF800;                               \
+                       (g) = (tmp<<5)&0xFC00;                          \
+                       (b) = (tmp<<11)&0xF800;                         \
+                       buf += 2;                                       \
+               }                                                       \
+               break;                                                  \
+                                                                       \
+               case VIDEO_PALETTE_RGB555:                              \
+                       (r) = (buf[0]&0xF8)<<8;                         \
+                       (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
+                       (b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
+                       buf += 2;                                       \
+                       break;                                          \
+                                                                       \
+               case VIDEO_PALETTE_RGB24:                               \
+                       (r) = buf[0] << 8; (g) = buf[1] << 8;           \
+                       (b) = buf[2] << 8;                              \
+                       buf += 3;                                       \
+                       break;                                          \
+                                                                       \
+               default:                                                \
+                       fprintf(stderr,                                 \
+                               "Format %d not yet supported\n",        \
+                               format);                                \
+       }                                                               \
+}
+
+int get_brightness_adj(unsigned char *image, long size, int *brightness) {
+  long i, tot = 0;
+  for (i=0;i<size*3;i++)
+    tot += image[i];
+  *brightness = (128 - tot/(size*3))/3;
+  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
+}
+
+int main(int argc, char ** argv)
+{
+  int fd = open(FILE, O_RDONLY), f;
+  struct video_capability cap;
+  struct video_window win;
+  struct video_picture vpic;
+
+  unsigned char *buffer, *src;
+  int bpp = 24, r, g, b;
+  unsigned int i, src_depth;
+
+  if (fd < 0) {
+    perror(FILE);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
+    perror("VIDIOGCAP");
+    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
+    perror("VIDIOCGWIN");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
+    perror("VIDIOCGPICT");
+    close(fd);
+    exit(1);
+  }
+
+  if (cap.type & VID_TYPE_MONOCHROME) {
+    vpic.depth=8;
+    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.depth=6;
+      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+       vpic.depth=4;
+       if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+         fprintf(stderr, "Unable to find a supported capture format.\n");
+         close(fd);
+         exit(1);
+       }
+      }
+    }
+  } else {
+    vpic.depth=24;
+    vpic.palette=VIDEO_PALETTE_RGB24;
+
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.palette=VIDEO_PALETTE_RGB565;
+      vpic.depth=16;
+
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+       vpic.palette=VIDEO_PALETTE_RGB555;
+       vpic.depth=15;
+
+       if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+         fprintf(stderr, "Unable to find a supported capture format.\n");
+         return -1;
+       }
+      }
+    }
+  }
+
+  buffer = malloc(win.width * win.height * bpp);
+  if (!buffer) {
+    fprintf(stderr, "Out of memory.\n");
+    exit(1);
+  }
+
+  do {
+    int newbright;
+    read(fd, buffer, win.width * win.height * bpp);
+    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
+    if (f) {
+      vpic.brightness += (newbright << 8);
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+       perror("VIDIOSPICT");
+       break;
+      }
+    }
+  } while (f);
+
+  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
+
+  src = buffer;
+
+  for (i = 0; i < win.width * win.height; i++) {
+    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
+    fputc(r>>8, stdout);
+    fputc(g>>8, stdout);
+    fputc(b>>8, stdout);
+  }
+
+  close(fd);
+  return 0;
+}
diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490
new file mode 100644 (file)
index 0000000..44a4918
--- /dev/null
@@ -0,0 +1,18 @@
+Kernel driver ds2490
+====================
+
+Supported chips:
+  * Maxim DS2490 based
+
+Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+Description
+-----------
+
+The Maixm/Dallas Semiconductor DS2490 is a chip
+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.
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
new file mode 100644 (file)
index 0000000..3640c7c
--- /dev/null
@@ -0,0 +1,98 @@
+Userspace communication protocol over connector [1].
+
+
+Message types.
+=============
+
+There are three types of messages between w1 core and userspace:
+1. Events. They are generated each time new master or slave device found
+       either due to automatic or requested search.
+2. Userspace commands. Includes read/write and search/alarm search comamnds.
+3. Replies to userspace commands.
+
+
+Protocol.
+========
+
+[struct cn_msg] - connector header. It's length field is equal to size of the attached data.
+[struct w1_netlink_msg] - w1 netlink header.
+       __u8 type       - message type.
+                       W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events.
+                       W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events.
+                       W1_MASTER_CMD - userspace command for bus master device (search/alarm search).
+                       W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search
+                                       for bus master device where given slave device found).
+       __u8 res        - reserved
+       __u16 len       - size of attached to this header data.
+       union {
+               __u8 id;                         - slave unique device id
+               struct w1_mst {
+                       __u32           id;      - master's id.
+                       __u32           res;     - reserved
+               } mst;
+       } id;
+
+[strucrt w1_netlink_cmd] - command for gived master or slave device.
+       __u8 cmd        - command opcode.
+                       W1_CMD_READ     - read command.
+                       W1_CMD_WRITE    - write command.
+                       W1_CMD_SEARCH   - search command.
+                       W1_CMD_ALARM_SEARCH - alarm search command.
+       __u8 res        - reserved
+       __u16 len       - length of data for this command.
+                       For read command data must be allocated like for write command.
+       __u8 data[0]    - data for this command.
+
+
+Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages.
+
+For event messages there are no w1_netlink_cmd embedded structures, only connector header
+and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types)
+and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned
+to bus master device when it is added to w1 core.
+
+Currently replies to userspace commands are only generated for read command request.
+One reply is generated exactly for one w1_netlink_cmd read request.
+Replies are not combined when sent - i.e. typical reply messages looks like the following:
+[cn_msg][w1_netlink_msg][w1_netlink_cmd]
+cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
+w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len;
+w1_netlink_cmd.len = cmd->len;
+
+
+Operation steps in w1 core when new command is received.
+=======================================================
+
+When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request,
+according to w1_netlink_msg.type field.
+Then master or slave device is searched for.
+When found, master device (requested or those one on where slave device is found) is locked.
+If slave command is requested, then reset/select procedure is started to select given device.
+
+Then all requested in w1_netlink_msg operations are performed one by one.
+If command requires reply (like read command) it is sent on command completion.
+
+When all commands (w1_netlink_cmd) are processed muster device is unlocked
+and next w1_netlink_msg header processing started.
+
+
+Connector [1] specific documentation.
+====================================
+
+Each connector message includes two u32 fields as "address".
+w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header.
+Each message also includes sequence and acknowledge numbers.
+Sequence number for event messages is appropriate bus master sequence number increased with
+each event message sent "through" this master.
+Sequence number for userspace requests is set by userspace application.
+Sequence number for reply is the same as was in request, and
+acknowledge number is set to seq+1.
+
+
+Additional documantion, source code examples.
+============================================
+
+1. Documentation/connector
+2. http://tservice.net.ru/~s0mbre/archive/w1
+This archive includes userspace application w1d.c which
+uses read/write/search commands for all master/slave devices found on the bus.
diff --git a/Documentation/watchdog/src/watchdog-simple.c b/Documentation/watchdog/src/watchdog-simple.c
new file mode 100644 (file)
index 0000000..85cf17c
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdlib.h>
+#include <fcntl.h>
+
+int main(int argc, const char *argv[]) {
+       int fd = open("/dev/watchdog", O_WRONLY);
+       if (fd == -1) {
+               perror("watchdog");
+               exit(1);
+       }
+       while (1) {
+               write(fd, "\0", 1);
+               fsync(fd);
+               sleep(10);
+       }
+}
diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c
new file mode 100644 (file)
index 0000000..65f6c19
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Watchdog Driver Test Program
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+int fd;
+
+/*
+ * This function simply sends an IOCTL to the driver, which in turn ticks
+ * the PC Watchdog card to reset its internal timer so it doesn't trigger
+ * a computer reset.
+ */
+void keep_alive(void)
+{
+    int dummy;
+
+    ioctl(fd, WDIOC_KEEPALIVE, &dummy);
+}
+
+/*
+ * The main program.  Run the program with "-d" to disable the card,
+ * or "-e" to enable the card.
+ */
+int main(int argc, char *argv[])
+{
+    fd = open("/dev/watchdog", O_WRONLY);
+
+    if (fd == -1) {
+       fprintf(stderr, "Watchdog device not enabled.\n");
+       fflush(stderr);
+       exit(-1);
+    }
+
+    if (argc > 1) {
+       if (!strncasecmp(argv[1], "-d", 2)) {
+           ioctl(fd, WDIOC_SETOPTIONS, WDIOS_DISABLECARD);
+           fprintf(stderr, "Watchdog card disabled.\n");
+           fflush(stderr);
+           exit(0);
+       } else if (!strncasecmp(argv[1], "-e", 2)) {
+           ioctl(fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD);
+           fprintf(stderr, "Watchdog card enabled.\n");
+           fflush(stderr);
+           exit(0);
+       } else {
+           fprintf(stderr, "-d to disable, -e to enable.\n");
+           fprintf(stderr, "run by itself to tick the card.\n");
+           fflush(stderr);
+           exit(0);
+       }
+    } else {
+       fprintf(stderr, "Watchdog Ticking Away!\n");
+       fflush(stderr);
+    }
+
+    while(1) {
+       keep_alive();
+       sleep(1);
+    }
+}
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
new file mode 100644 (file)
index 0000000..bee7813
--- /dev/null
@@ -0,0 +1,1313 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Sun May  7 16:53:18 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+CONFIG_MACH_ATEB9200=y
+# CONFIG_MACH_KAFA is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=m
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+CONFIG_MTD_BLOCK_RO=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# 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_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# 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 is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# 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_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP2101=m
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_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
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX 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_AT91=y
+CONFIG_USB_AT91=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91RM9200=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="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=m
+# 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=m
+# 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=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig
new file mode 100644 (file)
index 0000000..8a075c8
--- /dev/null
@@ -0,0 +1,724 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc4
+# Tue Jun 14 12:05:24 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+CONFIG_MACH_CARMEVA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# 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_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+CONFIG_ARM_AT91_ETHER_RMII=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91RM9200=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
new file mode 100644 (file)
index 0000000..1db633e
--- /dev/null
@@ -0,0 +1,885 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Sun May  7 16:54:53 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+CONFIG_MACH_KAFA=y
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL 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
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+CONFIG_MTD_BLOCK_RO=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# 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_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=32
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig
new file mode 100644 (file)
index 0000000..45396e0
--- /dev/null
@@ -0,0 +1,781 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-rc2
+# Sun Aug 14 19:26:59 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+CONFIG_MACH_KB9200=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x10000000
+CONFIG_ZBOOT_ROM_BSS=0x20040000
+CONFIG_ZBOOT_ROM=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+CONFIG_DEBUG_DRIVER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+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=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 is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_AT91_SPI is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# 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_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+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 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
new file mode 100644 (file)
index 0000000..4b29e09
--- /dev/null
@@ -0,0 +1,981 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc1
+# Sun Jul  9 14:15:23 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED 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=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_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_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+CONFIG_MACH_LOGICPD_PXA270=y
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_MACH_TRIZEPS4 is not set
+CONFIG_PXA27x=y
+CONFIG_IWMMXT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
+# CONFIG_XIP_KERNEL 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
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET 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 is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL 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=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=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 is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=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
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=y
+CONFIG_SND_PXA2XX_AC97=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_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_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 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=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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS 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_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig
new file mode 100644 (file)
index 0000000..61115a7
--- /dev/null
@@ -0,0 +1,926 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc6
+# Tue Jun  6 15:26:53 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED 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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_NETX=y
+
+#
+# NetX Implementations
+#
+CONFIG_MACH_NXDKN=y
+CONFIG_MACH_NXDB500=y
+CONFIG_MACH_NXEB500HMI=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_VIC=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySMX0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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 is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_PLATRAM=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_NET_NETX=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_NETX=y
+CONFIG_SERIAL_NETX_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=m
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_NETX=m
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=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_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig
new file mode 100644 (file)
index 0000000..6a93e3a
--- /dev/null
@@ -0,0 +1,1076 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc1
+# Sun Jul  9 14:16:20 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=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_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+
+#
+# Atmel AT91 Processors
+#
+CONFIG_ARCH_AT91RM9200=y
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+
+#
+# AT91RM9200 Board Type
+#
+CONFIG_MACH_ONEARM=y
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_ATEB9200 is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_KAFA is not set
+
+#
+# AT91 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M"
+# CONFIG_XIP_KERNEL 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
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 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_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX 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_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AT91RM9200=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=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_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS 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 is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig
new file mode 100644 (file)
index 0000000..a4989f4
--- /dev/null
@@ -0,0 +1,1665 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Mon Sep 11 13:59:24 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=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_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_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_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PNX4008=y
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200"
+# CONFIG_XIP_KERNEL 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 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY 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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+# CONFIG_BRIDGE_EBT_ULOG is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=y
+CONFIG_ATM_CLIP=y
+# 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=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_NET_DIVERT is not set
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=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
+CONFIG_NET_SCH_INGRESS=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_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+# CONFIG_IEEE80211_CRYPT_WEP is not set
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# 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=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_DEBUG=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=y
+CONFIG_HDLC_RAW_ETH=y
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+CONFIG_HDLC_X25=y
+CONFIG_DLCI=m
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+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=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_SHAPER=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_TSDEV=m
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+# CONFIG_JOYSTICK_TWIDJOY is not set
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+CONFIG_TOUCHSCREEN_GUNZE=m
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+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 is not set
+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=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+# CONFIG_DVB_CX24123 is not set
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+# CONFIG_DVB_S5H1420 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+# CONFIG_DVB_ZL10353 is not set
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# 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
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6421 is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+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 is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+
+#
+# ALSA ARM devices
+#
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OSS_OBSOLETE_DRIVER is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_TI is not set
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+# CONFIG_USB_UEAGLEATM is not set
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX 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_AT91 is not set
+CONFIG_USB_GADGET_DUMMY_HCD=y
+CONFIG_USB_DUMMY_HCD=m
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# 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=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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_JFFS_FS=m
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+# CONFIG_NCPFS_SMALLDOS is not set
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+# CONFIG_ACORN_PARTITION_CUMANA is not set
+# CONFIG_ACORN_PARTITION_EESOX is not set
+CONFIG_ACORN_PARTITION_ICS=y
+# CONFIG_ACORN_PARTITION_ADFS is not set
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="cp437"
+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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS 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_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+CONFIG_SECURITY_ROOTPLUG=m
+CONFIG_SECURITY_SECLVL=m
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
new file mode 100644 (file)
index 0000000..a6698dc
--- /dev/null
@@ -0,0 +1,1579 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sat Jun 24 22:45:14 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_MACH_TRIZEPS4=y
+CONFIG_MACH_TRIZEPS4_CONXS=y
+# CONFIG_MACH_TRIZEPS4_ANY is not set
+CONFIG_PXA27x=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PXA2XX=m
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200n8"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_PXA_FICP is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIUSB is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+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=y
+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
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_TRIZEPS4 is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_SHARP_SL 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=y
+CONFIG_MTD_DOCPROBE=y
+CONFIG_MTD_DOCECC=y
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_H1900 is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_DISKONCHIP=y
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+# CONFIG_MTD_NAND_SHARPSL is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_PXA_CF=y
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_DM9000=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+CONFIG_AIRO_CS=m
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_CS=m
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=640
+CONFIG_INPUT_TSDEV_SCREEN_Y=480
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# 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_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SA1100_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_PXA=y
+CONFIG_I2C_PXA_SLAVE=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=m
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_PXA2XX=m
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+CONFIG_UCB1400=y
+CONFIG_UCB1400_TS=y
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_SEQUENCER_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=y
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=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
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=y
+CONFIG_SND_PXA2XX_AC97=y
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+CONFIG_USB_TOUCHSCREEN=m
+# CONFIG_USB_TOUCHSCREEN_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN_PANJIT is not set
+# CONFIG_USB_TOUCHSCREEN_3M is not set
+# CONFIG_USB_TOUCHSCREEN_ITM is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX 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_AT91 is not set
+CONFIG_USB_GADGET_DUMMY_HCD=y
+CONFIG_USB_DUMMY_HCD=y
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_PXA=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_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=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# 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_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_ACL_SUPPORT=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 is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION 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
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-15"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# 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=m
+# 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=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_DEC16=y
diff --git a/arch/arm/kernel/crunch-bits.S b/arch/arm/kernel/crunch-bits.S
new file mode 100644 (file)
index 0000000..a268867
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * arch/arm/kernel/crunch-bits.S
+ * Cirrus MaverickCrunch context switching and handling
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
+ * Copyright (c) 2003-2004, MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm/arch/ep93xx-regs.h>
+
+/*
+ * We can't use hex constants here due to a bug in gas.
+ */
+#define CRUNCH_MVDX0           0
+#define CRUNCH_MVDX1           8
+#define CRUNCH_MVDX2           16
+#define CRUNCH_MVDX3           24
+#define CRUNCH_MVDX4           32
+#define CRUNCH_MVDX5           40
+#define CRUNCH_MVDX6           48
+#define CRUNCH_MVDX7           56
+#define CRUNCH_MVDX8           64
+#define CRUNCH_MVDX9           72
+#define CRUNCH_MVDX10          80
+#define CRUNCH_MVDX11          88
+#define CRUNCH_MVDX12          96
+#define CRUNCH_MVDX13          104
+#define CRUNCH_MVDX14          112
+#define CRUNCH_MVDX15          120
+#define CRUNCH_MVAX0L          128
+#define CRUNCH_MVAX0M          132
+#define CRUNCH_MVAX0H          136
+#define CRUNCH_MVAX1L          140
+#define CRUNCH_MVAX1M          144
+#define CRUNCH_MVAX1H          148
+#define CRUNCH_MVAX2L          152
+#define CRUNCH_MVAX2M          156
+#define CRUNCH_MVAX2H          160
+#define CRUNCH_MVAX3L          164
+#define CRUNCH_MVAX3M          168
+#define CRUNCH_MVAX3H          172
+#define CRUNCH_DSPSC           176
+
+#define CRUNCH_SIZE            184
+
+       .text
+
+/*
+ * Lazy switching of crunch coprocessor context
+ *
+ * r10 = struct thread_info pointer
+ * r9  = ret_from_exception
+ * lr  = undefined instr exit
+ *
+ * called from prefetch exception handler with interrupts disabled
+ */
+ENTRY(crunch_task_enable)
+       ldr     r8, =(EP93XX_APB_VIRT_BASE + 0x00130000)        @ syscon addr
+
+       ldr     r1, [r8, #0x80]
+       tst     r1, #0x00800000                 @ access to crunch enabled?
+       movne   pc, lr                          @ if so no business here
+       mov     r3, #0xaa                       @ unlock syscon swlock
+       str     r3, [r8, #0xc0]
+       orr     r1, r1, #0x00800000             @ enable access to crunch
+       str     r1, [r8, #0x80]
+
+       ldr     r3, =crunch_owner
+       add     r0, r10, #TI_CRUNCH_STATE       @ get task crunch save area
+       ldr     r2, [sp, #60]                   @ current task pc value
+       ldr     r1, [r3]                        @ get current crunch owner
+       str     r0, [r3]                        @ this task now owns crunch
+       sub     r2, r2, #4                      @ adjust pc back
+       str     r2, [sp, #60]
+
+       ldr     r2, [r8, #0x80]
+       mov     r2, r2                          @ flush out enable (@@@)
+
+       teq     r1, #0                          @ test for last ownership
+       mov     lr, r9                          @ normal exit from exception
+       beq     crunch_load                     @ no owner, skip save
+
+crunch_save:
+       cfstr64         mvdx0, [r1, #CRUNCH_MVDX0]      @ save 64b registers
+       cfstr64         mvdx1, [r1, #CRUNCH_MVDX1]
+       cfstr64         mvdx2, [r1, #CRUNCH_MVDX2]
+       cfstr64         mvdx3, [r1, #CRUNCH_MVDX3]
+       cfstr64         mvdx4, [r1, #CRUNCH_MVDX4]
+       cfstr64         mvdx5, [r1, #CRUNCH_MVDX5]
+       cfstr64         mvdx6, [r1, #CRUNCH_MVDX6]
+       cfstr64         mvdx7, [r1, #CRUNCH_MVDX7]
+       cfstr64         mvdx8, [r1, #CRUNCH_MVDX8]
+       cfstr64         mvdx9, [r1, #CRUNCH_MVDX9]
+       cfstr64         mvdx10, [r1, #CRUNCH_MVDX10]
+       cfstr64         mvdx11, [r1, #CRUNCH_MVDX11]
+       cfstr64         mvdx12, [r1, #CRUNCH_MVDX12]
+       cfstr64         mvdx13, [r1, #CRUNCH_MVDX13]
+       cfstr64         mvdx14, [r1, #CRUNCH_MVDX14]
+       cfstr64         mvdx15, [r1, #CRUNCH_MVDX15]
+
+#ifdef __ARMEB__
+#error fix me for ARMEB
+#endif
+
+       cfmv32al        mvfx0, mvax0                    @ save 72b accumulators
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX0L]
+       cfmv32am        mvfx0, mvax0
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX0M]
+       cfmv32ah        mvfx0, mvax0
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX0H]
+       cfmv32al        mvfx0, mvax1
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX1L]
+       cfmv32am        mvfx0, mvax1
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX1M]
+       cfmv32ah        mvfx0, mvax1
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX1H]
+       cfmv32al        mvfx0, mvax2
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX2L]
+       cfmv32am        mvfx0, mvax2
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX2M]
+       cfmv32ah        mvfx0, mvax2
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX2H]
+       cfmv32al        mvfx0, mvax3
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX3L]
+       cfmv32am        mvfx0, mvax3
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX3M]
+       cfmv32ah        mvfx0, mvax3
+       cfstr32         mvfx0, [r1, #CRUNCH_MVAX3H]
+
+       cfmv32sc        mvdx0, dspsc                    @ save status word
+       cfstr64         mvdx0, [r1, #CRUNCH_DSPSC]
+
+       teq             r0, #0                          @ anything to load?
+       cfldr64eq       mvdx0, [r1, #CRUNCH_MVDX0]      @ mvdx0 was clobbered
+       moveq           pc, lr
+
+crunch_load:
+       cfldr64         mvdx0, [r0, #CRUNCH_DSPSC]      @ load status word
+       cfmvsc32        dspsc, mvdx0
+
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX0L]     @ load 72b accumulators
+       cfmval32        mvax0, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX0M]
+       cfmvam32        mvax0, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX0H]
+       cfmvah32        mvax0, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX1L]
+       cfmval32        mvax1, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX1M]
+       cfmvam32        mvax1, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX1H]
+       cfmvah32        mvax1, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX2L]
+       cfmval32        mvax2, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX2M]
+       cfmvam32        mvax2, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX2H]
+       cfmvah32        mvax2, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX3L]
+       cfmval32        mvax3, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX3M]
+       cfmvam32        mvax3, mvfx0
+       cfldr32         mvfx0, [r0, #CRUNCH_MVAX3H]
+       cfmvah32        mvax3, mvfx0
+
+       cfldr64         mvdx0, [r0, #CRUNCH_MVDX0]      @ load 64b registers
+       cfldr64         mvdx1, [r0, #CRUNCH_MVDX1]
+       cfldr64         mvdx2, [r0, #CRUNCH_MVDX2]
+       cfldr64         mvdx3, [r0, #CRUNCH_MVDX3]
+       cfldr64         mvdx4, [r0, #CRUNCH_MVDX4]
+       cfldr64         mvdx5, [r0, #CRUNCH_MVDX5]
+       cfldr64         mvdx6, [r0, #CRUNCH_MVDX6]
+       cfldr64         mvdx7, [r0, #CRUNCH_MVDX7]
+       cfldr64         mvdx8, [r0, #CRUNCH_MVDX8]
+       cfldr64         mvdx9, [r0, #CRUNCH_MVDX9]
+       cfldr64         mvdx10, [r0, #CRUNCH_MVDX10]
+       cfldr64         mvdx11, [r0, #CRUNCH_MVDX11]
+       cfldr64         mvdx12, [r0, #CRUNCH_MVDX12]
+       cfldr64         mvdx13, [r0, #CRUNCH_MVDX13]
+       cfldr64         mvdx14, [r0, #CRUNCH_MVDX14]
+       cfldr64         mvdx15, [r0, #CRUNCH_MVDX15]
+
+       mov     pc, lr
+
+/*
+ * Back up crunch regs to save area and disable access to them
+ * (mainly for gdb or sleep mode usage)
+ *
+ * r0 = struct thread_info pointer of target task or NULL for any
+ */
+ENTRY(crunch_task_disable)
+       stmfd   sp!, {r4, r5, lr}
+
+       mrs     ip, cpsr
+       orr     r2, ip, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, r2
+
+       ldr     r4, =(EP93XX_APB_VIRT_BASE + 0x00130000)        @ syscon addr
+
+       ldr     r3, =crunch_owner
+       add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
+       ldr     r1, [r3]                        @ get current crunch owner
+       teq     r1, #0                          @ any current owner?
+       beq     1f                              @ no: quit
+       teq     r0, #0                          @ any owner?
+       teqne   r1, r2                          @ or specified one?
+       bne     1f                              @ no: quit
+
+       ldr     r5, [r4, #0x80]                 @ enable access to crunch
+       mov     r2, #0xaa
+       str     r2, [r4, #0xc0]
+       orr     r5, r5, #0x00800000
+       str     r5, [r4, #0x80]
+
+       mov     r0, #0                          @ nothing to load
+       str     r0, [r3]                        @ no more current owner
+       ldr     r2, [r4, #0x80]                 @ flush out enable (@@@)
+       mov     r2, r2
+       bl      crunch_save
+
+       mov     r2, #0xaa                       @ disable access to crunch
+       str     r2, [r4, #0xc0]
+       bic     r5, r5, #0x00800000
+       str     r5, [r4, #0x80]
+       ldr     r5, [r4, #0x80]                 @ flush out enable (@@@)
+       mov     r5, r5
+
+1:     msr     cpsr_c, ip                      @ restore interrupt mode
+       ldmfd   sp!, {r4, r5, pc}
+
+/*
+ * Copy crunch state to given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to store crunch state
+ *
+ * this is called mainly in the creation of signal stack frames
+ */
+ENTRY(crunch_task_copy)
+       mrs     ip, cpsr
+       orr     r2, ip, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, r2
+
+       ldr     r3, =crunch_owner
+       add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
+       ldr     r3, [r3]                        @ get current crunch owner
+       teq     r2, r3                          @ does this task own it...
+       beq     1f
+
+       @ current crunch values are in the task save area
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     r0, r1
+       mov     r1, r2
+       mov     r2, #CRUNCH_SIZE
+       b       memcpy
+
+1:     @ this task owns crunch regs -- grab a copy from there
+       mov     r0, #0                          @ nothing to load
+       mov     r3, lr                          @ preserve return address
+       bl      crunch_save
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     pc, r3
+
+/*
+ * Restore crunch state from given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to get crunch state from
+ *
+ * this is used to restore crunch state when unwinding a signal stack frame
+ */
+ENTRY(crunch_task_restore)
+       mrs     ip, cpsr
+       orr     r2, ip, #PSR_I_BIT              @ disable interrupts
+       msr     cpsr_c, r2
+
+       ldr     r3, =crunch_owner
+       add     r2, r0, #TI_CRUNCH_STATE        @ get task crunch save area
+       ldr     r3, [r3]                        @ get current crunch owner
+       teq     r2, r3                          @ does this task own it...
+       beq     1f
+
+       @ this task doesn't own crunch regs -- use its save area
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     r0, r2
+       mov     r2, #CRUNCH_SIZE
+       b       memcpy
+
+1:     @ this task owns crunch regs -- load them directly
+       mov     r0, r1
+       mov     r1, #0                          @ nothing to save
+       mov     r3, lr                          @ preserve return address
+       bl      crunch_load
+       msr     cpsr_c, ip                      @ restore interrupt mode
+       mov     pc, r3
diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c
new file mode 100644 (file)
index 0000000..cec8378
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * arch/arm/kernel/crunch.c
+ * Cirrus MaverickCrunch context switching and handling
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/arch/ep93xx-regs.h>
+#include <asm/thread_notify.h>
+#include <asm/io.h>
+
+struct crunch_state *crunch_owner;
+
+void crunch_task_release(struct thread_info *thread)
+{
+       local_irq_disable();
+       if (crunch_owner == &thread->crunchstate)
+               crunch_owner = NULL;
+       local_irq_enable();
+}
+
+static int crunch_enabled(u32 devcfg)
+{
+       return !!(devcfg & EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE);
+}
+
+static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+       struct thread_info *thread = (struct thread_info *)t;
+       struct crunch_state *crunch_state;
+       u32 devcfg;
+
+       crunch_state = &thread->crunchstate;
+
+       switch (cmd) {
+       case THREAD_NOTIFY_FLUSH:
+               memset(crunch_state, 0, sizeof(*crunch_state));
+
+               /*
+                * FALLTHROUGH: Ensure we don't try to overwrite our newly
+                * initialised state information on the first fault.
+                */
+
+       case THREAD_NOTIFY_RELEASE:
+               crunch_task_release(thread);
+               break;
+
+       case THREAD_NOTIFY_SWITCH:
+               devcfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG);
+               if (crunch_enabled(devcfg) || crunch_owner == crunch_state) {
+                       devcfg ^= EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE;
+                       __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+                       __raw_writel(devcfg, EP93XX_SYSCON_DEVICE_CONFIG);
+               }
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block crunch_notifier_block = {
+       .notifier_call  = crunch_do,
+};
+
+static int __init crunch_init(void)
+{
+       thread_register_notifier(&crunch_notifier_block);
+
+       return 0;
+}
+
+late_initcall(crunch_init);
diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c
new file mode 100644 (file)
index 0000000..0d1a1db
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  linux/arch/arm/kernel/iwmmxt-notifier.c
+ *
+ *  XScale iWMMXt (Concan) context switching and handling
+ *
+ *  Initial code:
+ *  Copyright (c) 2003, Intel Corporation
+ *
+ *  Full lazy switching support, optimizations and more, by Nicolas Pitre
+ *  Copyright (c) 2003-2004, MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/thread_notify.h>
+#include <asm/io.h>
+
+static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+       struct thread_info *thread = t;
+
+       switch (cmd) {
+       case THREAD_NOTIFY_FLUSH:
+               /*
+                * flush_thread() zeroes thread->fpstate, so no need
+                * to do anything here.
+                *
+                * FALLTHROUGH: Ensure we don't try to overwrite our newly
+                * initialised state information on the first fault.
+                */
+
+       case THREAD_NOTIFY_RELEASE:
+               iwmmxt_task_release(thread);
+               break;
+
+       case THREAD_NOTIFY_SWITCH:
+               iwmmxt_task_switch(thread);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block iwmmxt_notifier_block = {
+       .notifier_call  = iwmmxt_do,
+};
+
+static int __init iwmmxt_init(void)
+{
+       thread_register_notifier(&iwmmxt_notifier_block);
+
+       return 0;
+}
+
+late_initcall(iwmmxt_init);
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c
new file mode 100644 (file)
index 0000000..0985b1c
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * arch/arm/mach-at91rm9200/at91rm9200.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include "generic.h"
+
+static struct map_desc at91rm9200_io_desc[] __initdata = {
+       {
+               .virtual        = AT91_VA_BASE_SYS,
+               .pfn            = __phys_to_pfn(AT91_BASE_SYS),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_SPI,
+               .pfn            = __phys_to_pfn(AT91_BASE_SPI),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_SSC2,
+               .pfn            = __phys_to_pfn(AT91_BASE_SSC2),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_SSC1,
+               .pfn            = __phys_to_pfn(AT91_BASE_SSC1),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_SSC0,
+               .pfn            = __phys_to_pfn(AT91_BASE_SSC0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_US3,
+               .pfn            = __phys_to_pfn(AT91_BASE_US3),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_US2,
+               .pfn            = __phys_to_pfn(AT91_BASE_US2),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_US1,
+               .pfn            = __phys_to_pfn(AT91_BASE_US1),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_US0,
+               .pfn            = __phys_to_pfn(AT91_BASE_US0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_EMAC,
+               .pfn            = __phys_to_pfn(AT91_BASE_EMAC),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_TWI,
+               .pfn            = __phys_to_pfn(AT91_BASE_TWI),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_MCI,
+               .pfn            = __phys_to_pfn(AT91_BASE_MCI),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_UDP,
+               .pfn            = __phys_to_pfn(AT91_BASE_UDP),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_TCB1,
+               .pfn            = __phys_to_pfn(AT91_BASE_TCB1),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_VA_BASE_TCB0,
+               .pfn            = __phys_to_pfn(AT91_BASE_TCB0),
+               .length         = SZ_16K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = AT91_SRAM_VIRT_BASE,
+               .pfn            = __phys_to_pfn(AT91_SRAM_BASE),
+               .length         = AT91_SRAM_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init at91rm9200_map_io(void)
+{
+       iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+}
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
+       7,      /* Advanced Interrupt Controller (FIQ) */
+       7,      /* System Peripherals */
+       0,      /* Parallel IO Controller A */
+       0,      /* Parallel IO Controller B */
+       0,      /* Parallel IO Controller C */
+       0,      /* Parallel IO Controller D */
+       6,      /* USART 0 */
+       6,      /* USART 1 */
+       6,      /* USART 2 */
+       6,      /* USART 3 */
+       0,      /* Multimedia Card Interface */
+       4,      /* USB Device Port */
+       0,      /* Two-Wire Interface */
+       6,      /* Serial Peripheral Interface */
+       5,      /* Serial Synchronous Controller 0 */
+       5,      /* Serial Synchronous Controller 1 */
+       5,      /* Serial Synchronous Controller 2 */
+       0,      /* Timer Counter 0 */
+       0,      /* Timer Counter 1 */
+       0,      /* Timer Counter 2 */
+       0,      /* Timer Counter 3 */
+       0,      /* Timer Counter 4 */
+       0,      /* Timer Counter 5 */
+       3,      /* USB Host port */
+       3,      /* Ethernet MAC */
+       0,      /* Advanced Interrupt Controller (IRQ0) */
+       0,      /* Advanced Interrupt Controller (IRQ1) */
+       0,      /* Advanced Interrupt Controller (IRQ2) */
+       0,      /* Advanced Interrupt Controller (IRQ3) */
+       0,      /* Advanced Interrupt Controller (IRQ4) */
+       0,      /* Advanced Interrupt Controller (IRQ5) */
+       0       /* Advanced Interrupt Controller (IRQ6) */
+};
+
+void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
+{
+       if (!priority)
+               priority = at91rm9200_default_irq_priority;
+
+       at91_aic_init(priority);
+}
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c
new file mode 100644 (file)
index 0000000..a92a862
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c
+ *
+ *  Copyright (C) 2003 SAN People
+ *  Copyright (C) 2003 ATMEL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+static unsigned long last_crtr;
+
+/*
+ * The ST_CRTR is updated asynchronously to the master clock.  It is therefore
+ *  necessary to read it twice (with the same value) to ensure accuracy.
+ */
+static inline unsigned long read_CRTR(void) {
+       unsigned long x1, x2;
+
+       do {
+               x1 = at91_sys_read(AT91_ST_CRTR);
+               x2 = at91_sys_read(AT91_ST_CRTR);
+       } while (x1 != x2);
+
+       return x1;
+}
+
+/*
+ * Returns number of microseconds since last timer interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ *  'tick' is usecs per jiffy (linux/timex.h).
+ */
+static unsigned long at91rm9200_gettimeoffset(void)
+{
+       unsigned long elapsed;
+
+       elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
+
+       return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */
+               write_seqlock(&xtime_lock);
+
+               while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
+                       timer_tick(regs);
+                       last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
+               }
+
+               write_sequnlock(&xtime_lock);
+
+               return IRQ_HANDLED;
+       }
+       else
+               return IRQ_NONE;                /* not handled */
+}
+
+static struct irqaction at91rm9200_timer_irq = {
+       .name           = "at91_tick",
+       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER,
+       .handler        = at91rm9200_timer_interrupt
+};
+
+void at91rm9200_timer_reset(void)
+{
+       last_crtr = 0;
+
+       /* Real time counter incremented every 30.51758 microseconds */
+       at91_sys_write(AT91_ST_RTMR, 1);
+
+       /* Set Period Interval timer */
+       at91_sys_write(AT91_ST_PIMR, LATCH);
+
+       /* Enable Period Interval Timer interrupt */
+       at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+}
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91rm9200_timer_init(void)
+{
+       /* Disable all timer interrupts */
+       at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
+       (void) at91_sys_read(AT91_ST_SR);       /* Clear any pending interrupts */
+
+       /* Make IRQs happen for the system timer */
+       setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+
+       /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
+       tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
+
+       /* Initialize and enable the timer interrupt */
+       at91rm9200_timer_reset();
+}
+
+#ifdef CONFIG_PM
+static void at91rm9200_timer_suspend(void)
+{
+       /* disable Period Interval Timer interrupt */
+       at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
+}
+#else
+#define at91rm9200_timer_suspend       NULL
+#endif
+
+struct sys_timer at91rm9200_timer = {
+       .init           = at91rm9200_timer_init,
+       .offset         = at91rm9200_gettimeoffset,
+       .suspend        = at91rm9200_timer_suspend,
+       .resume         = at91rm9200_timer_reset,
+};
+
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c
new file mode 100644 (file)
index 0000000..051a295
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-1arm.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init onearm_init_irq(void)
+{
+       /* Initialize AIC controller */
+       at91rm9200_init_irq(NULL);
+
+       /* Set up the GPIO interrupts */
+       at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata onearm_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 3,
+       .tty_map        = { 4, 0, 1, -1, -1 },          /* ttyS0, ..., ttyS4 */
+};
+
+static void __init onearm_map_io(void)
+{
+       at91rm9200_map_io();
+
+       /* Initialize clocks: 18.432 MHz crystal */
+       at91_clock_init(18432000);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&onearm_uart_config);
+}
+
+static struct at91_eth_data __initdata onearm_eth_data = {
+       .phy_irq_pin    = AT91_PIN_PC4,
+       .is_rmii        = 1,
+};
+
+static struct at91_usbh_data __initdata onearm_usbh_data = {
+       .ports          = 1,
+};
+
+static struct at91_udc_data __initdata onearm_udc_data = {
+       .vbus_pin       = AT91_PIN_PC2,
+       .pullup_pin     = AT91_PIN_PC3,
+};
+
+static void __init onearm_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* Ethernet */
+       at91_add_device_eth(&onearm_eth_data);
+       /* USB Host */
+       at91_add_device_usbh(&onearm_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&onearm_udc_data);
+}
+
+MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91rm9200_timer,
+       .map_io         = onearm_map_io,
+       .init_irq       = onearm_init_irq,
+       .init_machine   = onearm_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c
new file mode 100644 (file)
index 0000000..1efcd04
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-carmeva.c
+ *
+ *  Copyright (c) 2005 Peer Georgi
+ *                    Conitec Datasystems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init carmeva_init_irq(void)
+{
+       /* Initialize AIC controller */
+       at91rm9200_init_irq(NULL);
+
+       /* Set up the GPIO interrupts */
+       at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata carmeva_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 2,
+       .tty_map        = { 4, 1, -1, -1, -1 }          /* ttyS0, ..., ttyS4 */
+};
+
+static void __init carmeva_map_io(void)
+{
+       at91rm9200_map_io();
+
+       /* Initialize clocks: 20.000 MHz crystal */
+       at91_clock_init(20000000);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&carmeva_uart_config);
+}
+
+static struct at91_eth_data __initdata carmeva_eth_data = {
+       .phy_irq_pin    = AT91_PIN_PC4,
+       .is_rmii        = 1,
+};
+
+static struct at91_usbh_data __initdata carmeva_usbh_data = {
+       .ports          = 2,
+};
+
+static struct at91_udc_data __initdata carmeva_udc_data = {
+       .vbus_pin       = AT91_PIN_PD12,
+       .pullup_pin     = AT91_PIN_PD9,
+};
+
+/* FIXME: user dependend */
+// static struct at91_cf_data __initdata carmeva_cf_data = {
+//     .det_pin        = AT91_PIN_PB0,
+//     .rst_pin        = AT91_PIN_PC5,
+       // .irq_pin     = ... not connected
+       // .vcc_pin     = ... always powered
+// };
+
+static struct at91_mmc_data __initdata carmeva_mmc_data = {
+       .is_b           = 0,
+       .wire4          = 1,
+};
+
+static void __init carmeva_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* Ethernet */
+       at91_add_device_eth(&carmeva_eth_data);
+       /* USB Host */
+       at91_add_device_usbh(&carmeva_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&carmeva_udc_data);
+       /* I2C */
+       at91_add_device_i2c();
+       /* Compact Flash */
+//     at91_add_device_cf(&carmeva_cf_data);
+       /* SPI */
+//     at91_add_device_spi(NULL, 0);
+       /* MMC */
+       at91_add_device_mmc(&carmeva_mmc_data);
+}
+
+MACHINE_START(CARMEVA, "Carmeva")
+       /* Maintainer: Conitec Datasystems */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91rm9200_timer,
+       .map_io         = carmeva_map_io,
+       .init_irq       = carmeva_init_irq,
+       .init_machine   = carmeva_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c
new file mode 100644 (file)
index 0000000..4531f34
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-eb9200.c
+ *
+ *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
+ *  by Andrew Patrikalakis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init eb9200_init_irq(void)
+{
+       /* Initialize AIC controller */
+       at91rm9200_init_irq(NULL);
+
+       /* Set up the GPIO interrupts */
+       at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata eb9200_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 2,
+       .tty_map        = { 4, 1, -1, -1, -1 }          /* ttyS0, ..., ttyS4 */
+};
+
+static void __init eb9200_map_io(void)
+{
+       at91rm9200_map_io();
+
+       /* Initialize clocks: 18.432 MHz crystal */
+       at91_clock_init(18432000);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&eb9200_uart_config);
+}
+
+static struct at91_eth_data __initdata eb9200_eth_data = {
+       .phy_irq_pin    = AT91_PIN_PC4,
+       .is_rmii        = 1,
+};
+
+static struct at91_usbh_data __initdata eb9200_usbh_data = {
+       .ports          = 2,
+};
+
+static struct at91_udc_data __initdata eb9200_udc_data = {
+       .vbus_pin       = AT91_PIN_PD4,
+       .pullup_pin     = AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata eb9200_cf_data = {
+       .det_pin        = AT91_PIN_PB0,
+       .rst_pin        = AT91_PIN_PC5,
+       // .irq_pin     = ... not connected
+       // .vcc_pin     = ... always powered
+};
+
+static struct at91_mmc_data __initdata eb9200_mmc_data = {
+       .is_b           = 0,
+       .wire4          = 1,
+};
+
+static void __init eb9200_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* Ethernet */
+       at91_add_device_eth(&eb9200_eth_data);
+       /* USB Host */
+       at91_add_device_usbh(&eb9200_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&eb9200_udc_data);
+       /* I2C */
+       at91_add_device_i2c();
+       /* Compact Flash */
+       at91_add_device_cf(&eb9200_cf_data);
+       /* SPI */
+       at91_add_device_spi(NULL, 0);
+       /* MMC */
+       /* only supports 1 or 4 bit interface, not wired through to SPI */
+       at91_add_device_mmc(&eb9200_mmc_data);
+}
+
+MACHINE_START(ATEB9200, "Embest ATEB9200")
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91rm9200_timer,
+       .map_io         = eb9200_map_io,
+       .init_irq       = eb9200_init_irq,
+       .init_machine   = eb9200_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c
new file mode 100644 (file)
index 0000000..354b91c
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-kafa.c
+ *
+ *  Copyright (C) 2006 Sperry-Sun
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init kafa_init_irq(void)
+{
+       /* Initialize AIC controller */
+       at91rm9200_init_irq(NULL);
+
+       /* Set up the GPIO interrupts */
+       at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kafa_uart_config = {
+       .console_tty    = 0,                            /* ttyS0 */
+       .nr_tty         = 2,
+       .tty_map        = { 4, 0, -1, -1, -1 }          /* ttyS0, ..., ttyS4 */
+};
+
+static void __init kafa_map_io(void)
+{
+       at91rm9200_map_io();
+
+       /* Initialize clocks: 18.432 MHz crystal */
+       at91_clock_init(18432000);
+
+       /* Set up the LEDs */
+       at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&kafa_uart_config);
+}
+
+static struct at91_eth_data __initdata kafa_eth_data = {
+       .phy_irq_pin    = AT91_PIN_PC4,
+       .is_rmii        = 0,
+};
+
+static struct at91_usbh_data __initdata kafa_usbh_data = {
+       .ports          = 1,
+};
+
+static struct at91_udc_data __initdata kafa_udc_data = {
+       .vbus_pin       = AT91_PIN_PB6,
+       .pullup_pin     = AT91_PIN_PB7,
+};
+
+static void __init kafa_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* Ethernet */
+       at91_add_device_eth(&kafa_eth_data);
+       /* USB Host */
+       at91_add_device_usbh(&kafa_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&kafa_udc_data);
+       /* I2C */
+       at91_add_device_i2c();
+       /* SPI */
+       at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KAFA, "Sperry-Sun KAFA")
+       /* Maintainer: Sergei Sharonov */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91rm9200_timer,
+       .map_io         = kafa_map_io,
+       .init_irq       = kafa_init_irq,
+       .init_machine   = kafa_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c
new file mode 100644 (file)
index 0000000..1827db4
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-kb9202.c
+ *
+ *  Copyright (c) 2005 kb_admin
+ *                    KwikByte, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init kb9202_init_irq(void)
+{
+       /* Initialize AIC controller */
+       at91rm9200_init_irq(NULL);
+
+       /* Set up the GPIO interrupts */
+       at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kb9202_uart_config = {
+       .console_tty    = 0,                                    /* ttyS0 */
+       .nr_tty         = 3,
+       .tty_map        = { 4, 0, 1, -1, -1 }                   /* ttyS0, ..., ttyS4 */
+};
+
+static void __init kb9202_map_io(void)
+{
+       at91rm9200_map_io();
+
+       /* Initialize clocks: 10 MHz crystal */
+       at91_clock_init(10000000);
+
+       /* Set up the LEDs */
+       at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
+
+       /* Setup the serial ports and console */
+       at91_init_serial(&kb9202_uart_config);
+}
+
+static struct at91_eth_data __initdata kb9202_eth_data = {
+       .phy_irq_pin    = AT91_PIN_PB29,
+       .is_rmii        = 0,
+};
+
+static struct at91_usbh_data __initdata kb9202_usbh_data = {
+       .ports          = 1,
+};
+
+static struct at91_udc_data __initdata kb9202_udc_data = {
+       .vbus_pin       = AT91_PIN_PB24,
+       .pullup_pin     = AT91_PIN_PB22,
+};
+
+static struct at91_mmc_data __initdata kb9202_mmc_data = {
+       .det_pin        = AT91_PIN_PB2,
+       .is_b           = 0,
+       .wire4          = 1,
+};
+
+static void __init kb9202_board_init(void)
+{
+       /* Serial */
+       at91_add_device_serial();
+       /* Ethernet */
+       at91_add_device_eth(&kb9202_eth_data);
+       /* USB Host */
+       at91_add_device_usbh(&kb9202_usbh_data);
+       /* USB Device */
+       at91_add_device_udc(&kb9202_udc_data);
+       /* MMC */
+       at91_add_device_mmc(&kb9202_mmc_data);
+       /* I2C */
+       at91_add_device_i2c();
+       /* SPI */
+       at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KB9200, "KB920x")
+       /* Maintainer: KwikByte, Inc. */
+       .phys_io        = AT91_BASE_SYS,
+       .io_pg_offst    = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91rm9200_timer,
+       .map_io         = kb9202_map_io,
+       .init_irq       = kb9202_init_irq,
+       .init_machine   = kb9202_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c
new file mode 100644 (file)
index 0000000..47e5480
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * arch/arm/mach-at91rm9200/pm.c
+ * AT91 Power Management
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+static int at91_pm_valid_state(suspend_state_t state)
+{
+       switch (state) {
+               case PM_SUSPEND_ON:
+               case PM_SUSPEND_STANDBY:
+               case PM_SUSPEND_MEM:
+                       return 1;
+
+               default:
+                       return 0;
+       }
+}
+
+
+static suspend_state_t target_state;
+
+/*
+ * Called after processes are frozen, but before we shutdown devices.
+ */
+static int at91_pm_prepare(suspend_state_t state)
+{
+       target_state = state;
+       return 0;
+}
+
+/*
+ * Verify that all the clocks are correct before entering
+ * slow-clock mode.
+ */
+static int at91_pm_verify_clocks(void)
+{
+       unsigned long scsr;
+       int i;
+
+       scsr = at91_sys_read(AT91_PMC_SCSR);
+
+       /* USB must not be using PLLB */
+       if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) {
+               pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+               return 0;
+       }
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+       /* PCK0..PCK3 must be disabled, or configured to use clk32k */
+       for (i = 0; i < 4; i++) {
+               u32 css;
+
+               if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
+                       continue;
+
+               css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+               if (css != AT91_PMC_CSS_SLOW) {
+                       pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
+                       return 0;
+               }
+       }
+#endif
+
+       return 1;
+}
+
+/*
+ * Call this from platform driver suspend() to see how deeply to suspend.
+ * For example, some controllers (like OHCI) need one of the PLL clocks
+ * in order to act as a wakeup source, and those are not available when
+ * going into slow clock mode.
+ *
+ * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
+ * the very same problem (but not using at91 main_clk), and it'd be better
+ * to add one generic API rather than lots of platform-specific ones.
+ */
+int at91_suspend_entering_slow_clock(void)
+{
+       return (target_state == PM_SUSPEND_MEM);
+}
+EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+
+static void (*slow_clock)(void);
+
+
+
+static int at91_pm_enter(suspend_state_t state)
+{
+       at91_gpio_suspend();
+       at91_irq_suspend();
+
+       pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+                       /* remember all the always-wake irqs */
+                       (at91_sys_read(AT91_PMC_PCSR)
+                                       | (1 << AT91_ID_FIQ)
+                                       | (1 << AT91_ID_SYS)
+                                       | (1 << AT91_ID_IRQ0)
+                                       | (1 << AT91_ID_IRQ1)
+                                       | (1 << AT91_ID_IRQ2)
+                                       | (1 << AT91_ID_IRQ3)
+                                       | (1 << AT91_ID_IRQ4)
+                                       | (1 << AT91_ID_IRQ5)
+                                       | (1 << AT91_ID_IRQ6))
+                               & at91_sys_read(AT91_AIC_IMR),
+                       state);
+
+       switch (state) {
+               /*
+                * Suspend-to-RAM is like STANDBY plus slow clock mode, so
+                * drivers must suspend more deeply:  only the master clock
+                * controller may be using the main oscillator.
+                */
+               case PM_SUSPEND_MEM:
+                       /*
+                        * Ensure that clocks are in a valid state.
+                        */
+                       if (!at91_pm_verify_clocks())
+                               goto error;
+
+                       /*
+                        * Enter slow clock mode by switching over to clk32k and
+                        * turning off the main oscillator; reverse on wakeup.
+                        */
+                       if (slow_clock) {
+                               slow_clock();
+                               break;
+                       } else {
+                               /* DEVELOPMENT ONLY */
+                               pr_info("AT91: PM - no slow clock mode yet ...\n");
+                               /* FALLTHROUGH leaving master clock alone */
+                       }
+
+               /*
+                * STANDBY mode has *all* drivers suspended; ignores irqs not
+                * marked as 'wakeup' event sources; and reduces DRAM power.
+                * But otherwise it's identical to PM_SUSPEND_ON:  cpu idle, and
+                * nothing fancy done with main or cpu clocks.
+                */
+               case PM_SUSPEND_STANDBY:
+                       /*
+                        * NOTE: the Wait-for-Interrupt instruction needs to be
+                        * in icache so the SDRAM stays in self-refresh mode until
+                        * the wakeup IRQ occurs.
+                        */
+                       asm("b 1f; .align 5; 1:");
+                       asm("mcr p15, 0, r0, c7, c10, 4");      /* drain write buffer */
+                       at91_sys_write(AT91_SDRAMC_SRR, 1);     /* self-refresh mode */
+                       /* fall though to next state */
+
+               case PM_SUSPEND_ON:
+                       asm("mcr p15, 0, r0, c7, c0, 4");       /* wait for interrupt */
+                       break;
+
+               default:
+                       pr_debug("AT91: PM - bogus suspend state %d\n", state);
+                       goto error;
+       }
+
+       pr_debug("AT91: PM - wakeup %08x\n",
+                       at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+
+error:
+       target_state = PM_SUSPEND_ON;
+       at91_irq_resume();
+       at91_gpio_resume();
+       return 0;
+}
+
+
+static struct pm_ops at91_pm_ops ={
+       .pm_disk_mode   = 0,
+       .valid          = at91_pm_valid_state,
+       .prepare        = at91_pm_prepare,
+       .enter          = at91_pm_enter,
+};
+
+static int __init at91_pm_init(void)
+{
+       printk("AT91: Power Management\n");
+
+#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+       /* REVISIT allocations of SRAM should be dynamically managed.
+        * FIQ handlers and other components will want SRAM/TCM too...
+        */
+       slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+       memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
+#endif
+
+       /* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */
+       at91_sys_write(AT91_SDRAMC_LPR, 0);
+
+       pm_set_ops(&at91_pm_ops);
+
+       return 0;
+}
+arch_initcall(at91_pm_init);
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
new file mode 100644 (file)
index 0000000..08ad782
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * arch/arm/mach-ep93xx/clock.c
+ * Clock control for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <asm/div64.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+struct clk {
+       char            *name;
+       unsigned long   rate;
+       int             users;
+       u32             enable_reg;
+       u32             enable_mask;
+};
+
+static struct clk clk_pll1 = {
+       .name           = "pll1",
+};
+static struct clk clk_f = {
+       .name           = "fclk",
+};
+static struct clk clk_h = {
+       .name           = "hclk",
+};
+static struct clk clk_p = {
+       .name           = "pclk",
+};
+static struct clk clk_pll2 = {
+       .name           = "pll2",
+};
+static struct clk clk_usb_host = {
+       .name           = "usb_host",
+       .enable_reg     = EP93XX_SYSCON_CLOCK_CONTROL,
+       .enable_mask    = EP93XX_SYSCON_CLOCK_USH_EN,
+};
+
+
+static struct clk *clocks[] = {
+       &clk_pll1,
+       &clk_f,
+       &clk_h,
+       &clk_p,
+       &clk_pll2,
+       &clk_usb_host,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+               if (!strcmp(clocks[i]->name, id))
+                       return clocks[i];
+       }
+
+       return ERR_PTR(-ENOENT);
+}
+
+int clk_enable(struct clk *clk)
+{
+       if (!clk->users++ && clk->enable_reg) {
+               u32 value;
+
+               value = __raw_readl(clk->enable_reg);
+               __raw_writel(value | clk->enable_mask, clk->enable_reg);
+       }
+
+       return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+       if (!--clk->users && clk->enable_reg) {
+               u32 value;
+
+               value = __raw_readl(clk->enable_reg);
+               __raw_writel(value & ~clk->enable_mask, clk->enable_reg);
+       }
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+
+
+static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+static char pclk_divisors[] = { 1, 2, 4, 8 };
+
+/*
+ * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
+ */
+static unsigned long calc_pll_rate(u32 config_word)
+{
+       unsigned long long rate;
+       int i;
+
+       rate = 14745600;
+       rate *= ((config_word >> 11) & 0x1f) + 1;               /* X1FBD */
+       rate *= ((config_word >> 5) & 0x3f) + 1;                /* X2FBD */
+       do_div(rate, (config_word & 0x1f) + 1);                 /* X2IPD */
+       for (i = 0; i < ((config_word >> 16) & 3); i++)         /* PS */
+               rate >>= 1;
+
+       return (unsigned long)rate;
+}
+
+void ep93xx_clock_init(void)
+{
+       u32 value;
+
+       value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
+       if (!(value & 0x00800000)) {                    /* PLL1 bypassed?  */
+               clk_pll1.rate = 14745600;
+       } else {
+               clk_pll1.rate = calc_pll_rate(value);
+       }
+       clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
+       clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
+       clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+
+       value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
+       if (!(value & 0x00080000)) {                    /* PLL2 bypassed?  */
+               clk_pll2.rate = 14745600;
+       } else if (value & 0x00040000) {                /* PLL2 enabled?  */
+               clk_pll2.rate = calc_pll_rate(value);
+       } else {
+               clk_pll2.rate = 0;
+       }
+       clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
+
+       printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
+               clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
+       printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
+               clk_f.rate / 1000000, clk_h.rate / 1000000,
+               clk_p.rate / 1000000);
+}
diff --git a/arch/arm/mach-ep93xx/edb9302.c b/arch/arm/mach-ep93xx/edb9302.c
new file mode 100644 (file)
index 0000000..0315615
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-ep93xx/edb9302.c
+ * Cirrus Logic EDB9302 support.
+ *
+ * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9302_flash_data = {
+       .width          = 2,
+};
+
+static struct resource edb9302_flash_resource = {
+       .start          = 0x60000000,
+       .end            = 0x60ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device edb9302_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &edb9302_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &edb9302_flash_resource,
+};
+
+static void __init edb9302_init_machine(void)
+{
+       ep93xx_init_devices();
+       platform_device_register(&edb9302_flash);
+}
+
+MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
+       /* Maintainer: George Kashperko <george@chas.com.ua> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = edb9302_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9315.c b/arch/arm/mach-ep93xx/edb9315.c
new file mode 100644 (file)
index 0000000..249ca9e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-ep93xx/edb9315.c
+ * Cirrus Logic EDB9315 support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9315_flash_data = {
+       .width          = 4,
+};
+
+static struct resource edb9315_flash_resource = {
+       .start          = 0x60000000,
+       .end            = 0x61ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device edb9315_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &edb9315_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &edb9315_flash_resource,
+};
+
+static void __init edb9315_init_machine(void)
+{
+       ep93xx_init_devices();
+       platform_device_register(&edb9315_flash);
+}
+
+MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0x00000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = edb9315_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/edb9315a.c b/arch/arm/mach-ep93xx/edb9315a.c
new file mode 100644 (file)
index 0000000..e03407e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-ep93xx/edb9315a.c
+ * Cirrus Logic EDB9315A support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static struct physmap_flash_data edb9315a_flash_data = {
+       .width          = 2,
+};
+
+static struct resource edb9315a_flash_resource = {
+       .start          = 0x60000000,
+       .end            = 0x60ffffff,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device edb9315a_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &edb9315a_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &edb9315a_flash_resource,
+};
+
+static void __init edb9315a_init_machine(void)
+{
+       ep93xx_init_devices();
+       platform_device_register(&edb9315a_flash);
+}
+
+MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
+       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+       .phys_io        = EP93XX_APB_PHYS_BASE,
+       .io_pg_offst    = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+       .boot_params    = 0xc0000100,
+       .map_io         = ep93xx_map_io,
+       .init_irq       = ep93xx_init_irq,
+       .timer          = &ep93xx_timer,
+       .init_machine   = edb9315a_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
new file mode 100644 (file)
index 0000000..1992db4
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  arch/arm/mach-lh7a40x/clcd.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+
+//#include <linux/module.h>
+//#include <linux/time.h>
+//#include <asm/hardware.h>
+
+//#include <asm/mach/time.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#define HRTFTC_HRSETUP         __REG(HRTFTC_PHYS + 0x00)
+#define HRTFTC_HRCON           __REG(HRTFTC_PHYS + 0x04)
+#define HRTFTC_HRTIMING1       __REG(HRTFTC_PHYS + 0x08)
+#define HRTFTC_HRTIMING2       __REG(HRTFTC_PHYS + 0x0c)
+
+#define ALI_SETUP              __REG(ALI_PHYS + 0x00)
+#define ALI_CONTROL            __REG(ALI_PHYS + 0x04)
+#define ALI_TIMING1            __REG(ALI_PHYS + 0x08)
+#define ALI_TIMING2            __REG(ALI_PHYS + 0x0c)
+
+#include "lcd-panel.h"
+
+static void lh7a40x_clcd_disable (struct clcd_fb *fb)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL &= ~(1<<1);        /* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       GPIO_PCD  &= ~(1<<3);           /* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+       HRTFTC_HRSETUP &= ~(1<<13);     /* Disable HRTFT controller */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+       ALI_SETUP &= ~(1<<13);          /* Disable ALI */
+#endif
+}
+
+static void lh7a40x_clcd_enable (struct clcd_fb *fb)
+{
+       struct clcd_panel_extra* extra
+               = (struct clcd_panel_extra*) fb->board_data;
+
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL |= (1<<1);         /* Enable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       GPIO_PCDD &= ~(1<<3);           /* Enable LCD Vee */
+       GPIO_PCD  |=  (1<<3);
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+
+       if (extra) {
+               HRTFTC_HRSETUP
+                       = (1 << 13)
+                       | ((fb->fb.var.xres - 1) << 4)
+                       | 0xc
+                       | (extra->hrmode ? 1 : 0);
+               HRTFTC_HRCON
+                       = ((extra->clsen ? 1 : 0) << 1)
+                       | ((extra->spsen ? 1 : 0) << 0);
+               HRTFTC_HRTIMING1
+                       = (extra->pcdel << 8)
+                       | (extra->revdel << 4)
+                       | (extra->lpdel << 0);
+               HRTFTC_HRTIMING2
+                       = (extra->spldel << 9)
+                       | (extra->pc2del << 0);
+       }
+       else
+               HRTFTC_HRSETUP
+                       = (1 << 13)
+                       | 0xc;
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+
+       if (extra) {
+               ALI_SETUP
+                       = (1 << 13)
+                       | ((fb->fb.var.xres - 1) << 4)
+                       | 0xc
+                       | (extra->hrmode ? 1 : 0);
+               ALI_CONTROL
+                       = ((extra->clsen ? 1 : 0) << 1)
+                       | ((extra->spsen ? 1 : 0) << 0);
+               ALI_TIMING1
+                       = (extra->pcdel << 8)
+                       | (extra->revdel << 4)
+                       | (extra->lpdel << 0);
+               ALI_TIMING2
+                       = (extra->spldel << 9)
+                       | (extra->pc2del << 0);
+       }
+       else
+               ALI_SETUP
+                       = (1 << 13)
+                       | 0xc;
+#endif
+
+}
+
+#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
+
+static int lh7a40x_clcd_setup (struct clcd_fb *fb)
+{
+       dma_addr_t dma;
+       u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
+                            *(lcd_panel.bpp/8));
+
+       fb->panel = &lcd_panel;
+
+               /* Enforce the sync polarity defaults */
+       if (!(fb->panel->tim2 & TIM2_IHS))
+               fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
+       if (!(fb->panel->tim2 & TIM2_IVS))
+               fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+#if defined (HAS_LCD_PANEL_EXTRA)
+       fb->board_data = &lcd_panel_extra;
+#endif
+
+       fb->fb.screen_base
+               = dma_alloc_writecombine (&fb->dev->dev, len,
+                                         &dma, GFP_KERNEL);
+       printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
+               fb->fb.screen_base, (void*) dma, len,
+               (void*) io_p2v (CLCDC_PHYS));
+       printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
+
+       if (!fb->fb.screen_base) {
+               printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+               return -ENOMEM;
+       }
+
+#if defined (USE_RGB555)
+       fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
+#endif
+
+       fb->fb.fix.smem_start = dma;
+       fb->fb.fix.smem_len = len;
+
+               /* Drive PE4 high to prevent CPLD crash */
+       GPIO_PEDD |= (1<<4);
+       GPIO_PED  |= (1<<4);
+
+       GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
+
+//     fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
+//     fb->fb.fbops->fb_set_par (&fb->fb);
+
+       return 0;
+}
+
+static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       return dma_mmap_writecombine(&fb->dev->dev, vma,
+                                    fb->fb.screen_base,
+                                    fb->fb.fix.smem_start,
+                                    fb->fb.fix.smem_len);
+}
+
+static void lh7a40x_clcd_remove (struct clcd_fb *fb)
+{
+       dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
+                              fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_platform_data = {
+       .name           = "lh7a40x FB",
+       .check          = clcdfb_check,
+       .decode         = clcdfb_decode,
+       .enable         = lh7a40x_clcd_enable,
+       .setup          = lh7a40x_clcd_setup,
+       .mmap           = lh7a40x_clcd_mmap,
+       .remove         = lh7a40x_clcd_remove,
+       .disable        = lh7a40x_clcd_disable,
+};
+
+#define IRQ_CLCDC (IRQ_LCDINTR)
+
+#define AMBA_DEVICE(name,busid,base,plat,pid)                  \
+static struct amba_device name##_device = {                    \
+       .dev = {                                                \
+               .coherent_dma_mask = ~0,                        \
+               .bus_id = busid,                                \
+               .platform_data = plat,                          \
+               },                                              \
+       .res = {                                                \
+               .start  = base##_PHYS,                          \
+               .end    = (base##_PHYS) + (4*1024) - 1,         \
+               .flags  = IORESOURCE_MEM,                       \
+               },                                              \
+       .dma_mask       = ~0,                                   \
+       .irq            = { IRQ_##base, },                      \
+       /* .dma         = base##_DMA,*/                         \
+       .periphid = pid,                                        \
+}
+
+AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
+
+static struct amba_device *amba_devs[] __initdata = {
+       &clcd_device,
+};
+
+void __init lh7a40x_clcd_init (void)
+{
+       int i;
+       int result;
+       printk ("CLCD: registering amba devices\n");
+       for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+               struct amba_device *d = amba_devs[i];
+               result = amba_device_register(d, &iomem_resource);
+               printk ("  %d -> %d\n", i ,result);
+       }
+}
diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c
new file mode 100644 (file)
index 0000000..7530a95
--- /dev/null
@@ -0,0 +1,198 @@
+/* arch/arm/mach-lh7a40x/clocks.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can 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/cpufreq.h>
+#include <asm/hardware.h>
+#include <asm/arch/clocks.h>
+#include <linux/err.h>
+
+struct module;
+struct icst525_params;
+
+struct clk {
+       struct list_head node;
+       unsigned long rate;
+       struct module *owner;
+       const char *name;
+//     void *data;
+//     const struct icst525_params *params;
+//     void (*setvco)(struct clk *, struct icst525_vco vco);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+/* ----- */
+
+#define MAINDIV1(c)    (((c) >>  7) & 0x0f)
+#define MAINDIV2(c)    (((c) >> 11) & 0x1f)
+#define PS(c)          (((c) >> 18) & 0x03)
+#define PREDIV(c)      (((c) >>  2) & 0x1f)
+#define HCLKDIV(c)     (((c) >>  0) & 0x02)
+#define PCLKDIV(c)     (((c) >> 16) & 0x03)
+
+unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
+{
+       return fclkfreq_get ()/1000;
+}
+EXPORT_SYMBOL(cpufreq_get);
+
+unsigned int fclkfreq_get (void)
+{
+       unsigned int clkset = CSC_CLKSET;
+       unsigned int gclk
+               = XTAL_IN
+               / (1 << PS(clkset))
+               * (MAINDIV1(clkset) + 2)
+               / (PREDIV(clkset)   + 2)
+               * (MAINDIV2(clkset) + 2)
+               ;
+       return gclk;
+}
+
+unsigned int hclkfreq_get (void)
+{
+       unsigned int clkset = CSC_CLKSET;
+       unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
+
+       return hclk;
+}
+
+unsigned int pclkfreq_get (void)
+{
+       unsigned int clkset = CSC_CLKSET;
+       int pclkdiv = PCLKDIV(clkset);
+       unsigned int pclk;
+       if (pclkdiv == 0x3)
+               pclkdiv = 0x2;
+       pclk = hclkfreq_get () / (1 << pclkdiv);
+
+       return pclk;
+}
+
+/* ----- */
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get (struct device *dev, const char *id)
+{
+       struct clk *p;
+       struct clk *clk = ERR_PTR(-ENOENT);
+
+       down (&clocks_sem);
+       list_for_each_entry (p, &clocks, node) {
+               if (strcmp (id, p->name) == 0
+                   && try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+       up (&clocks_sem);
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put (struct clk *clk)
+{
+       module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable (struct clk *clk)
+{
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use (struct clk *clk)
+{
+       return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate (struct clk *clk)
+{
+       return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate (struct clk *clk, unsigned long rate)
+{
+       return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate (struct clk *clk, unsigned long rate)
+{
+       int ret = -EIO;
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+#if 0
+/*
+ * These are fixed clocks.
+ */
+static struct clk kmi_clk = {
+       .name   = "KMIREFCLK",
+       .rate   = 24000000,
+};
+
+static struct clk uart_clk = {
+       .name   = "UARTCLK",
+       .rate   = 24000000,
+};
+
+static struct clk mmci_clk = {
+       .name   = "MCLK",
+       .rate   = 33000000,
+};
+#endif
+
+static struct clk clcd_clk = {
+       .name   = "CLCDCLK",
+       .rate   = 0,
+};
+
+int clk_register (struct clk *clk)
+{
+       down (&clocks_sem);
+       list_add (&clk->node, &clocks);
+       up (&clocks_sem);
+       return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister (struct clk *clk)
+{
+       down (&clocks_sem);
+       list_del (&clk->node);
+       up (&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init (void)
+{
+       clk_register(&clcd_clk);
+       return 0;
+}
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
new file mode 100644 (file)
index 0000000..4fb2efc
--- /dev/null
@@ -0,0 +1,346 @@
+/* lcd-panel.h
+     $Id$
+
+   written by Marc Singer
+   18 Jul 2005
+
+   Copyright (C) 2005 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   Only one panel may be defined at a time.
+
+   The pixel clock is calculated to be no greater than the target.
+
+   Each timing value is accompanied by a specification comment.
+
+     UNITS/MIN/TYP/MAX
+
+   Most of the units will be in clocks.
+
+   USE_RGB555
+
+     Define this macro to configure the AMBA LCD controller to use an
+     RGB555 encoding for the pels instead of the normal RGB565.
+
+   LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
+
+     These boards are best approximated by 555 for all panels.  Some
+     can use an extra low-order bit of blue in bit 16 of the color
+     value, but we don't have a way to communicate this non-linear
+     mapping to the kernel.
+
+*/
+
+#if !defined (__LCD_PANEL_H__)
+#    define   __LCD_PANEL_H__
+
+#if defined (MACH_LPD79520)\
+ || defined (MACH_LPD79524)\
+ || defined (MACH_LPD7A400)\
+ || defined (MACH_LPD7A404)
+# define USE_RGB555
+#endif
+
+struct clcd_panel_extra {
+       unsigned int hrmode;
+       unsigned int clsen;
+       unsigned int spsen;
+       unsigned int pcdel;
+       unsigned int revdel;
+       unsigned int lpdel;
+       unsigned int spldel;
+       unsigned int pc2del;
+};
+
+#define NS_TO_CLOCK(ns,c)      ((((ns)*((c)/1000) + (1000000 - 1))/1000000))
+#define CLOCK_TO_DIV(e,c)      (((c) + (e) - 1)/(e))
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
+
+       /* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
+       /* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
+
+#define PIX_CLOCK_TARGET       (6800000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "3.5in QVGA (LQ035Q7DB02)",
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 16,
+               .right_margin   = 21,
+               .upper_margin   = 8,                    // line/8/8/8
+               .lower_margin   = 5,
+               .hsync_len      = 61,
+               .vsync_len      = NS_TO_CLOCK (60, PIX_CLOCK),
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#define HAS_LCD_PANEL_EXTRA
+
+static struct clcd_panel_extra lcd_panel_extra = {
+       .hrmode = 1,
+       .clsen = 1,
+       .spsen = 1,
+       .pcdel = 8,
+       .revdel = 7,
+       .lpdel = 13,
+       .spldel = 77,
+       .pc2del = 208,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
+
+       /* Logic Product Development LCD 5.7" QVGA -10 */
+       /* Sharp PN LQ057Q3DC02 */
+       /* QVGA mode, V/Q=LOW */
+
+/* From Sharp on 2006.1.3.  I believe some of the values are incorrect
+ * based on the datasheet.
+
+    Timing0    TIMING1         TIMING2         CONTROL
+    0x140A0C4C 0x080504EF      0x013F380D      0x00000829
+    HBP= 20    VBP=  8         BCD=  0
+    HFP= 10    VFP=  5         CPL=319
+    HSW= 12    VSW=  1         IOE=  0
+    PPL= 19    LPP=239         IPC=  1
+                               IHS=  1
+                               IVS=  1
+                               ACB=  0
+                               CSEL= 0
+                               PCD= 13
+
+ */
+
+/* The full horozontal cycle (Th) is clock/360/400/450. */
+/* The full vertical   cycle (Tv) is line/251/262/280. */
+
+#define PIX_CLOCK_TARGET       (6300000) /* -/6.3/7 MHz */
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "5.7in QVGA (LQ057Q3DC02)",
+               .xres           = 320,
+               .yres           = 240,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 11,
+               .right_margin   = 400-11-320-2,
+               .upper_margin   = 7,                    // line/7/7/7
+               .lower_margin   = 262-7-240-2,
+               .hsync_len      = 2,                    // clk/2/96/200
+               .vsync_len      = 2,                    // line/2/-/34
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
+
+       /* Logic Product Development LCD 6.4" VGA -10 */
+       /* Sharp PN LQ64D343 */
+
+/* The full horozontal cycle (Th) is clock/750/800/900. */
+/* The full vertical   cycle (Tv) is line/515/525/560. */
+
+#define PIX_CLOCK_TARGET       (28330000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "6.4in QVGA (LQ64D343)",
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 32,
+               .right_margin   = 800-32-640-96,
+               .upper_margin   = 32,                   // line/34/34/34
+               .lower_margin   = 540-32-480-2,
+               .hsync_len      = 96,                   // clk/2/96/200
+               .vsync_len      = 2,                    // line/2/-/34
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
+
+       /* Logic Product Development LCD 10.4" VGA -10 */
+       /* Sharp PN LQ10D368 */
+
+#define PIX_CLOCK_TARGET       (28330000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "10.4in VGA (LQ10D368)",
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 21,
+               .right_margin   = 15,
+               .upper_margin   = 34,
+               .lower_margin   = 5,
+               .hsync_len      = 96,
+               .vsync_len      = 16,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
+
+       /* Logic Product Development LCD 12.1" SVGA -10 */
+       /* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
+
+/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
+ * target clock frequency range of 35MHz to 42MHz. */
+
+/* If the target pixel clock is substantially lower than the panel
+ * spec, this is done to prevent the LCD display from glitching when
+ * the CPU is under load.  A pixel clock higher than 25MHz
+ * (empirically determined) will compete with the CPU for bus cycles
+ * for the Ethernet chip.  However, even a pixel clock of 10MHz
+ * competes with Compact Flash interface during some operations
+ * (fdisk, e2fsck).  And, at that speed the display may have a visible
+ * flicker. */
+
+/* The full horozontal cycle (Th) is clock/832/1056/1395. */
+
+#define PIX_CLOCK_TARGET       (20000000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "12.1in SVGA (LQ121S1DG41)",
+               .xres           = 800,
+               .yres           = 600,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 89,           // ns/5/-/(1/PIX_CLOCK)-10
+               .right_margin   = 1056-800-89-128,
+               .upper_margin   = 23,           // line/23/23/23
+               .lower_margin   = 44,
+               .hsync_len      = 128,          // clk/2/128/200
+               .vsync_len      = 4,            // line/2/4/6
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_HITACHI
+
+       /* Hitachi*/
+       /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET       (49000000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "Hitachi 800x480",
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 88,
+               .right_margin   = 40,
+               .upper_margin   = 32,
+               .lower_margin   = 11,
+               .hsync_len      = 128,
+               .vsync_len      = 2,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IPC | TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+
+#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
+
+       /* AU Optotronics  A070VW01 7.0 Wide Screen color Display*/
+       /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET       (10000000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "7.0in Wide (A070VW01)",
+               .xres           = 480,
+               .yres           = 234,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 30,
+               .right_margin   = 25,
+               .upper_margin   = 14,
+               .lower_margin   = 12,
+               .hsync_len      = 100,
+               .vsync_len      = 1,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IPC | TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#undef NS_TO_CLOCK
+#undef CLOCK_TO_DIV
+
+#endif  /* __LCD_PANEL_H__ */
diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c
new file mode 100644 (file)
index 0000000..a108301
--- /dev/null
@@ -0,0 +1,343 @@
+/* arch/arm/mach-lh7a40x/ssp-cpld.c
+ *
+ *  Copyright (C) 2004,2005 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ * SSP/SPI driver for the CardEngine CPLD.
+ *
+ */
+
+/* NOTES
+   -----
+
+   o *** This driver is cribbed from the 7952x implementation.
+        Some comments may not apply.
+
+   o This driver contains sufficient logic to control either the
+     serial EEPROMs or the audio codec.  It is included in the kernel
+     to support the codec.  The EEPROMs are really the responsibility
+     of the boot loader and should probably be left alone.
+
+   o The code must be augmented to cope with multiple, simultaneous
+     clients.
+     o The audio codec writes to the codec chip whenever playback
+       starts.
+     o The touchscreen driver writes to the ads chip every time it
+       samples.
+     o The audio codec must write 16 bits, but the touch chip writes
+       are 8 bits long.
+     o We need to be able to keep these configurations separate while
+       simultaneously active.
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+//#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+//#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/ssp.h>
+
+//#define TALK
+
+#if defined (TALK)
+#define PRINTK(f...)           printk (f)
+#else
+#define PRINTK(f...)           do {} while (0)
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+# define CPLD_SPID             __REGP16(CPLD06_VIRT) /* SPI data */
+# define CPLD_SPIC             __REGP16(CPLD08_VIRT) /* SPI control */
+# define CPLD_SPIC_CS_CODEC    (1<<0)
+# define CPLD_SPIC_CS_TOUCH    (1<<1)
+# define CPLD_SPIC_WRITE       (0<<2)
+# define CPLD_SPIC_READ                (1<<2)
+# define CPLD_SPIC_DONE                (1<<3) /* r/o */
+# define CPLD_SPIC_LOAD                (1<<4)
+# define CPLD_SPIC_START       (1<<4)
+# define CPLD_SPIC_LOADED      (1<<5) /* r/o */
+#endif
+
+#define CPLD_SPI               __REGP16(CPLD0A_VIRT) /* SPI operation */
+#define CPLD_SPI_CS_EEPROM     (1<<3)
+#define CPLD_SPI_SCLK          (1<<2)
+#define CPLD_SPI_TX_SHIFT      (1)
+#define CPLD_SPI_TX            (1<<CPLD_SPI_TX_SHIFT)
+#define CPLD_SPI_RX_SHIFT      (0)
+#define CPLD_SPI_RX            (1<<CPLD_SPI_RX_SHIFT)
+
+/* *** FIXME: these timing values are substantially larger than the
+   *** chip requires. We may implement an nsleep () function. */
+#define T_SKH  1               /* Clock time high (us) */
+#define T_SKL  1               /* Clock time low (us) */
+#define T_CS   1               /* Minimum chip select low time (us)  */
+#define T_CSS  1               /* Minimum chip select setup time (us)  */
+#define T_DIS  1               /* Data setup time (us) */
+
+        /* EEPROM SPI bits */
+#define P_START                (1<<9)
+#define P_WRITE                (1<<7)
+#define P_READ         (2<<7)
+#define P_ERASE                (3<<7)
+#define P_EWDS         (0<<7)
+#define P_WRAL         (0<<7)
+#define P_ERAL         (0<<7)
+#define P_EWEN         (0<<7)
+#define P_A_EWDS       (0<<5)
+#define P_A_WRAL       (1<<5)
+#define P_A_ERAL       (2<<5)
+#define P_A_EWEN       (3<<5)
+
+struct ssp_configuration {
+       int device;
+       int mode;
+       int speed;
+       int frame_size_write;
+       int frame_size_read;
+};
+
+static struct ssp_configuration ssp_configuration;
+static spinlock_t ssp_lock;
+
+static void enable_cs (void)
+{
+       switch (ssp_configuration.device) {
+       case DEVICE_EEPROM:
+               CPLD_SPI |= CPLD_SPI_CS_EEPROM;
+               break;
+       }
+       udelay (T_CSS);
+}
+
+static void disable_cs (void)
+{
+       switch (ssp_configuration.device) {
+       case DEVICE_EEPROM:
+               CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
+               break;
+       }
+       udelay (T_CS);
+}
+
+static void pulse_clock (void)
+{
+       CPLD_SPI |=  CPLD_SPI_SCLK;
+       udelay (T_SKH);
+       CPLD_SPI &= ~CPLD_SPI_SCLK;
+       udelay (T_SKL);
+}
+
+
+/* execute_spi_command
+
+   sends an spi command to a device.  It first sends cwrite bits from
+   v.  If cread is greater than zero it will read cread bits
+   (discarding the leading 0 bit) and return them.  If cread is less
+   than zero it will check for completetion status and return 0 on
+   success or -1 on timeout.  If cread is zero it does nothing other
+   than sending the command.
+
+   On the LPD7A400, we can only read or write multiples of 8 bits on
+   the codec and the touch screen device.  Here, we round up.
+
+*/
+
+static int execute_spi_command (int v, int cwrite, int cread)
+{
+       unsigned long l = 0;
+
+#if defined (CONFIG_MACH_LPD7A400)
+       /* The codec and touch devices cannot be bit-banged.  Instead,
+        * the CPLD provides an eight-bit shift register and a crude
+        * interface.  */
+       if (   ssp_configuration.device == DEVICE_CODEC
+           || ssp_configuration.device == DEVICE_TOUCH) {
+               int select = 0;
+
+               PRINTK ("spi(%d %d.%d) 0x%04x",
+                       ssp_configuration.device, cwrite, cread,
+                       v);
+#if defined (TALK)
+               if (ssp_configuration.device == DEVICE_CODEC)
+                       PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
+#endif
+               PRINTK ("\n");
+
+               if (ssp_configuration.device == DEVICE_CODEC)
+                       select = CPLD_SPIC_CS_CODEC;
+               if (ssp_configuration.device == DEVICE_TOUCH)
+                       select = CPLD_SPIC_CS_TOUCH;
+               if (cwrite) {
+                       for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
+                               CPLD_SPID = (v >> (8*cwrite)) & 0xff;
+                               CPLD_SPIC = select | CPLD_SPIC_LOAD;
+                               while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+                                       ;
+                               CPLD_SPIC = select;
+                               while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+                                       ;
+                       }
+                       v = 0;
+               }
+               if (cread) {
+                       mdelay (2);     /* *** FIXME: required by ads7843? */
+                       v = 0;
+                       for (cread = (cread + 7)/8; cread-- > 0;) {
+                               CPLD_SPID = 0;
+                               CPLD_SPIC = select | CPLD_SPIC_READ
+                                       | CPLD_SPIC_START;
+                               while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+                                       ;
+                               CPLD_SPIC = select | CPLD_SPIC_READ;
+                               while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+                                       ;
+                               v = (v << 8) | CPLD_SPID;
+                       }
+               }
+               return v;
+       }
+#endif
+
+       PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
+               v & 0x1ff, (v >> 9) & 0x7f);
+
+       enable_cs ();
+
+       v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
+       while (cwrite--) {
+               CPLD_SPI
+                       = (CPLD_SPI & ~CPLD_SPI_TX)
+                       | ((v >> cwrite) & CPLD_SPI_TX);
+               udelay (T_DIS);
+               pulse_clock ();
+       }
+
+       if (cread < 0) {
+               int delay = 10;
+               disable_cs ();
+               udelay (1);
+               enable_cs ();
+
+               l = -1;
+               do {
+                       if (CPLD_SPI & CPLD_SPI_RX) {
+                               l = 0;
+                               break;
+                       }
+               } while (udelay (1), --delay);
+       }
+       else
+       /* We pulse the clock before the data to skip the leading zero. */
+               while (cread-- > 0) {
+                       pulse_clock ();
+                       l = (l<<1)
+                               | (((CPLD_SPI & CPLD_SPI_RX)
+                                   >> CPLD_SPI_RX_SHIFT) & 0x1);
+               }
+
+       disable_cs ();
+       return l;
+}
+
+static int ssp_init (void)
+{
+       spin_lock_init (&ssp_lock);
+       memset (&ssp_configuration, 0, sizeof (ssp_configuration));
+       return 0;
+}
+
+
+/* ssp_chip_select
+
+   drops the chip select line for the CPLD shift-register controlled
+   devices.  It doesn't enable chip
+
+*/
+
+static void ssp_chip_select (int enable)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+       int select;
+
+       if (ssp_configuration.device == DEVICE_CODEC)
+               select = CPLD_SPIC_CS_CODEC;
+       else if (ssp_configuration.device == DEVICE_TOUCH)
+               select = CPLD_SPIC_CS_TOUCH;
+       else
+               return;
+
+       if (enable)
+               CPLD_SPIC = select;
+       else
+               CPLD_SPIC = 0;
+#endif
+}
+
+static void ssp_acquire (void)
+{
+       spin_lock (&ssp_lock);
+}
+
+static void ssp_release (void)
+{
+       ssp_chip_select (0);    /* just in case */
+       spin_unlock (&ssp_lock);
+}
+
+static int ssp_configure (int device, int mode, int speed,
+                          int frame_size_write, int frame_size_read)
+{
+       ssp_configuration.device                = device;
+       ssp_configuration.mode                  = mode;
+       ssp_configuration.speed                 = speed;
+       ssp_configuration.frame_size_write      = frame_size_write;
+       ssp_configuration.frame_size_read       = frame_size_read;
+
+       return 0;
+}
+
+static int ssp_read (void)
+{
+       return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
+}
+
+static int ssp_write (u16 data)
+{
+       execute_spi_command (data, ssp_configuration.frame_size_write, 0);
+       return 0;
+}
+
+static int ssp_write_read (u16 data)
+{
+       return execute_spi_command (data, ssp_configuration.frame_size_write,
+                                   ssp_configuration.frame_size_read);
+}
+
+struct ssp_driver lh7a40x_cpld_ssp_driver = {
+       .init           = ssp_init,
+       .acquire        = ssp_acquire,
+       .release        = ssp_release,
+       .configure      = ssp_configure,
+       .chip_select    = ssp_chip_select,
+       .read           = ssp_read,
+       .write          = ssp_write,
+       .write_read     = ssp_write_read,
+};
+
+
+MODULE_AUTHOR("Marc Singer");
+MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig
new file mode 100644 (file)
index 0000000..3d90ef1
--- /dev/null
@@ -0,0 +1,24 @@
+menu "NetX Implementations"
+       depends on ARCH_NETX
+
+config MACH_NXDKN
+       bool "Enable Hilscher nxdkn Eval Board support"
+       depends on ARCH_NETX
+       help
+         Board support for the Hilscher NetX Eval Board
+
+config MACH_NXDB500
+       bool "Enable Hilscher nxdb500 Eval Board support"
+       depends on ARCH_NETX
+       select ARM_AMBA
+       help
+         Board support for the Hilscher nxdb500 Eval Board
+
+config MACH_NXEB500HMI
+       bool "Enable Hilscher nxeb500hmi Eval Board support"
+       depends on ARCH_NETX
+       select ARM_AMBA
+       help
+         Board support for the Hilscher nxeb500hmi Eval Board
+
+endmenu
diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile
new file mode 100644 (file)
index 0000000..18785ff
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+# Object file lists.
+
+obj-y                  += time.o generic.o pfifo.o xc.o
+
+# Specific board support
+obj-$(CONFIG_MACH_NXDKN) += nxdkn.o
+obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o
+obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o
diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot
new file mode 100644 (file)
index 0000000..b81cf6a
--- /dev/null
@@ -0,0 +1,2 @@
+    zreladdr-y                 := 0x80008000
+
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
new file mode 100644 (file)
index 0000000..ef0ab61
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-netx/fb.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/device.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/arch/netx-regs.h>
+#include <asm/hardware.h>
+
+struct clk {};
+
+static struct clk fb_clk;
+
+static struct clcd_panel *netx_panel;
+
+void netx_clcd_enable(struct clcd_fb *fb)
+{
+}
+
+int netx_clcd_setup(struct clcd_fb *fb)
+{
+       dma_addr_t dma;
+
+       fb->panel = netx_panel;
+
+       fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024,
+                                                   &dma, GFP_KERNEL);
+       if (!fb->fb.screen_base) {
+               printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+               return -ENOMEM;
+       }
+
+       fb->fb.fix.smem_start   = dma;
+       fb->fb.fix.smem_len     = 1024*1024;
+
+       return 0;
+}
+
+int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       return dma_mmap_writecombine(&fb->dev->dev, vma,
+                                    fb->fb.screen_base,
+                                    fb->fb.fix.smem_start,
+                                    fb->fb.fix.smem_len);
+}
+
+void netx_clcd_remove(struct clcd_fb *fb)
+{
+       dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+                             fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+void clk_disable(struct clk *clk)
+{
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+       return 0;
+}
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       return &fb_clk;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+static struct amba_device fb_device = {
+       .dev            = {
+               .bus_id = "fb",
+               .coherent_dma_mask = ~0,
+       },
+       .res            = {
+               .start  = 0x00104000,
+               .end    = 0x00104fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       .irq            = { NETX_IRQ_LCD, NO_IRQ },
+       .periphid       = 0x10112400,
+};
+
+int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel)
+{
+       netx_panel = panel;
+       fb_device.dev.platform_data = board;
+       return amba_device_register(&fb_device, &iomem_resource);
+}
diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h
new file mode 100644 (file)
index 0000000..4919cf3
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-netx/fb.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+void netx_clcd_enable(struct clcd_fb *fb);
+int netx_clcd_setup(struct clcd_fb *fb);
+int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
+void netx_clcd_remove(struct clcd_fb *fb);
+int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel);
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
new file mode 100644 (file)
index 0000000..af0b135
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * arch/arm/mach-netx/generic.c
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/vic.h>
+#include <asm/io.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/mach/irq.h>
+
+static struct map_desc netx_io_desc[] __initdata = {
+       {
+               .virtual        = NETX_IO_VIRT,
+               .pfn            = __phys_to_pfn(NETX_IO_PHYS),
+               .length         = NETX_IO_SIZE,
+               .type           = MT_DEVICE
+       }
+};
+
+void __init netx_map_io(void)
+{
+       iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc));
+}
+
+static struct resource netx_rtc_resources[] = {
+       [0] = {
+               .start  = 0x00101200,
+               .end    = 0x00101220,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device netx_rtc_device = {
+       .name           = "netx-rtc",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(netx_rtc_resources),
+       .resource       = netx_rtc_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &netx_rtc_device,
+};
+
+#if 0
+#define DEBUG_IRQ(fmt...)      printk(fmt)
+#else
+#define DEBUG_IRQ(fmt...)      while (0) {}
+#endif
+
+static void
+netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+                       struct pt_regs *regs)
+{
+       unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
+       unsigned int stat;
+
+       stat = ((readl(NETX_DPMAS_INT_EN) &
+               readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
+
+       desc = irq_desc + NETX_IRQ_HIF_CHAINED(0);
+
+       while (stat) {
+               if (stat & 1) {
+                       DEBUG_IRQ("handling irq %d\n", irq);
+                       desc_handle_irq(irq, desc, regs);
+               }
+               irq++;
+               desc++;
+               stat >>= 1;
+       }
+}
+
+static int
+netx_hif_irq_type(unsigned int _irq, unsigned int type)
+{
+       unsigned int val, irq;
+
+       val = readl(NETX_DPMAS_IF_CONF1);
+
+       irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+
+       if (type & __IRQT_RISEDGE) {
+               DEBUG_IRQ("rising edges\n");
+               val |= (1 << 26) << irq;
+       }
+       if (type & __IRQT_FALEDGE) {
+               DEBUG_IRQ("falling edges\n");
+               val &= ~((1 << 26) << irq);
+       }
+       if (type & __IRQT_LOWLVL) {
+               DEBUG_IRQ("low level\n");
+               val &= ~((1 << 26) << irq);
+       }
+       if (type & __IRQT_HIGHLVL) {
+               DEBUG_IRQ("high level\n");
+               val |= (1 << 26) << irq;
+       }
+
+       writel(val, NETX_DPMAS_IF_CONF1);
+
+       return 0;
+}
+
+static void
+netx_hif_ack_irq(unsigned int _irq)
+{
+       unsigned int val, irq;
+
+       irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+       writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
+
+       val = readl(NETX_DPMAS_INT_EN);
+       val &= ~((1 << 24) << irq);
+       writel(val, NETX_DPMAS_INT_EN);
+
+       DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static void
+netx_hif_mask_irq(unsigned int _irq)
+{
+       unsigned int val, irq;
+
+       irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+       val = readl(NETX_DPMAS_INT_EN);
+       val &= ~((1 << 24) << irq);
+       writel(val, NETX_DPMAS_INT_EN);
+       DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static void
+netx_hif_unmask_irq(unsigned int _irq)
+{
+       unsigned int val, irq;
+
+       irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+       val = readl(NETX_DPMAS_INT_EN);
+       val |= (1 << 24) << irq;
+       writel(val, NETX_DPMAS_INT_EN);
+       DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static struct irqchip netx_hif_chip = {
+       .ack = netx_hif_ack_irq,
+       .mask = netx_hif_mask_irq,
+       .unmask = netx_hif_unmask_irq,
+       .set_type = netx_hif_irq_type,
+};
+
+void __init netx_init_irq(void)
+{
+       int irq;
+
+       vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0);
+
+       for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
+               set_irq_chip(irq, &netx_hif_chip);
+               set_irq_handler(irq, do_level_IRQ);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
+       set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
+}
+
+static int __init netx_init(void)
+{
+       return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(netx_init);
+
diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h
new file mode 100644 (file)
index 0000000..ede2d35
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-netx/generic.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+extern void __init netx_map_io(void);
+extern void __init netx_init_irq(void);
+
+struct sys_timer;
+extern struct sys_timer netx_timer;
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
new file mode 100644 (file)
index 0000000..e4a133d
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * arch/arm/mach-netx/nxdb500.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+#include "fb.h"
+
+static struct clcd_panel qvga = {
+       .mode           = {
+               .name           = "QVGA",
+               .refresh        = 60,
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = 187617,
+               .left_margin    = 6,
+               .right_margin   = 26,
+               .upper_margin   = 0,
+               .lower_margin   = 6,
+               .hsync_len      = 6,
+               .vsync_len      = 1,
+               .sync           = 0,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           =  16,
+       .cntl           = CNTL_LCDTFT | CNTL_BGR,
+       .bpp            = 16,
+       .grayscale      = 0,
+};
+
+static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+       var->green.length = 5;
+       var->green.msb_right = 0;
+
+       return clcdfb_check(fb, var);
+}
+
+static int nxdb500_clcd_setup(struct clcd_fb *fb)
+{
+       unsigned int val;
+
+       fb->fb.var.green.length = 5;
+       fb->fb.var.green.msb_right = 0;
+
+       /* enable asic control */
+       val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+       writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+       writel(3, NETX_SYSTEM_IOC_CR);
+
+       val = readl(NETX_PIO_OUTPIO);
+       writel(val | 1, NETX_PIO_OUTPIO);
+
+       val = readl(NETX_PIO_OEPIO);
+       writel(val | 1, NETX_PIO_OEPIO);
+       return netx_clcd_setup(fb);
+}
+
+static struct clcd_board clcd_data = {
+       .name           = "netX",
+       .check          = nxdb500_check,
+       .decode         = clcdfb_decode,
+       .enable         = netx_clcd_enable,
+       .setup          = nxdb500_clcd_setup,
+       .mmap           = netx_clcd_mmap,
+       .remove         = netx_clcd_remove,
+};
+
+static struct netxeth_platform_data eth0_platform_data = {
+       .xcno = 0,
+};
+
+static struct platform_device netx_eth0_device = {
+       .name           = "netx-eth",
+       .id             = 0,
+       .num_resources  = 0,
+       .resource       = NULL,
+       .dev = {
+               .platform_data = &eth0_platform_data,
+       }
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+       .xcno = 1,
+};
+
+static struct platform_device netx_eth1_device = {
+       .name           = "netx-eth",
+       .id             = 1,
+       .num_resources  = 0,
+       .resource       = NULL,
+       .dev = {
+               .platform_data = &eth1_platform_data,
+       }
+};
+
+static struct resource netx_uart0_resources[] = {
+       [0] = {
+               .start  = 0x00100A00,
+               .end    = 0x00100A3F,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (NETX_IRQ_UART0),
+               .end    = (NETX_IRQ_UART0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device netx_uart0_device = {
+       .name           = "netx-uart",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(netx_uart0_resources),
+       .resource       = netx_uart0_resources,
+};
+
+static struct resource netx_uart1_resources[] = {
+       [0] = {
+               .start  = 0x00100A40,
+               .end    = 0x00100A7F,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (NETX_IRQ_UART1),
+               .end    = (NETX_IRQ_UART1),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device netx_uart1_device = {
+       .name           = "netx-uart",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(netx_uart1_resources),
+       .resource       = netx_uart1_resources,
+};
+
+static struct resource netx_uart2_resources[] = {
+       [0] = {
+               .start  = 0x00100A80,
+               .end    = 0x00100ABF,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (NETX_IRQ_UART2),
+               .end    = (NETX_IRQ_UART2),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device netx_uart2_device = {
+       .name           = "netx-uart",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(netx_uart2_resources),
+       .resource       = netx_uart2_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &netx_eth0_device,
+       &netx_eth1_device,
+       &netx_uart0_device,
+       &netx_uart1_device,
+       &netx_uart2_device,
+};
+
+static void __init nxdb500_init(void)
+{
+       netx_fb_init(&clcd_data, &qvga);
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXDB500, "Hilscher nxdb500")
+       .phys_io        = 0x00100000,
+       .io_pg_offst    = (io_p2v(0x00100000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = netx_map_io,
+       .init_irq       = netx_init_irq,
+       .timer          = &netx_timer,
+       .init_machine   = nxdb500_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
new file mode 100644 (file)
index 0000000..7e26c42
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * arch/arm/mach-netx/nxdkn.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+
+static struct netxeth_platform_data eth0_platform_data = {
+       .xcno = 0,
+};
+
+static struct platform_device nxdkn_eth0_device = {
+       .name           = "netx-eth",
+       .id             = 0,
+       .num_resources  = 0,
+       .resource       = NULL,
+       .dev = {
+               .platform_data = &eth0_platform_data,
+       }
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+       .xcno = 1,
+};
+
+static struct platform_device nxdkn_eth1_device = {
+       .name           = "netx-eth",
+       .id             = 1,
+       .num_resources  = 0,
+       .resource       = NULL,
+       .dev = {
+               .platform_data = &eth1_platform_data,
+       }
+};
+
+static struct resource netx_uart0_resources[] = {
+       [0] = {
+               .start  = 0x00100A00,
+               .end    = 0x00100A3F,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (NETX_IRQ_UART0),
+               .end    = (NETX_IRQ_UART0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device netx_uart0_device = {
+       .name           = "netx-uart",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(netx_uart0_resources),
+       .resource       = netx_uart0_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &nxdkn_eth0_device,
+       &nxdkn_eth1_device,
+       &netx_uart0_device,
+};
+
+static void __init nxdkn_init(void)
+{
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXDKN, "Hilscher nxdkn")
+       .phys_io        = 0x00100000,
+       .io_pg_offst    = (io_p2v(0x00100000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = netx_map_io,
+       .init_irq       = netx_init_irq,
+       .timer          = &netx_timer,
+       .init_machine   = nxdkn_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
new file mode 100644 (file)
index 0000000..53e10a9
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * arch/arm/mach-netx/nxeb500hmi.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+#include "fb.h"
+
+static struct clcd_panel qvga = {
+       .mode           = {
+               .name           = "QVGA",
+               .refresh        = 60,
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = 187617,
+               .left_margin    = 6,
+               .right_margin   = 26,
+               .upper_margin   = 0,
+               .lower_margin   = 6,
+               .hsync_len      = 6,
+               .vsync_len      = 1,
+               .sync           = 0,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           =  16,
+       .cntl           = CNTL_LCDTFT | CNTL_BGR,
+       .bpp            = 16,
+       .grayscale      = 0,
+};
+
+static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+       var->green.length = 5;
+       var->green.msb_right = 0;
+
+       return clcdfb_check(fb, var);
+}
+
+static int nxeb500hmi_clcd_setup(struct clcd_fb *fb)
+{
+       unsigned int val;
+
+       fb->fb.var.green.length = 5;
+       fb->fb.var.green.msb_right = 0;
+
+       /* enable asic control */
+       val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+       writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+       writel(3, NETX_SYSTEM_IOC_CR);
+
+       /* GPIO 14 is used for display enable on newer boards */
+       writel(9, NETX_GPIO_CFG(14));
+
+       val = readl(NETX_PIO_OUTPIO);
+       writel(val | 1, NETX_PIO_OUTPIO);
+
+       val = readl(NETX_PIO_OEPIO);
+       writel(val | 1, NETX_PIO_OEPIO);
+       return netx_clcd_setup(fb);
+}
+
+static struct clcd_board clcd_data = {
+       .name           = "netX",
+       .check          = nxeb500hmi_check,
+       .decode         = clcdfb_decode,
+       .enable         = netx_clcd_enable,
+       .setup          = nxeb500hmi_clcd_setup,
+       .mmap           = netx_clcd_mmap,
+       .remove         = netx_clcd_remove,
+};
+
+static struct netxeth_platform_data eth0_platform_data = {
+       .xcno = 0,
+};
+
+static struct platform_device netx_eth0_device = {
+       .name           = "netx-eth",
+       .id             = 0,
+       .num_resources  = 0,
+       .resource       = NULL,
+       .dev = {
+               .platform_data = &eth0_platform_data,
+       }
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+       .xcno = 1,
+};
+
+static struct platform_device netx_eth1_device = {
+       .name           = "netx-eth",
+       .id             = 1,
+       .num_resources  = 0,
+       .resource       = NULL,
+       .dev = {
+               .platform_data = &eth1_platform_data,
+       }
+};
+
+static struct resource netx_cf_resources[] = {
+       [0] = {
+               .start  = 0x20000000,
+               .end    = 0x25ffffff,
+               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+       },
+};
+
+static struct platform_device netx_cf_device = {
+       .name           = "netx-cf",
+       .id             = 0,
+       .resource       = netx_cf_resources,
+       .num_resources  = ARRAY_SIZE(netx_cf_resources),
+};
+
+static struct resource netx_uart0_resources[] = {
+       [0] = {
+               .start  = 0x00100A00,
+               .end    = 0x00100A3F,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = (NETX_IRQ_UART0),
+               .end    = (NETX_IRQ_UART0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device netx_uart0_device = {
+       .name           = "netx-uart",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(netx_uart0_resources),
+       .resource       = netx_uart0_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &netx_eth0_device,
+       &netx_eth1_device,
+       &netx_cf_device,
+       &netx_uart0_device,
+};
+
+static void __init nxeb500hmi_init(void)
+{
+       netx_fb_init(&clcd_data, &qvga);
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
+       .phys_io        = 0x00100000,
+       .io_pg_offst    = (io_p2v(0x00100000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = netx_map_io,
+       .init_irq       = netx_init_irq,
+       .timer          = &netx_timer,
+       .init_machine   = nxeb500hmi_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c
new file mode 100644 (file)
index 0000000..44dea61
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * arch/arm/mach-netx/pfifo.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/pfifo.h>
+
+static DEFINE_MUTEX(pfifo_lock);
+
+static unsigned int pfifo_used = 0;
+
+int pfifo_request(unsigned int pfifo_mask)
+{
+       int err = 0;
+       unsigned int val;
+
+       mutex_lock(&pfifo_lock);
+
+       if (pfifo_mask & pfifo_used) {
+               err = -EBUSY;
+               goto out;
+       }
+
+       pfifo_used |= pfifo_mask;
+
+       val = readl(NETX_PFIFO_RESET);
+       writel(val | pfifo_mask, NETX_PFIFO_RESET);
+       writel(val, NETX_PFIFO_RESET);
+
+out:
+       mutex_unlock(&pfifo_lock);
+       return err;
+}
+
+void pfifo_free(unsigned int pfifo_mask)
+{
+       mutex_lock(&pfifo_lock);
+       pfifo_used &= ~pfifo_mask;
+       mutex_unlock(&pfifo_lock);
+}
+
+EXPORT_SYMBOL(pfifo_push);
+EXPORT_SYMBOL(pfifo_pop);
+EXPORT_SYMBOL(pfifo_fill_level);
+EXPORT_SYMBOL(pfifo_empty);
+EXPORT_SYMBOL(pfifo_request);
+EXPORT_SYMBOL(pfifo_free);
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
new file mode 100644 (file)
index 0000000..6d72c81
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-netx/time.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+#include <asm/arch/netx-regs.h>
+
+/*
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long netx_gettimeoffset(void)
+{
+       return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100;
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       write_seqlock(&xtime_lock);
+
+       timer_tick(regs);
+       write_sequnlock(&xtime_lock);
+
+       /* acknowledge interrupt */
+       writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
+
+       return IRQ_HANDLED;
+}
+
+
+static struct irqaction netx_timer_irq = {
+       .name           = "NetX Timer Tick",
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .handler        = netx_timer_interrupt,
+};
+
+/*
+ * Set up timer interrupt
+ */
+static void __init netx_timer_init(void)
+{
+       /* disable timer initially */
+       writel(0, NETX_GPIO_COUNTER_CTRL(0));
+
+       /* Reset the timer value to zero */
+       writel(0, NETX_GPIO_COUNTER_CURRENT(0));
+
+       writel(LATCH, NETX_GPIO_COUNTER_MAX(0));
+
+       /* acknowledge interrupt */
+       writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
+
+       /* Enable the interrupt in the specific timer register and start timer */
+       writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE);
+       writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN,
+               NETX_GPIO_COUNTER_CTRL(0));
+
+       setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq);
+}
+
+struct sys_timer netx_timer = {
+       .init           = netx_timer_init,
+       .offset         = netx_gettimeoffset,
+};
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
new file mode 100644 (file)
index 0000000..172a058
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * arch/arm/mach-netx/xc.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/init.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+
+#include <asm/arch/xc.h>
+
+static DEFINE_MUTEX(xc_lock);
+
+static int xc_in_use = 0;
+
+struct fw_desc {
+       unsigned int ofs;
+       unsigned int size;
+       unsigned int patch_ofs;
+       unsigned int patch_entries;
+};
+
+struct fw_header {
+       unsigned int magic;
+       unsigned int type;
+       unsigned int version;
+       unsigned int reserved[5];
+       struct fw_desc fw_desc[3];
+} __attribute__ ((packed));
+
+int xc_stop(struct xc *x)
+{
+       writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
+       writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
+       writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
+       return 0;
+}
+
+int xc_start(struct xc *x)
+{
+       writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
+       writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
+       writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
+       return 0;
+}
+
+int xc_running(struct xc *x)
+{
+       return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC)
+           || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC)
+           || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ?
+               0 : 1;
+}
+
+int xc_reset(struct xc *x)
+{
+       writel(0, x->xpec_base + NETX_XPEC_PC_OFS);
+       return 0;
+}
+
+static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size)
+{
+       if (adr >= NETX_PA_XMAC(x->no) &&
+           adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE)
+               return 0;
+
+       if (adr >= NETX_PA_XPEC(x->no) &&
+           adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE)
+               return 0;
+
+       dev_err(x->dev, "Illegal pointer in firmware found. aborting\n");
+
+       return -1;
+}
+
+static int xc_patch(struct xc *x, void *patch, int count)
+{
+       unsigned int val, adr;
+       unsigned int *data = patch;
+
+       int i;
+       for (i = 0; i < count; i++) {
+               adr = *data++;
+               val = *data++;
+               if (xc_check_ptr(x, adr, 4) < 0)
+                       return -EINVAL;
+
+               writel(val, (void __iomem *)io_p2v(adr));
+       }
+       return 0;
+}
+
+int xc_request_firmware(struct xc *x)
+{
+       int ret;
+       char name[16];
+       const struct firmware *fw;
+       struct fw_header *head;
+       unsigned int size;
+       int i;
+       void *src;
+       unsigned long dst;
+
+       sprintf(name, "xc%d.bin", x->no);
+
+       ret = request_firmware(&fw, name, x->dev);
+
+       if (ret < 0) {
+               dev_err(x->dev, "request_firmware failed\n");
+               return ret;
+       }
+
+       head = (struct fw_header *)fw->data;
+       if (head->magic != 0x4e657458) {
+               if (head->magic == 0x5874654e) {
+                       dev_err(x->dev,
+                           "firmware magic is 'XteN'. Endianess problems?\n");
+                       ret = -ENODEV;
+                       goto exit_release_firmware;
+               }
+               dev_err(x->dev, "unrecognized firmware magic 0x%08x\n",
+                       head->magic);
+               ret = -ENODEV;
+               goto exit_release_firmware;
+       }
+
+       x->type = head->type;
+       x->version = head->version;
+
+       ret = -EINVAL;
+
+       for (i = 0; i < 3; i++) {
+               src = fw->data + head->fw_desc[i].ofs;
+               dst = *(unsigned int *)src;
+               src += sizeof (unsigned int);
+               size = head->fw_desc[i].size - sizeof (unsigned int);
+
+               if (xc_check_ptr(x, dst, size))
+                       goto exit_release_firmware;
+
+               memcpy((void *)io_p2v(dst), src, size);
+
+               src = fw->data + head->fw_desc[i].patch_ofs;
+               size = head->fw_desc[i].patch_entries;
+               ret = xc_patch(x, src, size);
+               if (ret < 0)
+                       goto exit_release_firmware;
+       }
+
+       ret = 0;
+
+      exit_release_firmware:
+       release_firmware(fw);
+
+       return ret;
+}
+
+struct xc *request_xc(int xcno, struct device *dev)
+{
+       struct xc *x = NULL;
+
+       mutex_lock(&xc_lock);
+
+       if (xcno > 3)
+               goto exit;
+       if (xc_in_use & (1 << xcno))
+               goto exit;
+
+       x = kmalloc(sizeof (struct xc), GFP_KERNEL);
+       if (!x)
+               goto exit;
+
+       if (!request_mem_region
+           (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name))
+               goto exit_free;
+
+       if (!request_mem_region
+           (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name))
+               goto exit_release_1;
+
+       if (!request_mem_region
+           (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name))
+               goto exit_release_2;
+
+       x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno));
+       x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno));
+       x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+       if (!x->sram_base)
+               goto exit_release_3;
+
+       x->irq = NETX_IRQ_XPEC(xcno);
+
+       x->no = xcno;
+       x->dev = dev;
+
+       xc_in_use |= (1 << xcno);
+
+       goto exit;
+
+      exit_release_3:
+       release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+      exit_release_2:
+       release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
+      exit_release_1:
+       release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
+      exit_free:
+       kfree(x);
+       x = NULL;
+      exit:
+       mutex_unlock(&xc_lock);
+       return x;
+}
+
+void free_xc(struct xc *x)
+{
+       int xcno = x->no;
+
+       mutex_lock(&xc_lock);
+
+       iounmap(x->sram_base);
+       release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+       release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
+       release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
+       xc_in_use &= ~(1 << x->no);
+       kfree(x);
+
+       mutex_unlock(&xc_lock);
+}
+
+EXPORT_SYMBOL(free_xc);
+EXPORT_SYMBOL(request_xc);
+EXPORT_SYMBOL(xc_request_firmware);
+EXPORT_SYMBOL(xc_reset);
+EXPORT_SYMBOL(xc_running);
+EXPORT_SYMBOL(xc_start);
+EXPORT_SYMBOL(xc_stop);
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
new file mode 100644 (file)
index 0000000..c753a3c
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * linux/arch/arm/mach-omap1/board-fsample.c
+ *
+ * Modified from board-perseus2.c
+ *
+ * Original OMAP730 support by Jean Pihet <j-pihet@ti.com>
+ * Updated for 2.6 by Kevin Hilman <kjh@hilman.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/tc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/board.h>
+#include <asm/arch/board-fsample.h>
+
+static int fsample_keymap[] = {
+       KEY(0,0,KEY_UP),
+       KEY(0,1,KEY_RIGHT),
+       KEY(0,2,KEY_LEFT),
+       KEY(0,3,KEY_DOWN),
+       KEY(0,4,KEY_CENTER),
+       KEY(0,5,KEY_0_5),
+       KEY(1,0,KEY_SOFT2),
+       KEY(1,1,KEY_SEND),
+       KEY(1,2,KEY_END),
+       KEY(1,3,KEY_VOLUMEDOWN),
+       KEY(1,4,KEY_VOLUMEUP),
+       KEY(1,5,KEY_RECORD),
+       KEY(2,0,KEY_SOFT1),
+       KEY(2,1,KEY_3),
+       KEY(2,2,KEY_6),
+       KEY(2,3,KEY_9),
+       KEY(2,4,KEY_SHARP),
+       KEY(2,5,KEY_2_5),
+       KEY(3,0,KEY_BACK),
+       KEY(3,1,KEY_2),
+       KEY(3,2,KEY_5),
+       KEY(3,3,KEY_8),
+       KEY(3,4,KEY_0),
+       KEY(3,5,KEY_HEADSETHOOK),
+       KEY(4,0,KEY_HOME),
+       KEY(4,1,KEY_1),
+       KEY(4,2,KEY_4),
+       KEY(4,3,KEY_7),
+       KEY(4,4,KEY_STAR),
+       KEY(4,5,KEY_POWER),
+       0
+};
+
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = H2P2_DBG_FPGA_ETHR_START,     /* Physical */
+               .end    = H2P2_DBG_FPGA_ETHR_START + 0xf,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = INT_730_MPU_EXT_NIRQ,
+               .end    = 0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct mtd_partition nor_partitions[] = {
+       /* bootloader (U-Boot, etc) in first sector */
+       {
+             .name             = "bootloader",
+             .offset           = 0,
+             .size             = SZ_128K,
+             .mask_flags       = MTD_WRITEABLE, /* force read-only */
+       },
+       /* bootloader params in the next sector */
+       {
+             .name             = "params",
+             .offset           = MTDPART_OFS_APPEND,
+             .size             = SZ_128K,
+             .mask_flags       = 0,
+       },
+       /* kernel */
+       {
+             .name             = "kernel",
+             .offset           = MTDPART_OFS_APPEND,
+             .size             = SZ_2M,
+             .mask_flags       = 0
+       },
+       /* rest of flash is a file system */
+       {
+             .name             = "rootfs",
+             .offset           = MTDPART_OFS_APPEND,
+             .size             = MTDPART_SIZ_FULL,
+             .mask_flags       = 0
+       },
+};
+
+static struct flash_platform_data nor_data = {
+       .map_name       = "cfi_probe",
+       .width          = 2,
+       .parts          = nor_partitions,
+       .nr_parts       = ARRAY_SIZE(nor_partitions),
+};
+
+static struct resource nor_resource = {
+       .start          = OMAP_CS0_PHYS,
+       .end            = OMAP_CS0_PHYS + SZ_32M - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device nor_device = {
+       .name           = "omapflash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &nor_data,
+       },
+       .num_resources  = 1,
+       .resource       = &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+       .options        = NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+       .start          = OMAP_CS3_PHYS,
+       .end            = OMAP_CS3_PHYS + SZ_4K - 1,
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+       .name           = "omapnand",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &nand_resource,
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static struct resource kp_resources[] = {
+       [0] = {
+               .start  = INT_730_MPUIO_KEYPAD,
+               .end    = INT_730_MPUIO_KEYPAD,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct omap_kp_platform_data kp_data = {
+       .rows   = 8,
+       .cols   = 8,
+       .keymap = fsample_keymap,
+};
+
+static struct platform_device kp_device = {
+       .name           = "omap-keypad",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &kp_data,
+       },
+       .num_resources  = ARRAY_SIZE(kp_resources),
+       .resource       = kp_resources,
+};
+
+static struct platform_device lcd_device = {
+       .name           = "lcd_p2",
+       .id             = -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &nor_device,
+       &nand_device,
+       &smc91x_device,
+       &kp_device,
+       &lcd_device,
+};
+
+#define P2_NAND_RB_GPIO_PIN    62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+       return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
+static struct omap_uart_config fsample_uart_config __initdata = {
+       .enabled_uarts = ((1 << 0) | (1 << 1)),
+};
+
+static struct omap_lcd_config fsample_lcd_config __initdata = {
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel fsample_config[] = {
+       { OMAP_TAG_UART,        &fsample_uart_config },
+       { OMAP_TAG_LCD,         &fsample_lcd_config },
+};
+
+static void __init omap_fsample_init(void)
+{
+       if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+               nand_data.dev_ready = nand_dev_ready;
+
+       omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+       omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       omap_board_config = fsample_config;
+       omap_board_config_size = ARRAY_SIZE(fsample_config);
+       omap_serial_init();
+}
+
+static void __init fsample_init_smc91x(void)
+{
+       fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+       mdelay(50);
+       fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+                  H2P2_DBG_FPGA_LAN_RESET);
+       mdelay(50);
+}
+
+void omap_fsample_init_irq(void)
+{
+       omap1_init_common_hw();
+       omap_init_irq();
+       omap_gpio_init();
+       fsample_init_smc91x();
+}
+
+/* Only FPGA needs to be mapped here. All others are done with ioremap */
+static struct map_desc omap_fsample_io_desc[] __initdata = {
+       {
+               .virtual        = H2P2_DBG_FPGA_BASE,
+               .pfn            = __phys_to_pfn(H2P2_DBG_FPGA_START),
+               .length         = H2P2_DBG_FPGA_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = FSAMPLE_CPLD_BASE,
+               .pfn            = __phys_to_pfn(FSAMPLE_CPLD_START),
+               .length         = FSAMPLE_CPLD_SIZE,
+               .type           = MT_DEVICE
+       }
+};
+
+static void __init omap_fsample_map_io(void)
+{
+       omap1_map_common_io();
+       iotable_init(omap_fsample_io_desc,
+                    ARRAY_SIZE(omap_fsample_io_desc));
+
+       /* Early, board-dependent init */
+
+       /*
+        * Hold GSM Reset until needed
+        */
+       omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL);
+
+       /*
+        * UARTs -> done automagically by 8250 driver
+        */
+
+       /*
+        * CSx timings, GPIO Mux ... setup
+        */
+
+       /* Flash: CS0 timings setup */
+       omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0);
+       omap_writel(0x00000088, OMAP730_FLASH_ACFG_0);
+
+       /*
+        * Ethernet support through the debug board
+        * CS1 timings setup
+        */
+       omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1);
+       omap_writel(0x00000000, OMAP730_FLASH_ACFG_1);
+
+       /*
+        * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+        * It is used as the Ethernet controller interrupt
+        */
+       omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
+}
+
+MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
+/* Maintainer: Brian Swetland <swetland@google.com> */
+       .phys_io        = 0xfff00000,
+       .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
+       .boot_params    = 0x10000100,
+       .map_io         = omap_fsample_map_io,
+       .init_irq       = omap_fsample_init_irq,
+       .init_machine   = omap_fsample_init,
+       .timer          = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
new file mode 100644 (file)
index 0000000..c7a48f9
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * GPMC support functions
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ *
+ * Author: Juha Yrjola
+ *
+ * This program is free software; you can 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/clk.h>
+
+#include <asm/io.h>
+#include <asm/arch/gpmc.h>
+
+#undef DEBUG
+
+#define GPMC_BASE              0x6800a000
+#define GPMC_REVISION          0x00
+#define GPMC_SYSCONFIG         0x10
+#define GPMC_SYSSTATUS         0x14
+#define GPMC_IRQSTATUS         0x18
+#define GPMC_IRQENABLE         0x1c
+#define GPMC_TIMEOUT_CONTROL   0x40
+#define GPMC_ERR_ADDRESS       0x44
+#define GPMC_ERR_TYPE          0x48
+#define GPMC_CONFIG            0x50
+#define GPMC_STATUS            0x54
+#define GPMC_PREFETCH_CONFIG1  0x1e0
+#define GPMC_PREFETCH_CONFIG2  0x1e4
+#define GPMC_PREFETCH_CONTROL  0x1e8
+#define GPMC_PREFETCH_STATUS   0x1f0
+#define GPMC_ECC_CONFIG                0x1f4
+#define GPMC_ECC_CONTROL       0x1f8
+#define GPMC_ECC_SIZE_CONFIG   0x1fc
+
+#define GPMC_CS0               0x60
+#define GPMC_CS_SIZE           0x30
+
+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 struct clk *gpmc_l3_clk;
+
+static void gpmc_write_reg(int idx, u32 val)
+{
+       __raw_writel(val, gpmc_base + idx);
+}
+
+static u32 gpmc_read_reg(int idx)
+{
+       return __raw_readl(gpmc_base + idx);
+}
+
+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;
+       __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);
+}
+
+/* TODO: Add support for gpmc_fck to clock framework and use it */
+static unsigned long gpmc_get_fclk_period(void)
+{
+       /* In picoseconds */
+       return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000);
+}
+
+unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+{
+       unsigned long tick_ps;
+
+       /* Calculate in picosecs to yield more exact results */
+       tick_ps = gpmc_get_fclk_period();
+
+       return (time_ns * 1000 + tick_ps - 1) / tick_ps;
+}
+
+#ifdef DEBUG
+static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
+                              int time, const char *name)
+#else
+static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
+                              int time)
+#endif
+{
+       u32 l;
+       int ticks, mask, nr_bits;
+
+       if (time == 0)
+               ticks = 0;
+       else
+               ticks = gpmc_ns_to_ticks(time);
+       nr_bits = end_bit - st_bit + 1;
+       if (ticks >= 1 << nr_bits)
+               return -1;
+
+       mask = (1 << nr_bits) - 1;
+       l = gpmc_cs_read_reg(cs, reg);
+#ifdef DEBUG
+       printk(KERN_INFO "GPMC CS%d: %-10s: %d ticks, %3lu ns (was %i ticks)\n",
+              cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
+              (l >> st_bit) & mask);
+#endif
+       l &= ~(mask << st_bit);
+       l |= ticks << st_bit;
+       gpmc_cs_write_reg(cs, reg, l);
+
+       return 0;
+}
+
+#ifdef DEBUG
+#define GPMC_SET_ONE(reg, st, end, field) \
+       if (set_gpmc_timing_reg(cs, (reg), (st), (end),         \
+                       t->field, #field) < 0)                  \
+               return -1
+#else
+#define GPMC_SET_ONE(reg, st, end, field) \
+       if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \
+               return -1
+#endif
+
+int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
+{
+       int div;
+       u32 l;
+
+       l = sync_clk * 1000 + (gpmc_get_fclk_period() - 1);
+       div = l / gpmc_get_fclk_period();
+       if (div > 4)
+               return -1;
+       if (div < 0)
+               div = 1;
+
+       return div;
+}
+
+int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
+{
+       int div;
+       u32 l;
+
+       div = gpmc_cs_calc_divider(cs, t->sync_clk);
+       if (div < 0)
+               return -1;
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG2,  0,  3, cs_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG2,  8, 12, cs_rd_off);
+       GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG3,  0,  3, adv_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG3,  8, 12, adv_rd_off);
+       GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG4,  0,  3, oe_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG4,  8, 12, oe_off);
+       GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG5,  0,  4, rd_cycle);
+       GPMC_SET_ONE(GPMC_CS_CONFIG5,  8, 12, wr_cycle);
+       GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
+
+#ifdef DEBUG
+       printk(KERN_INFO "GPMC CS%d CLK period is %lu (div %d)\n",
+              cs, gpmc_get_fclk_period(), div);
+#endif
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+       l &= ~0x03;
+       l |= (div - 1);
+
+       return 0;
+}
+
+unsigned long gpmc_cs_get_base_addr(int cs)
+{
+       return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24;
+}
+
+void __init gpmc_init(void)
+{
+       u32 l;
+
+       gpmc_l3_clk = clk_get(NULL, "core_l3_ck");
+       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);
+       /* Set smart idle mode and automatic L3 clock gating */
+       l = gpmc_read_reg(GPMC_SYSCONFIG);
+       l &= 0x03 << 3;
+       l |= (0x02 << 3) | (1 << 0);
+       gpmc_write_reg(GPMC_SYSCONFIG, l);
+}
diff --git a/arch/arm/mach-omap2/pm-domain.c b/arch/arm/mach-omap2/pm-domain.c
new file mode 100644 (file)
index 0000000..2494091
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * linux/arch/arm/mach-omap2/pm-domain.c
+ *
+ * Power domain functions for OMAP2
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Some code based on earlier OMAP2 sample PM code
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+#include "prcm-regs.h"
+
+/* Power domain offsets */
+#define PM_MPU_OFFSET                  0x100
+#define PM_CORE_OFFSET                 0x200
+#define PM_GFX_OFFSET                  0x300
+#define PM_WKUP_OFFSET                 0x400           /* Autoidle only */
+#define PM_PLL_OFFSET                  0x500           /* Autoidle only */
+#define PM_DSP_OFFSET                  0x800
+#define PM_MDM_OFFSET                  0xc00
+
+/* Power domain wake-up dependency control register */
+#define PM_WKDEP_OFFSET                        0xc8
+#define                EN_MDM                  (1 << 5)
+#define                EN_WKUP                 (1 << 4)
+#define                EN_GFX                  (1 << 3)
+#define                EN_DSP                  (1 << 2)
+#define                EN_MPU                  (1 << 1)
+#define                EN_CORE                 (1 << 0)
+
+/* Core power domain state transition control register */
+#define PM_PWSTCTRL_OFFSET             0xe0
+#define                FORCESTATE              (1 << 18)       /* Only for DSP & GFX */
+#define                MEM4RETSTATE            (1 << 6)
+#define                MEM3RETSTATE            (1 << 5)
+#define                MEM2RETSTATE            (1 << 4)
+#define                MEM1RETSTATE            (1 << 3)
+#define                LOGICRETSTATE           (1 << 2)        /* Logic is retained */
+#define                POWERSTATE_OFF          0x3
+#define                POWERSTATE_RETENTION    0x1
+#define                POWERSTATE_ON           0x0
+
+/* Power domain state register */
+#define PM_PWSTST_OFFSET               0xe4
+
+/* Hardware supervised state transition control register */
+#define CM_CLKSTCTRL_OFFSET            0x48
+#define                AUTOSTAT_MPU            (1 << 0)        /* MPU */
+#define                AUTOSTAT_DSS            (1 << 2)        /* Core */
+#define                AUTOSTAT_L4             (1 << 1)        /* Core */
+#define                AUTOSTAT_L3             (1 << 0)        /* Core */
+#define                AUTOSTAT_GFX            (1 << 0)        /* GFX */
+#define                AUTOSTAT_IVA            (1 << 8)        /* 2420 IVA in DSP domain */
+#define                AUTOSTAT_DSP            (1 << 0)        /* DSP */
+#define                AUTOSTAT_MDM            (1 << 0)        /* MDM */
+
+/* Automatic control of interface clock idling */
+#define CM_AUTOIDLE1_OFFSET            0x30
+#define CM_AUTOIDLE2_OFFSET            0x34            /* Core only */
+#define CM_AUTOIDLE3_OFFSET            0x38            /* Core only */
+#define CM_AUTOIDLE4_OFFSET            0x3c            /* Core only */
+#define                AUTO_54M(x)             (((x) & 0x3) << 6)
+#define                AUTO_96M(x)             (((x) & 0x3) << 2)
+#define                AUTO_DPLL(x)            (((x) & 0x3) << 0)
+#define                AUTO_STOPPED            0x3
+#define                AUTO_BYPASS_FAST        0x2             /* DPLL only */
+#define                AUTO_BYPASS_LOW_POWER   0x1             /* DPLL only */
+#define                AUTO_DISABLED           0x0
+
+/* Voltage control PRCM_VOLTCTRL bits */
+#define                AUTO_EXTVOLT            (1 << 15)
+#define                FORCE_EXTVOLT           (1 << 14)
+#define                SETOFF_LEVEL(x)         (((x) & 0x3) << 12)
+#define                MEMRETCTRL              (1 << 8)
+#define                SETRET_LEVEL(x)         (((x) & 0x3) << 6)
+#define                VOLT_LEVEL(x)           (((x) & 0x3) << 0)
+
+#define OMAP24XX_PRCM_VBASE    IO_ADDRESS(OMAP24XX_PRCM_BASE)
+#define prcm_readl(r)          __raw_readl(OMAP24XX_PRCM_VBASE + (r))
+#define prcm_writel(v, r)      __raw_writel((v), OMAP24XX_PRCM_VBASE + (r))
+
+static u32 pmdomain_get_wakeup_dependencies(int domain_offset)
+{
+       return prcm_readl(domain_offset + PM_WKDEP_OFFSET);
+}
+
+static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset)
+{
+       prcm_writel(state, domain_offset + PM_WKDEP_OFFSET);
+}
+
+static u32 pmdomain_get_powerstate(int domain_offset)
+{
+       return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET);
+}
+
+static void pmdomain_set_powerstate(u32 state, int domain_offset)
+{
+       prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET);
+}
+
+static u32 pmdomain_get_clock_autocontrol(int domain_offset)
+{
+       return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET);
+}
+
+static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset)
+{
+       prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET);
+}
+
+static u32 pmdomain_get_clock_autoidle1(int domain_offset)
+{
+       return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET);
+}
+
+/* Core domain only */
+static u32 pmdomain_get_clock_autoidle2(int domain_offset)
+{
+       return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET);
+}
+
+/* Core domain only */
+static u32 pmdomain_get_clock_autoidle3(int domain_offset)
+{
+       return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET);
+}
+
+/* Core domain only */
+static u32 pmdomain_get_clock_autoidle4(int domain_offset)
+{
+       return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET);
+}
+
+static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset)
+{
+       prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset);
+}
+
+/* Core domain only */
+static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset)
+{
+       prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset);
+}
+
+/* Core domain only */
+static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset)
+{
+       prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset);
+}
+
+/* Core domain only */
+static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset)
+{
+       prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset);
+}
+
+/*
+ * Configures power management domains to idle clocks automatically.
+ */
+void pmdomain_set_autoidle(void)
+{
+       u32 val;
+
+       /* Set PLL auto stop for 54M, 96M & DPLL */
+       pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) |
+                                    AUTO_96M(AUTO_STOPPED) |
+                                    AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET);
+
+       /* External clock input control
+        * REVISIT: Should this be in clock framework?
+        */
+       PRCM_CLKSRC_CTRL |= (0x3 << 3);
+
+       /* Configure number of 32KHz clock cycles for sys_clk */
+       PRCM_CLKSSETUP = 0x00ff;
+
+       /* Configure automatic voltage transition */
+       PRCM_VOLTSETUP = 0;
+       val = PRCM_VOLTCTRL;
+       val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3));
+       val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT;
+       PRCM_VOLTCTRL = val;
+
+       /* Disable emulation tools functional clock */
+       PRCM_CLKEMUL_CTRL = 0x0;
+
+       /* Set core memory retention state */
+       val = pmdomain_get_powerstate(PM_CORE_OFFSET);
+       if (cpu_is_omap2420()) {
+               val &= ~(0x7 << 3);
+               val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE);
+       } else {
+               val &= ~(0xf << 3);
+               val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE |
+                       MEM1RETSTATE);
+       }
+       pmdomain_set_powerstate(val, PM_CORE_OFFSET);
+
+       /* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */
+       val = SMS_SYSCONFIG;
+       val &= ~(0x3 << 3);
+       val |= (0x2 << 3) | (1 << 0);
+       SMS_SYSCONFIG |= val;
+
+       val = SDRC_SYSCONFIG;
+       val &= ~(0x3 << 3);
+       val |= (0x2 << 3);
+       SDRC_SYSCONFIG = val;
+
+       /* Configure L3 interface for smart idle.
+        * REVISIT: Enable autoidle bit0 ?
+        */
+       val = GPMC_SYSCONFIG;
+       val &= ~(0x3 << 3);
+       val |= (0x2 << 3) | (1 << 0);
+       GPMC_SYSCONFIG = val;
+
+       pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION,
+                               PM_MPU_OFFSET);
+       pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET);
+       if (!cpu_is_omap2420())
+               pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET);
+
+       /* Assume suspend function has saved the state for DSP and GFX */
+       pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET);
+       pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET);
+
+#if 0
+       /* REVISIT: Internal USB needs special handling */
+       force_standby_usb();
+       if (cpu_is_omap2430())
+               force_hsmmc();
+       sdram_self_refresh_on_idle_req(1);
+#endif
+
+       /* Enable clock auto control for all domains.
+        * Note that CORE domain includes also DSS, L4 & L3.
+        */
+       pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET);
+       pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET);
+       pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3,
+                                      PM_CORE_OFFSET);
+       if (cpu_is_omap2420())
+               pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP,
+                                              PM_DSP_OFFSET);
+       else {
+               pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET);
+               pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET);
+       }
+
+       /* Enable clock autoidle for all domains */
+       pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET);
+       if (cpu_is_omap2420()) {
+               pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET);
+               pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET);
+               pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET);
+       } else {
+               pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET);
+               pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET);
+               pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET);
+               pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET);
+       }
+       pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET);
+       pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET);
+}
+
+/*
+ * Initializes power domains by removing wake-up dependencies and powering
+ * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code
+ * must re-enable DSP and GFX when used.
+ */
+void __init pmdomain_init(void)
+{
+       /* Remove all domain wakeup dependencies */
+       pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET);
+       pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET);
+       pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET);
+       pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET);
+       if (cpu_is_omap2430())
+               pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET);
+
+       /* Power down DSP and GFX */
+       pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET);
+       pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET);
+}
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
new file mode 100644 (file)
index 0000000..b457ca0
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                  := core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot
new file mode 100644 (file)
index 0000000..44c7117
--- /dev/null
@@ -0,0 +1,4 @@
+   zreladdr-y          := 0x80008000
+params_phys-y          := 0x80000100
+initrd_phys-y          := 0x80800000
+
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
new file mode 100644 (file)
index 0000000..f582ed2
--- /dev/null
@@ -0,0 +1,983 @@
+/*
+ * arch/arm/mach-pnx4008/clock.c
+ *
+ * Clock control driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ * Generic clock management functions are partially based on:
+ *  linux/arch/arm/mach-omap/clock.c
+ *
+ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include "clock.h"
+
+/*forward declaration*/
+static struct clk per_ck;
+static struct clk hclk_ck;
+static struct clk ck_1MHz;
+static struct clk ck_13MHz;
+static struct clk ck_pll1;
+static int local_set_rate(struct clk *clk, u32 rate);
+
+static inline void clock_lock(void)
+{
+       local_irq_disable();
+}
+
+static inline void clock_unlock(void)
+{
+       local_irq_enable();
+}
+
+static void propagate_rate(struct clk *clk)
+{
+       struct clk *tmp_clk;
+
+       tmp_clk = clk;
+       while (tmp_clk->propagate_next) {
+               tmp_clk = tmp_clk->propagate_next;
+               local_set_rate(tmp_clk, tmp_clk->user_rate);
+       }
+}
+
+static inline void clk_reg_disable(struct clk *clk)
+{
+       if (clk->enable_reg)
+               __raw_writel(__raw_readl(clk->enable_reg) &
+                            ~(1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_enable(struct clk *clk)
+{
+       if (clk->enable_reg)
+               __raw_writel(__raw_readl(clk->enable_reg) |
+                            (1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_disable1(struct clk *clk)
+{
+       if (clk->enable_reg1)
+               __raw_writel(__raw_readl(clk->enable_reg1) &
+                            ~(1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static inline void clk_reg_enable1(struct clk *clk)
+{
+       if (clk->enable_reg1)
+               __raw_writel(__raw_readl(clk->enable_reg1) |
+                            (1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static int clk_wait_for_pll_lock(struct clk *clk)
+{
+       int i;
+       i = 0;
+       while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ;     /*wait for PLL to lock */
+
+       if (!(__raw_readl(clk->scale_reg) & 1)) {
+               printk(KERN_ERR
+                      "%s ERROR: failed to lock, scale reg data: %x\n",
+                      clk->name, __raw_readl(clk->scale_reg));
+               return -1;
+       }
+       return 0;
+}
+
+static int switch_to_dirty_13mhz(struct clk *clk)
+{
+       int i;
+       int ret;
+       u32 tmp_reg;
+
+       ret = 0;
+
+       if (!clk->rate)
+               clk_reg_enable1(clk);
+
+       tmp_reg = __raw_readl(clk->parent_switch_reg);
+       /*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
+       if (!(tmp_reg & 1)) {
+               tmp_reg |= (1 << 1);    /* Trigger switch to 13'MHz (dirty) clock */
+               __raw_writel(tmp_reg, clk->parent_switch_reg);
+               i = 0;
+               while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ;     /*wait for 13'MHz selection status */
+
+               if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
+                       printk(KERN_ERR
+                              "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
+                              clk->name, __raw_readl(clk->parent_switch_reg));
+                       ret = -1;
+               }
+       }
+
+       if (!clk->rate)
+               clk_reg_disable1(clk);
+
+       return ret;
+}
+
+static int switch_to_clean_13mhz(struct clk *clk)
+{
+       int i;
+       int ret;
+       u32 tmp_reg;
+
+       ret = 0;
+
+       if (!clk->rate)
+               clk_reg_enable1(clk);
+
+       tmp_reg = __raw_readl(clk->parent_switch_reg);
+       /*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
+       if (tmp_reg & 1) {
+               tmp_reg &= ~(1 << 1);   /* Trigger switch to 13MHz (clean) clock */
+               __raw_writel(tmp_reg, clk->parent_switch_reg);
+               i = 0;
+               while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ;      /*wait for 13MHz selection status */
+
+               if (__raw_readl(clk->parent_switch_reg) & 1) {
+                       printk(KERN_ERR
+                              "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
+                              clk->name, __raw_readl(clk->parent_switch_reg));
+                       ret = -1;
+               }
+       }
+
+       if (!clk->rate)
+               clk_reg_disable1(clk);
+
+       return ret;
+}
+
+static int set_13MHz_parent(struct clk *clk, struct clk *parent)
+{
+       int ret = -EINVAL;
+
+       if (parent == &ck_13MHz)
+               ret = switch_to_clean_13mhz(clk);
+       else if (parent == &ck_pll1)
+               ret = switch_to_dirty_13mhz(clk);
+
+       return ret;
+}
+
+#define PLL160_MIN_FCCO 156000
+#define PLL160_MAX_FCCO 320000
+
+/*
+ * Calculate pll160 settings.
+ * Possible input: up to 320MHz with step of clk->parent->rate.
+ * In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
+ * Ignored paths: "feedback" (bit 13 set), "div-by-N".
+ * Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
+ * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
+ * Please refer to PNX4008 IC manual for details.
+ */
+
+static int pll160_set_rate(struct clk *clk, u32 rate)
+{
+       u32 tmp_reg, tmp_m, tmp_2p, i;
+       u32 parent_rate;
+       int ret = -EINVAL;
+
+       parent_rate = clk->parent->rate;
+
+       if (!parent_rate)
+               goto out;
+
+       /* set direct run for ARM or disable output for others  */
+       clk_reg_disable(clk);
+
+       /* disable source input as well (ignored for ARM) */
+       clk_reg_disable1(clk);
+
+       tmp_reg = __raw_readl(clk->scale_reg);
+       tmp_reg &= ~0x1ffff;    /*clear all settings, power down */
+       __raw_writel(tmp_reg, clk->scale_reg);
+
+       rate -= rate % parent_rate;     /*round down the input */
+
+       if (rate > PLL160_MAX_FCCO)
+               rate = PLL160_MAX_FCCO;
+
+       if (!rate) {
+               clk->rate = 0;
+               ret = 0;
+               goto out;
+       }
+
+       clk_reg_enable1(clk);
+       tmp_reg = __raw_readl(clk->scale_reg);
+
+       if (rate == parent_rate) {
+               /*enter direct bypass mode */
+               tmp_reg |= ((1 << 14) | (1 << 15));
+               __raw_writel(tmp_reg, clk->scale_reg);
+               clk->rate = parent_rate;
+               clk_reg_enable(clk);
+               ret = 0;
+               goto out;
+       }
+
+       i = 0;
+       for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
+               if (rate * tmp_2p >= PLL160_MIN_FCCO)
+                       break;
+               i++;
+       }
+
+       if (tmp_2p > 1)
+               tmp_reg |= ((i - 1) << 11);
+       else
+               tmp_reg |= (1 << 14);   /*direct mode, no divide */
+
+       tmp_m = rate * tmp_2p;
+       tmp_m /= parent_rate;
+
+       tmp_reg |= (tmp_m - 1) << 1;    /*calculate M */
+       tmp_reg |= (1 << 16);   /*power up PLL */
+       __raw_writel(tmp_reg, clk->scale_reg);
+
+       if (clk_wait_for_pll_lock(clk) < 0) {
+               clk_reg_disable(clk);
+               clk_reg_disable1(clk);
+
+               tmp_reg = __raw_readl(clk->scale_reg);
+               tmp_reg &= ~0x1ffff;    /*clear all settings, power down */
+               __raw_writel(tmp_reg, clk->scale_reg);
+               clk->rate = 0;
+               ret = -EFAULT;
+               goto out;
+       }
+
+       clk->rate = (tmp_m * parent_rate) / tmp_2p;
+
+       if (clk->flags & RATE_PROPAGATES)
+               propagate_rate(clk);
+
+       clk_reg_enable(clk);
+       ret = 0;
+
+out:
+       return ret;
+}
+
+/*configure PER_CLK*/
+static int per_clk_set_rate(struct clk *clk, u32 rate)
+{
+       u32 tmp;
+
+       tmp = __raw_readl(clk->scale_reg);
+       tmp &= ~(0x1f << 2);
+       tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
+       __raw_writel(tmp, clk->scale_reg);
+       clk->rate = rate;
+       return 0;
+}
+
+/*configure HCLK*/
+static int hclk_set_rate(struct clk *clk, u32 rate)
+{
+       u32 tmp;
+       tmp = __raw_readl(clk->scale_reg);
+       tmp = tmp & ~0x3;
+       switch (rate) {
+       case 1:
+               break;
+       case 2:
+               tmp |= 1;
+               break;
+       case 4:
+               tmp |= 2;
+               break;
+       }
+
+       __raw_writel(tmp, clk->scale_reg);
+       clk->rate = rate;
+       return 0;
+}
+
+static u32 hclk_round_rate(struct clk *clk, u32 rate)
+{
+       switch (rate) {
+       case 1:
+       case 4:
+               return rate;
+       }
+       return 2;
+}
+
+static u32 per_clk_round_rate(struct clk *clk, u32 rate)
+{
+       return CLK_RATE_13MHZ;
+}
+
+static int on_off_set_rate(struct clk *clk, u32 rate)
+{
+       if (rate) {
+               clk_reg_enable(clk);
+               clk->rate = 1;
+       } else {
+               clk_reg_disable(clk);
+               clk->rate = 0;
+       }
+       return 0;
+}
+
+static int on_off_inv_set_rate(struct clk *clk, u32 rate)
+{
+       if (rate) {
+               clk_reg_disable(clk);   /*enable bit is inverted */
+               clk->rate = 1;
+       } else {
+               clk_reg_enable(clk);
+               clk->rate = 0;
+       }
+       return 0;
+}
+
+static u32 on_off_round_rate(struct clk *clk, u32 rate)
+{
+       return (rate ? 1 : 0);
+}
+
+static u32 pll4_round_rate(struct clk *clk, u32 rate)
+{
+       if (rate > CLK_RATE_208MHZ)
+               rate = CLK_RATE_208MHZ;
+       if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
+               rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
+       return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
+}
+
+static u32 pll3_round_rate(struct clk *clk, u32 rate)
+{
+       if (rate > CLK_RATE_208MHZ)
+               rate = CLK_RATE_208MHZ;
+       return (rate - rate % CLK_RATE_13MHZ);
+}
+
+static u32 pll5_round_rate(struct clk *clk, u32 rate)
+{
+       return (rate ? CLK_RATE_48MHZ : 0);
+}
+
+static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
+{
+       return (rate ? CLK_RATE_13MHZ : 0);
+}
+
+static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
+{
+       if (rate) {
+               clk_reg_disable(clk);   /*enable bit is inverted */
+               udelay(500);
+               clk->rate = CLK_RATE_13MHZ;
+               ck_1MHz.rate = CLK_RATE_1MHZ;
+       } else {
+               clk_reg_enable(clk);
+               clk->rate = 0;
+               ck_1MHz.rate = 0;
+       }
+       return 0;
+}
+
+static int pll1_set_rate(struct clk *clk, u32 rate)
+{
+#if 0 /* doesn't work on some boards, probably a HW BUG */
+       if (rate) {
+               clk_reg_disable(clk);   /*enable bit is inverted */
+               if (!clk_wait_for_pll_lock(clk)) {
+                       clk->rate = CLK_RATE_13MHZ;
+               } else {
+                       clk_reg_enable(clk);
+                       clk->rate = 0;
+               }
+
+       } else {
+               clk_reg_enable(clk);
+               clk->rate = 0;
+       }
+#endif
+       return 0;
+}
+
+/* Clock sources */
+
+static struct clk osc_13MHz = {
+       .name = "osc_13MHz",
+       .flags = FIXED_RATE,
+       .rate = CLK_RATE_13MHZ,
+};
+
+static struct clk ck_13MHz = {
+       .name = "ck_13MHz",
+       .parent = &osc_13MHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &ck_13MHz_round_rate,
+       .set_rate = &ck_13MHz_set_rate,
+       .enable_reg = OSC13CTRL_REG,
+       .enable_shift = 0,
+       .rate = CLK_RATE_13MHZ,
+};
+
+static struct clk osc_32KHz = {
+       .name = "osc_32KHz",
+       .flags = FIXED_RATE,
+       .rate = CLK_RATE_32KHZ,
+};
+
+/*attached to PLL5*/
+static struct clk ck_1MHz = {
+       .name = "ck_1MHz",
+       .flags = FIXED_RATE | PARENT_SET_RATE,
+       .parent = &ck_13MHz,
+};
+
+/* PLL1 (397) - provides 13' MHz clock */
+static struct clk ck_pll1 = {
+       .name = "ck_pll1",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &ck_13MHz_round_rate,
+       .set_rate = &pll1_set_rate,
+       .enable_reg = PLLCTRL_REG,
+       .enable_shift = 1,
+       .scale_reg = PLLCTRL_REG,
+       .rate = CLK_RATE_13MHZ,
+};
+
+/* CPU/Bus PLL */
+static struct clk ck_pll4 = {
+       .name = "ck_pll4",
+       .parent = &ck_pll1,
+       .flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
+       .propagate_next = &per_ck,
+       .round_rate = &pll4_round_rate,
+       .set_rate = &pll160_set_rate,
+       .rate = CLK_RATE_208MHZ,
+       .scale_reg = HCLKPLLCTRL_REG,
+       .enable_reg = PWRCTRL_REG,
+       .enable_shift = 2,
+       .parent_switch_reg = SYSCLKCTRL_REG,
+       .set_parent = &set_13MHz_parent,
+};
+
+/* USB PLL */
+static struct clk ck_pll5 = {
+       .name = "ck_pll5",
+       .parent = &ck_1MHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &pll5_round_rate,
+       .set_rate = &pll160_set_rate,
+       .scale_reg = USBCTRL_REG,
+       .enable_reg = USBCTRL_REG,
+       .enable_shift = 18,
+       .enable_reg1 = USBCTRL_REG,
+       .enable_shift1 = 17,
+};
+
+/* XPERTTeak DSP PLL */
+static struct clk ck_pll3 = {
+       .name = "ck_pll3",
+       .parent = &ck_pll1,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &pll3_round_rate,
+       .set_rate = &pll160_set_rate,
+       .scale_reg = DSPPLLCTRL_REG,
+       .enable_reg = DSPCLKCTRL_REG,
+       .enable_shift = 3,
+       .enable_reg1 = DSPCLKCTRL_REG,
+       .enable_shift1 = 2,
+       .parent_switch_reg = DSPCLKCTRL_REG,
+       .set_parent = &set_13MHz_parent,
+};
+
+static struct clk hclk_ck = {
+       .name = "hclk_ck",
+       .parent = &ck_pll4,
+       .flags = PARENT_SET_RATE,
+       .set_rate = &hclk_set_rate,
+       .round_rate = &hclk_round_rate,
+       .scale_reg = HCLKDIVCTRL_REG,
+       .rate = 2,
+       .user_rate = 2,
+};
+
+static struct clk per_ck = {
+       .name = "per_ck",
+       .parent = &ck_pll4,
+       .flags = FIXED_RATE,
+       .propagate_next = &hclk_ck,
+       .set_rate = &per_clk_set_rate,
+       .round_rate = &per_clk_round_rate,
+       .scale_reg = HCLKDIVCTRL_REG,
+       .rate = CLK_RATE_13MHZ,
+       .user_rate = CLK_RATE_13MHZ,
+};
+
+static struct clk m2hclk_ck = {
+       .name = "m2hclk_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_inv_set_rate,
+       .rate = 1,
+       .enable_shift = 6,
+       .enable_reg = PWRCTRL_REG,
+};
+
+static struct clk vfp9_ck = {
+       .name = "vfp9_ck",
+       .parent = &ck_pll4,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .rate = 1,
+       .enable_shift = 4,
+       .enable_reg = VFP9CLKCTRL_REG,
+};
+
+static struct clk keyscan_ck = {
+       .name = "keyscan_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = KEYCLKCTRL_REG,
+};
+
+static struct clk touch_ck = {
+       .name = "touch_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = TSCLKCTRL_REG,
+};
+
+static struct clk pwm1_ck = {
+       .name = "pwm1_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk pwm2_ck = {
+       .name = "pwm2_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 2,
+       .enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk jpeg_ck = {
+       .name = "jpeg_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = JPEGCLKCTRL_REG,
+};
+
+static struct clk ms_ck = {
+       .name = "ms_ck",
+       .parent = &ck_pll4,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 5,
+       .enable_reg = MSCTRL_REG,
+};
+
+static struct clk dum_ck = {
+       .name = "dum_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = DUMCLKCTRL_REG,
+};
+
+static struct clk flash_ck = {
+       .name = "flash_ck",
+       .parent = &hclk_ck,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 1,      /* Only MLC clock supported */
+       .enable_reg = FLASHCLKCTRL_REG,
+};
+
+static struct clk i2c0_ck = {
+       .name = "i2c0_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c1_ck = {
+       .name = "i2c1_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 1,
+       .enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c2_ck = {
+       .name = "i2c2_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 2,
+       .enable_reg = USB_OTG_CLKCTRL_REG,
+};
+
+static struct clk spi0_ck = {
+       .name = "spi0_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = SPICTRL_REG,
+};
+
+static struct clk spi1_ck = {
+       .name = "spi1_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 4,
+       .enable_reg = SPICTRL_REG,
+};
+
+static struct clk dma_ck = {
+       .name = "dma_ck",
+       .parent = &hclk_ck,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = DMACLKCTRL_REG,
+};
+
+static struct clk uart3_ck = {
+       .name = "uart3_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .rate = 1,
+       .enable_shift = 0,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart4_ck = {
+       .name = "uart4_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 1,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart5_ck = {
+       .name = "uart5_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .rate = 1,
+       .enable_shift = 2,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart6_ck = {
+       .name = "uart6_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 3,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+/* These clocks are visible outside this module
+ * and can be initialized
+ */
+static struct clk *onchip_clks[] = {
+       &ck_13MHz,
+       &ck_pll1,
+       &ck_pll4,
+       &ck_pll5,
+       &ck_pll3,
+       &vfp9_ck,
+       &m2hclk_ck,
+       &hclk_ck,
+       &dma_ck,
+       &flash_ck,
+       &dum_ck,
+       &keyscan_ck,
+       &pwm1_ck,
+       &pwm2_ck,
+       &jpeg_ck,
+       &ms_ck,
+       &touch_ck,
+       &i2c0_ck,
+       &i2c1_ck,
+       &i2c2_ck,
+       &spi0_ck,
+       &spi1_ck,
+       &uart3_ck,
+       &uart4_ck,
+       &uart5_ck,
+       &uart6_ck,
+};
+
+static int local_clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
+           && clk->user_rate)
+               ret = clk->set_rate(clk, clk->user_rate);
+       return ret;
+}
+
+static void local_clk_disable(struct clk *clk)
+{
+       if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
+               clk->set_rate(clk, 0);
+}
+
+static void local_clk_unuse(struct clk *clk)
+{
+       if (clk->usecount > 0 && !(--clk->usecount)) {
+               local_clk_disable(clk);
+               if (clk->parent)
+                       local_clk_unuse(clk->parent);
+       }
+}
+
+static int local_clk_use(struct clk *clk)
+{
+       int ret = 0;
+       if (clk->usecount++ == 0) {
+               if (clk->parent)
+                       ret = local_clk_use(clk->parent);
+
+               if (ret != 0) {
+                       clk->usecount--;
+                       goto out;
+               }
+
+               ret = local_clk_enable(clk);
+
+               if (ret != 0 && clk->parent) {
+                       local_clk_unuse(clk->parent);
+                       clk->usecount--;
+               }
+       }
+out:
+       return ret;
+}
+
+static int local_set_rate(struct clk *clk, u32 rate)
+{
+       int ret = -EINVAL;
+       if (clk->set_rate) {
+
+               if (clk->user_rate == clk->rate && clk->parent->rate) {
+                       /* if clock enabled or rate not set */
+                       clk->user_rate = clk->round_rate(clk, rate);
+                       ret = clk->set_rate(clk, clk->user_rate);
+               } else
+                       clk->user_rate = clk->round_rate(clk, rate);
+               ret = 0;
+       }
+       return ret;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       int ret = -EINVAL;
+
+       if (clk->flags & FIXED_RATE)
+               goto out;
+
+       clock_lock();
+       if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
+
+               clk->user_rate = clk->round_rate(clk, rate);
+               /* parent clock needs to be refreshed
+                  for the setting to take effect */
+       } else {
+               ret = local_set_rate(clk, rate);
+       }
+       ret = 0;
+       clock_unlock();
+
+out:
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *clk = ERR_PTR(-ENOENT);
+       struct clk **clkp;
+
+       clock_lock();
+       for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+            clkp++) {
+               if (strcmp(id, (*clkp)->name) == 0
+                   && try_module_get((*clkp)->owner)) {
+                       clk = (*clkp);
+                       break;
+               }
+       }
+       clock_unlock();
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       clock_lock();
+       if (clk && !IS_ERR(clk))
+               module_put(clk->owner);
+       clock_unlock();
+}
+EXPORT_SYMBOL(clk_put);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       unsigned long ret;
+       clock_lock();
+       ret = clk->rate;
+       clock_unlock();
+       return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       clock_lock();
+       ret = local_clk_use(clk);
+       clock_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       clock_lock();
+       local_clk_unuse(clk);
+       clock_unlock();
+}
+
+EXPORT_SYMBOL(clk_disable);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       long ret;
+       clock_lock();
+       if (clk->round_rate)
+               ret = clk->round_rate(clk, rate);
+       else
+               ret = clk->rate;
+       clock_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       int ret = -ENODEV;
+       if (!clk->set_parent)
+               goto out;
+
+       clock_lock();
+       ret = clk->set_parent(clk, parent);
+       if (!ret)
+               clk->parent = parent;
+       clock_unlock();
+
+out:
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_set_parent);
+
+static int __init clk_init(void)
+{
+       struct clk **clkp;
+
+       /* Disable autoclocking, as it doesn't seem to work */
+       __raw_writel(0xff, AUTOCLK_CTRL);
+
+       for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+            clkp++) {
+               if (((*clkp)->flags & NEEDS_INITIALIZATION)
+                   && ((*clkp)->set_rate)) {
+                       (*clkp)->user_rate = (*clkp)->rate;
+                       local_set_rate((*clkp), (*clkp)->user_rate);
+                       if ((*clkp)->set_parent)
+                               (*clkp)->set_parent((*clkp), (*clkp)->parent);
+               }
+               pr_debug("%s: clock %s, rate %ld\n",
+                       __FUNCTION__, (*clkp)->name, (*clkp)->rate);
+       }
+
+       local_clk_use(&ck_pll4);
+
+       /* if ck_13MHz is not used, disable it. */
+       if (ck_13MHz.usecount == 0)
+               local_clk_disable(&ck_13MHz);
+
+       /* Disable autoclocking */
+       __raw_writeb(0xff, AUTOCLK_CTRL);
+
+       return 0;
+}
+
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h
new file mode 100644 (file)
index 0000000..cd58f37
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * arch/arm/mach-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - internal header file
+ *
+ * Author: Vitaly Wool <source@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ARCH_ARM_PNX4008_CLOCK_H__
+#define __ARCH_ARM_PNX4008_CLOCK_H__
+
+struct clk {
+       struct list_head node;
+       struct module *owner;
+       const char *name;
+       struct clk *parent;
+       struct clk *propagate_next;
+       u32 rate;
+       u32 user_rate;
+       s8 usecount;
+       u32 flags;
+       u32 scale_reg;
+       u8 enable_shift;
+       u32 enable_reg;
+       u8 enable_shift1;
+       u32 enable_reg1;
+       u32 parent_switch_reg;
+        u32(*round_rate) (struct clk *, u32);
+       int (*set_rate) (struct clk *, u32);
+       int (*set_parent) (struct clk * clk, struct clk * parent);
+};
+
+/* Flags */
+#define RATE_PROPAGATES      (1<<0)
+#define NEEDS_INITIALIZATION (1<<1)
+#define PARENT_SET_RATE      (1<<2)
+#define FIXED_RATE           (1<<3)
+
+#endif
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
new file mode 100644 (file)
index 0000000..3d73c1e
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * arch/arm/mach-pnx4008/core.c
+ *
+ * PNX4008 core startup code
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev,
+ * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/irq.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dma.h>
+
+struct resource spipnx_0_resources[] = {
+       {
+               .start = PNX4008_SPI1_BASE,
+               .end = PNX4008_SPI1_BASE + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = PER_SPI1_REC_XMIT,
+               .flags = IORESOURCE_DMA,
+       }, {
+               .start = SPI1_INT,
+               .flags = IORESOURCE_IRQ,
+       }, {
+               .flags = 0,
+       },
+};
+
+struct resource spipnx_1_resources[] = {
+       {
+               .start = PNX4008_SPI2_BASE,
+               .end = PNX4008_SPI2_BASE + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = PER_SPI2_REC_XMIT,
+               .flags = IORESOURCE_DMA,
+       }, {
+               .start = SPI2_INT,
+               .flags = IORESOURCE_IRQ,
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+       {
+               .modalias       = "m25p80",
+               .max_speed_hz   = 1000000,
+               .bus_num        = 1,
+               .chip_select    = 0,
+       },
+};
+
+static struct platform_device spipnx_1 = {
+       .name = "spipnx",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(spipnx_0_resources),
+       .resource = spipnx_0_resources,
+       .dev = {
+               .coherent_dma_mask = 0xFFFFFFFF,
+               },
+};
+
+static struct platform_device spipnx_2 = {
+       .name = "spipnx",
+       .id = 2,
+       .num_resources = ARRAY_SIZE(spipnx_1_resources),
+       .resource = spipnx_1_resources,
+       .dev = {
+               .coherent_dma_mask = 0xFFFFFFFF,
+               },
+};
+
+static struct plat_serial8250_port platform_serial_ports[] = {
+       {
+               .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
+               .mapbase = (unsigned long)PNX4008_UART5_BASE,
+               .irq = IIR5_INT,
+               .uartclk = PNX4008_UART_CLK,
+               .regshift = 2,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+       },
+       {
+               .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
+               .mapbase = (unsigned long)PNX4008_UART3_BASE,
+               .irq = IIR3_INT,
+               .uartclk = PNX4008_UART_CLK,
+               .regshift = 2,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+        },
+       {}
+};
+
+static struct platform_device serial_device = {
+       .name = "serial8250",
+       .id = PLAT8250_DEV_PLATFORM,
+       .dev = {
+               .platform_data = &platform_serial_ports,
+       },
+};
+
+static struct platform_device *devices[] __initdata = {
+       &spipnx_1,
+       &spipnx_2,
+       &serial_device,
+};
+
+
+extern void pnx4008_uart_init(void);
+
+static void __init pnx4008_init(void)
+{
+       /*disable all START interrupt sources,
+          and clear all START interrupt flags */
+       __raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
+       __raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+       spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+       /* Switch on the UART clocks */
+       pnx4008_uart_init();
+}
+
+static struct map_desc pnx4008_io_desc[] __initdata = {
+       {
+               .virtual        = IO_ADDRESS(PNX4008_IRAM_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_IRAM_BASE),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
+               .length         = SZ_1M - SZ_128K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
+               .length         = SZ_128K * 3,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
+               .length         = SZ_1M,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_AHB2FAB_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_AHB2FAB_BASE),
+               .length         = SZ_1M,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init pnx4008_map_io(void)
+{
+       iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
+}
+
+extern struct sys_timer pnx4008_timer;
+
+MACHINE_START(PNX4008, "Philips PNX4008")
+       /* Maintainer: MontaVista Software Inc. */
+       .phys_io                = 0x40090000,
+       .io_pg_offst            = (0xf4090000 >> 18) & 0xfffc,
+       .boot_params            = 0x80000100,
+       .map_io                 = pnx4008_map_io,
+       .init_irq               = pnx4008_init_irq,
+       .init_machine           = pnx4008_init,
+       .timer                  = &pnx4008_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c
new file mode 100644 (file)
index 0000000..ec01574
--- /dev/null
@@ -0,0 +1,1108 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/dma.c
+ *
+ *  PNX4008 DMA registration and IRQ dispatching
+ *
+ *  Author:    Vitaly Wool
+ *  Copyright: MontaVista Software Inc. (c) 2005
+ *
+ *  Based on the code from Nicolas Pitre
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+#include <asm/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/mach/dma.h>
+#include <asm/arch/clock.h>
+
+static struct dma_channel {
+       char *name;
+       void (*irq_handler) (int, int, void *, struct pt_regs *);
+       void *data;
+       struct pnx4008_dma_ll *ll;
+       u32 ll_dma;
+       void *target_addr;
+       int target_id;
+} dma_channels[MAX_DMA_CHANNELS];
+
+static struct ll_pool {
+       void *vaddr;
+       void *cur;
+       dma_addr_t dma_addr;
+       int count;
+} ll_pool;
+
+static spinlock_t ll_lock = SPIN_LOCK_UNLOCKED;
+
+struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma)
+{
+       struct pnx4008_dma_ll *ll = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ll_lock, flags);
+       if (ll_pool.count > 4) { /* can give one more */
+               ll = *(struct pnx4008_dma_ll **) ll_pool.cur;
+               *ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr);
+               *(void **)ll_pool.cur = **(void ***)ll_pool.cur;
+               memset(ll, 0, sizeof(*ll));
+               ll_pool.count--;
+       }
+       spin_unlock_irqrestore(&ll_lock, flags);
+
+       return ll;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry);
+
+void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma)
+{
+       unsigned long flags;
+
+       if (ll) {
+               if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) {
+                       printk(KERN_ERR "Trying to free entry not allocated by DMA\n");
+                       BUG();
+               }
+
+               if (ll->flags & DMA_BUFFER_ALLOCATED)
+                       ll->free(ll->alloc_data);
+
+               spin_lock_irqsave(&ll_lock, flags);
+               *(long *)ll = *(long *)ll_pool.cur;
+               *(long *)ll_pool.cur = (long)ll;
+               ll_pool.count++;
+               spin_unlock_irqrestore(&ll_lock, flags);
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry);
+
+void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll)
+{
+       struct pnx4008_dma_ll *ptr;
+       u32 dma;
+
+       while (ll) {
+               dma = ll->next_dma;
+               ptr = ll->next;
+               pnx4008_free_ll_entry(ll, ll_dma);
+
+               ll_dma = dma;
+               ll = ptr;
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll);
+
+static int dma_channels_requested = 0;
+
+static inline void dma_increment_usage(void)
+{
+       if (!dma_channels_requested++) {
+               struct clk *clk = clk_get(0, "dma_ck");
+               if (!IS_ERR(clk)) {
+                       clk_set_rate(clk, 1);
+                       clk_put(clk);
+               }
+               pnx4008_config_dma(-1, -1, 1);
+       }
+}
+static inline void dma_decrement_usage(void)
+{
+       if (!--dma_channels_requested) {
+               struct clk *clk = clk_get(0, "dma_ck");
+               if (!IS_ERR(clk)) {
+                       clk_set_rate(clk, 0);
+                       clk_put(clk);
+               }
+               pnx4008_config_dma(-1, -1, 0);
+
+       }
+}
+
+static spinlock_t dma_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void pnx4008_dma_lock(void)
+{
+       spin_lock_irq(&dma_lock);
+}
+
+static inline void pnx4008_dma_unlock(void)
+{
+       spin_unlock_irq(&dma_lock);
+}
+
+#define VALID_CHANNEL(c)       (((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
+
+int pnx4008_request_channel(char *name, int ch,
+                           void (*irq_handler) (int, int, void *,
+                                                struct pt_regs *), void *data)
+{
+       int i, found = 0;
+
+       /* basic sanity checks */
+       if (!name || (ch != -1 && !VALID_CHANNEL(ch)))
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+
+       /* try grabbing a DMA channel with the requested priority */
+       for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+               if (!dma_channels[i].name && (ch == -1 || ch == i)) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found) {
+               dma_increment_usage();
+               dma_channels[i].name = name;
+               dma_channels[i].irq_handler = irq_handler;
+               dma_channels[i].data = data;
+               dma_channels[i].ll = NULL;
+               dma_channels[i].ll_dma = 0;
+       } else {
+               printk(KERN_WARNING "No more available DMA channels for %s\n",
+                      name);
+               i = -ENODEV;
+       }
+
+       pnx4008_dma_unlock();
+       return i;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_request_channel);
+
+void pnx4008_free_channel(int ch)
+{
+       if (!dma_channels[ch].name) {
+               printk(KERN_CRIT
+                      "%s: trying to free channel %d which is already freed\n",
+                      __FUNCTION__, ch);
+               return;
+       }
+
+       pnx4008_dma_lock();
+       pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll);
+       dma_channels[ch].ll = NULL;
+       dma_decrement_usage();
+
+       dma_channels[ch].name = NULL;
+       pnx4008_dma_unlock();
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_channel);
+
+int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable)
+{
+       unsigned long dma_cfg = __raw_readl(DMAC_CONFIG);
+
+       switch (ahb_m1_be) {
+       case 0:
+               dma_cfg &= ~(1 << 1);
+               break;
+       case 1:
+               dma_cfg |= (1 << 1);
+               break;
+       default:
+               break;
+       }
+
+       switch (ahb_m2_be) {
+       case 0:
+               dma_cfg &= ~(1 << 2);
+               break;
+       case 1:
+               dma_cfg |= (1 << 2);
+               break;
+       default:
+               break;
+       }
+
+       switch (enable) {
+       case 0:
+               dma_cfg &= ~(1 << 0);
+               break;
+       case 1:
+               dma_cfg |= (1 << 0);
+               break;
+       default:
+               break;
+       }
+
+       pnx4008_dma_lock();
+       __raw_writel(dma_cfg, DMAC_CONFIG);
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_dma);
+
+int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl,
+                            unsigned long *ctrl)
+{
+       int i = 0, dbsize, sbsize, err = 0;
+
+       if (!ctrl || !ch_ctrl) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       *ctrl = 0;
+
+       switch (ch_ctrl->tc_mask) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 31);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+
+       switch (ch_ctrl->cacheable) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 30);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->bufferable) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 29);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->priv_mode) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 28);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->di) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 27);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->si) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 26);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->dest_ahb1) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 25);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->src_ahb1) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 24);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->dwidth) {
+       case WIDTH_BYTE:
+               *ctrl &= ~(7 << 21);
+               break;
+       case WIDTH_HWORD:
+               *ctrl &= ~(7 << 21);
+               *ctrl |= (1 << 21);
+               break;
+       case WIDTH_WORD:
+               *ctrl &= ~(7 << 21);
+               *ctrl |= (2 << 21);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->swidth) {
+       case WIDTH_BYTE:
+               *ctrl &= ~(7 << 18);
+               break;
+       case WIDTH_HWORD:
+               *ctrl &= ~(7 << 18);
+               *ctrl |= (1 << 18);
+               break;
+       case WIDTH_WORD:
+               *ctrl &= ~(7 << 18);
+               *ctrl |= (2 << 18);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       dbsize = ch_ctrl->dbsize;
+       while (!(dbsize & 1)) {
+               i++;
+               dbsize >>= 1;
+       }
+       if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) {
+               err = -EINVAL;
+               goto out;
+       } else if (i > 1)
+               i--;
+       *ctrl &= ~(7 << 15);
+       *ctrl |= (i << 15);
+
+       sbsize = ch_ctrl->sbsize;
+       while (!(sbsize & 1)) {
+               i++;
+               sbsize >>= 1;
+       }
+       if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) {
+               err = -EINVAL;
+               goto out;
+       } else if (i > 1)
+               i--;
+       *ctrl &= ~(7 << 12);
+       *ctrl |= (i << 12);
+
+       if (ch_ctrl->tr_size > 0x7ff) {
+               err = -E2BIG;
+               goto out;
+       }
+       *ctrl &= ~0x7ff;
+       *ctrl |= ch_ctrl->tr_size & 0x7ff;
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control);
+
+int pnx4008_dma_parse_control(unsigned long ctrl,
+                             struct pnx4008_dma_ch_ctrl * ch_ctrl)
+{
+       int err = 0;
+
+       if (!ch_ctrl) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       ch_ctrl->tr_size = ctrl & 0x7ff;
+       ctrl >>= 12;
+
+       ch_ctrl->sbsize = 1 << (ctrl & 7);
+       if (ch_ctrl->sbsize > 1)
+               ch_ctrl->sbsize <<= 1;
+       ctrl >>= 3;
+
+       ch_ctrl->dbsize = 1 << (ctrl & 7);
+       if (ch_ctrl->dbsize > 1)
+               ch_ctrl->dbsize <<= 1;
+       ctrl >>= 3;
+
+       switch (ctrl & 7) {
+       case 0:
+               ch_ctrl->swidth = WIDTH_BYTE;
+               break;
+       case 1:
+               ch_ctrl->swidth = WIDTH_HWORD;
+               break;
+       case 2:
+               ch_ctrl->swidth = WIDTH_WORD;
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       ctrl >>= 3;
+
+       switch (ctrl & 7) {
+       case 0:
+               ch_ctrl->dwidth = WIDTH_BYTE;
+               break;
+       case 1:
+               ch_ctrl->dwidth = WIDTH_HWORD;
+               break;
+       case 2:
+               ch_ctrl->dwidth = WIDTH_WORD;
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       ctrl >>= 3;
+
+       ch_ctrl->src_ahb1 = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->dest_ahb1 = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->si = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->di = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->priv_mode = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->bufferable = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->cacheable = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->tc_mask = ctrl & 1;
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control);
+
+int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg,
+                           unsigned long *cfg)
+{
+       int err = 0;
+
+       if (!cfg || !ch_cfg) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       *cfg = 0;
+
+       switch (ch_cfg->halt) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 18);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->active) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 17);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->lock) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 16);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->itc) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 15);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->ie) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 14);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->flow_cntrl) {
+       case FC_MEM2MEM_DMA:
+               *cfg &= ~(7 << 11);
+               break;
+       case FC_MEM2PER_DMA:
+               *cfg &= ~(7 << 11);
+               *cfg |= (1 << 11);
+               break;
+       case FC_PER2MEM_DMA:
+               *cfg &= ~(7 << 11);
+               *cfg |= (2 << 11);
+               break;
+       case FC_PER2PER_DMA:
+               *cfg &= ~(7 << 11);
+               *cfg |= (3 << 11);
+               break;
+       case FC_PER2PER_DPER:
+               *cfg &= ~(7 << 11);
+               *cfg |= (4 << 11);
+               break;
+       case FC_MEM2PER_PER:
+               *cfg &= ~(7 << 11);
+               *cfg |= (5 << 11);
+               break;
+       case FC_PER2MEM_PER:
+               *cfg &= ~(7 << 11);
+               *cfg |= (6 << 11);
+               break;
+       case FC_PER2PER_SPER:
+               *cfg |= (7 << 11);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       *cfg &= ~(0x1f << 6);
+       *cfg |= ((ch_cfg->dest_per & 0x1f) << 6);
+
+       *cfg &= ~(0x1f << 1);
+       *cfg |= ((ch_cfg->src_per & 0x1f) << 1);
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config);
+
+int pnx4008_dma_parse_config(unsigned long cfg,
+                            struct pnx4008_dma_ch_config * ch_cfg)
+{
+       int err = 0;
+
+       if (!ch_cfg) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       cfg >>= 1;
+
+       ch_cfg->src_per = cfg & 0x1f;
+       cfg >>= 5;
+
+       ch_cfg->dest_per = cfg & 0x1f;
+       cfg >>= 5;
+
+       switch (cfg & 7) {
+       case 0:
+               ch_cfg->flow_cntrl = FC_MEM2MEM_DMA;
+               break;
+       case 1:
+               ch_cfg->flow_cntrl = FC_MEM2PER_DMA;
+               break;
+       case 2:
+               ch_cfg->flow_cntrl = FC_PER2MEM_DMA;
+               break;
+       case 3:
+               ch_cfg->flow_cntrl = FC_PER2PER_DMA;
+               break;
+       case 4:
+               ch_cfg->flow_cntrl = FC_PER2PER_DPER;
+               break;
+       case 5:
+               ch_cfg->flow_cntrl = FC_MEM2PER_PER;
+               break;
+       case 6:
+               ch_cfg->flow_cntrl = FC_PER2MEM_PER;
+               break;
+       case 7:
+               ch_cfg->flow_cntrl = FC_PER2PER_SPER;
+       }
+       cfg >>= 3;
+
+       ch_cfg->ie = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->itc = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->lock = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->active = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->halt = cfg & 1;
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config);
+
+void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config,
+                                 struct pnx4008_dma_ch_ctrl * ctrl)
+{
+       int new_len = ctrl->tr_size, num_entries = 0;
+       int old_len = new_len;
+       int src_width, dest_width, count = 1;
+
+       switch (ctrl->swidth) {
+       case WIDTH_BYTE:
+               src_width = 1;
+               break;
+       case WIDTH_HWORD:
+               src_width = 2;
+               break;
+       case WIDTH_WORD:
+               src_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       switch (ctrl->dwidth) {
+       case WIDTH_BYTE:
+               dest_width = 1;
+               break;
+       case WIDTH_HWORD:
+               dest_width = 2;
+               break;
+       case WIDTH_WORD:
+               dest_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       while (new_len > 0x7FF) {
+               num_entries++;
+               new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+       }
+       if (num_entries != 0) {
+               struct pnx4008_dma_ll *ll = NULL;
+               config->ch_ctrl &= ~0x7ff;
+               config->ch_ctrl |= new_len;
+               if (!config->is_ll) {
+                       config->is_ll = 1;
+                       while (num_entries) {
+                               if (!ll) {
+                                       config->ll =
+                                           pnx4008_alloc_ll_entry(&config->
+                                                                  ll_dma);
+                                       ll = config->ll;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           config->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = config->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           config->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = config->dest_addr;
+                               ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+               } else {
+                       struct pnx4008_dma_ll *ll_old = config->ll;
+                       unsigned long ll_dma_old = config->ll_dma;
+                       while (num_entries) {
+                               if (!ll) {
+                                       config->ll =
+                                           pnx4008_alloc_ll_entry(&config->
+                                                                  ll_dma);
+                                       ll = config->ll;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           config->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = config->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           config->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = config->dest_addr;
+                               ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+                       ll->next_dma = ll_dma_old;
+                       ll->next = ll_old;
+               }
+               /* adjust last length/tc */
+               ll->ch_ctrl = config->ch_ctrl & (~0x7ff);
+               ll->ch_ctrl |= old_len - new_len * (count - 1);
+               config->ch_ctrl &= 0x7fffffff;
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry);
+
+void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll,
+                               struct pnx4008_dma_ch_ctrl * ctrl)
+{
+       int new_len = ctrl->tr_size, num_entries = 0;
+       int old_len = new_len;
+       int src_width, dest_width, count = 1;
+
+       switch (ctrl->swidth) {
+       case WIDTH_BYTE:
+               src_width = 1;
+               break;
+       case WIDTH_HWORD:
+               src_width = 2;
+               break;
+       case WIDTH_WORD:
+               src_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       switch (ctrl->dwidth) {
+       case WIDTH_BYTE:
+               dest_width = 1;
+               break;
+       case WIDTH_HWORD:
+               dest_width = 2;
+               break;
+       case WIDTH_WORD:
+               dest_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       while (new_len > 0x7FF) {
+               num_entries++;
+               new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+       }
+       if (num_entries != 0) {
+               struct pnx4008_dma_ll *ll = NULL;
+               cur_ll->ch_ctrl &= ~0x7ff;
+               cur_ll->ch_ctrl |= new_len;
+               if (!cur_ll->next) {
+                       while (num_entries) {
+                               if (!ll) {
+                                       cur_ll->next =
+                                           pnx4008_alloc_ll_entry(&cur_ll->
+                                                                  next_dma);
+                                       ll = cur_ll->next;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           cur_ll->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = cur_ll->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           cur_ll->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = cur_ll->dest_addr;
+                               ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+               } else {
+                       struct pnx4008_dma_ll *ll_old = cur_ll->next;
+                       unsigned long ll_dma_old = cur_ll->next_dma;
+                       while (num_entries) {
+                               if (!ll) {
+                                       cur_ll->next =
+                                           pnx4008_alloc_ll_entry(&cur_ll->
+                                                                  next_dma);
+                                       ll = cur_ll->next;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           cur_ll->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = cur_ll->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           cur_ll->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = cur_ll->dest_addr;
+                               ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+
+                       ll->next_dma = ll_dma_old;
+                       ll->next = ll_old;
+               }
+               /* adjust last length/tc */
+               ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff);
+               ll->ch_ctrl |= old_len - new_len * (count - 1);
+               cur_ll->ch_ctrl &= 0x7fffffff;
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry);
+
+int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config)
+{
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       __raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch));
+       __raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch));
+
+       if (config->is_ll)
+               __raw_writel(config->ll_dma, DMAC_Cx_LLI(ch));
+       else
+               __raw_writel(0, DMAC_Cx_LLI(ch));
+
+       __raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch));
+       __raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_channel);
+
+int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config)
+{
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch));
+
+       config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch));
+       config->is_ll = config->ll_dma ? 1 : 0;
+
+       config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch));
+       config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_channel_get_config);
+
+int pnx4008_dma_ch_enable(int ch)
+{
+       unsigned long ch_cfg;
+
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       ch_cfg |= 1;
+       __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable);
+
+int pnx4008_dma_ch_disable(int ch)
+{
+       unsigned long ch_cfg;
+
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       ch_cfg &= ~1;
+       __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable);
+
+int pnx4008_dma_ch_enabled(int ch)
+{
+       unsigned long ch_cfg;
+
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return ch_cfg & 1;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       int i;
+       unsigned long dint = __raw_readl(DMAC_INT_STAT);
+       unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT);
+       unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT);
+       unsigned long i_bit;
+
+       for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+               i_bit = 1 << i;
+               if (dint & i_bit) {
+                       struct dma_channel *channel = &dma_channels[i];
+
+                       if (channel->name && channel->irq_handler) {
+                               int cause = 0;
+
+                               if (eint & i_bit)
+                                       cause |= DMA_ERR_INT;
+                               if (tcint & i_bit)
+                                       cause |= DMA_TC_INT;
+                               channel->irq_handler(i, cause, channel->data,
+                                                    regs);
+                       } else {
+                               /*
+                                * IRQ for an unregistered DMA channel
+                                */
+                               printk(KERN_WARNING
+                                      "spurious IRQ for DMA channel %d\n", i);
+                       }
+                       if (tcint & i_bit)
+                               __raw_writel(i_bit, DMAC_INT_TC_CLEAR);
+                       if (eint & i_bit)
+                               __raw_writel(i_bit, DMAC_INT_ERR_CLEAR);
+               }
+       }
+       return IRQ_HANDLED;
+}
+
+static int __init pnx4008_dma_init(void)
+{
+       int ret, i;
+
+       ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+       if (ret) {
+               printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+               goto out;
+       }
+
+       ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll);
+       ll_pool.cur = ll_pool.vaddr =
+           dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll),
+                              &ll_pool.dma_addr, GFP_KERNEL);
+
+       if (!ll_pool.vaddr) {
+               ret = -ENOMEM;
+               free_irq(DMA_INT, NULL);
+               goto out;
+       }
+
+       for (i = 0; i < ll_pool.count - 1; i++) {
+               void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll);
+               *addr = (void *)addr + sizeof(struct pnx4008_dma_ll);
+       }
+       *(long *)(ll_pool.vaddr +
+                 (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) =
+           (long)ll_pool.vaddr;
+
+       __raw_writel(1, DMAC_CONFIG);
+
+out:
+       return ret;
+}
+arch_initcall(pnx4008_dma_init);
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
new file mode 100644 (file)
index 0000000..1ab84ce
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * arch/arm/mach-pnx4008/gpio.c
+ *
+ * PNX4008 GPIO driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/gpio.h>
+
+/* register definitions */
+#define PIO_VA_BASE    IO_ADDRESS(PNX4008_PIO_BASE)
+
+#define PIO_INP_STATE  (0x00U)
+#define PIO_OUTP_SET   (0x04U)
+#define PIO_OUTP_CLR   (0x08U)
+#define PIO_OUTP_STATE (0x0CU)
+#define PIO_DRV_SET    (0x10U)
+#define PIO_DRV_CLR    (0x14U)
+#define PIO_DRV_STATE  (0x18U)
+#define PIO_SDINP_STATE        (0x1CU)
+#define PIO_SDOUTP_SET (0x20U)
+#define PIO_SDOUTP_CLR (0x24U)
+#define PIO_MUX_SET    (0x28U)
+#define PIO_MUX_CLR    (0x2CU)
+#define PIO_MUX_STATE  (0x30U)
+
+static inline void gpio_lock(void)
+{
+       local_irq_disable();
+}
+
+static inline void gpio_unlock(void)
+{
+       local_irq_enable();
+}
+
+/* Inline functions */
+static inline int gpio_read_bit(u32 reg, int gpio)
+{
+       u32 bit, val;
+       int ret = -EFAULT;
+
+       if (gpio < 0)
+               goto out;
+
+       bit = GPIO_BIT(gpio);
+       if (bit) {
+               val = __raw_readl(PIO_VA_BASE + reg);
+               ret = (val & bit) ? 1 : 0;
+       }
+out:
+       return ret;
+}
+
+static inline int gpio_set_bit(u32 reg, int gpio)
+{
+       u32 bit, val;
+       int ret = -EFAULT;
+
+       if (gpio < 0)
+               goto out;
+
+       bit = GPIO_BIT(gpio);
+       if (bit) {
+               val = __raw_readl(PIO_VA_BASE + reg);
+               val |= bit;
+               __raw_writel(val, PIO_VA_BASE + reg);
+               ret = 0;
+       }
+out:
+       return ret;
+}
+
+/* Very simple access control, bitmap for allocated/free */
+static unsigned long access_map[4];
+#define INP_INDEX      0
+#define OUTP_INDEX     1
+#define GPIO_INDEX     2
+#define MUX_INDEX      3
+
+/*GPIO to Input Mapping */
+static short gpio_to_inp_map[32] = {
+       -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, 10, 11, 12, 13, 14, 24, -1
+};
+
+/*GPIO to Mux Mapping */
+static short gpio_to_mux_map[32] = {
+       -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, 0, 1, 4, 5, -1
+};
+
+/*Output to Mux Mapping */
+static short outp_to_mux_map[32] = {
+       -1, -1, -1, 6, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, 2, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int pnx4008_gpio_register_pin(unsigned short pin)
+{
+       unsigned long bit = GPIO_BIT(pin);
+       int ret = -EBUSY;       /* Already in use */
+
+       gpio_lock();
+
+       if (GPIO_ISBID(pin)) {
+               if (access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] |= bit;
+
+       } else if (GPIO_ISRAM(pin)) {
+               if (access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] |= bit;
+
+       } else if (GPIO_ISMUX(pin)) {
+               if (access_map[MUX_INDEX] & bit)
+                       goto out;
+               access_map[MUX_INDEX] |= bit;
+
+       } else if (GPIO_ISOUT(pin)) {
+               if (access_map[OUTP_INDEX] & bit)
+                       goto out;
+               access_map[OUTP_INDEX] |= bit;
+
+       } else if (GPIO_ISIN(pin)) {
+               if (access_map[INP_INDEX] & bit)
+                       goto out;
+               access_map[INP_INDEX] |= bit;
+       } else
+               goto out;
+       ret = 0;
+
+out:
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_register_pin);
+
+int pnx4008_gpio_unregister_pin(unsigned short pin)
+{
+       unsigned long bit = GPIO_BIT(pin);
+       int ret = -EFAULT;      /* Not registered */
+
+       gpio_lock();
+
+       if (GPIO_ISBID(pin)) {
+               if (~access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] &= ~bit;
+       } else if (GPIO_ISRAM(pin)) {
+               if (~access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] &= ~bit;
+       } else if (GPIO_ISMUX(pin)) {
+               if (~access_map[MUX_INDEX] & bit)
+                       goto out;
+               access_map[MUX_INDEX] &= ~bit;
+       } else if (GPIO_ISOUT(pin)) {
+               if (~access_map[OUTP_INDEX] & bit)
+                       goto out;
+               access_map[OUTP_INDEX] &= ~bit;
+       } else if (GPIO_ISIN(pin)) {
+               if (~access_map[INP_INDEX] & bit)
+                       goto out;
+               access_map[INP_INDEX] &= ~bit;
+       } else
+               goto out;
+       ret = 0;
+
+out:
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
+
+unsigned long pnx4008_gpio_read_pin(unsigned short pin)
+{
+       unsigned long ret = -EFAULT;
+       int gpio = GPIO_BIT_MASK(pin);
+       gpio_lock();
+       if (GPIO_ISOUT(pin)) {
+               ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+       } else if (GPIO_ISRAM(pin)) {
+               if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
+                       ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
+               }
+       } else if (GPIO_ISBID(pin)) {
+               ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+               if (ret > 0)
+                       ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+               else if (ret == 0)
+                       ret =
+                           gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
+       } else if (GPIO_ISIN(pin)) {
+               ret = gpio_read_bit(PIO_INP_STATE, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin);
+
+/* Write Value to output */
+int pnx4008_gpio_write_pin(unsigned short pin, int output)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISOUT(pin)) {
+               printk( "writing '%x' to '%x'\n",
+                               gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
+               ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
+       } else if (GPIO_ISRAM(pin)) {
+               if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+                       ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
+                                          PIO_SDOUTP_CLR, gpio);
+       } else if (GPIO_ISBID(pin)) {
+               if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+                       ret = gpio_set_bit(output ? PIO_OUTP_SET :
+                                          PIO_OUTP_CLR, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_write_pin);
+
+/* Value = 1 : Set GPIO pin as output */
+/* Value = 0 : Set GPIO pin as input */
+int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+               ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
+
+/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
+int pnx4008_gpio_read_pin_direction(unsigned short pin)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+               ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
+
+/* Value = 1 : Set pin to muxed function  */
+/* Value = 0 : Set pin as GPIO */
+int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin)) {
+               ret =
+                   gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+                                gpio_to_mux_map[gpio]);
+       } else if (GPIO_ISOUT(pin)) {
+               ret =
+                   gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+                                outp_to_mux_map[gpio]);
+       } else if (GPIO_ISMUX(pin)) {
+               ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
+
+/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
+int pnx4008_gpio_read_pin_mux(unsigned short pin)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin)) {
+               ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
+       } else if (GPIO_ISOUT(pin)) {
+               ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
+       } else if (GPIO_ISMUX(pin)) {
+               ret = gpio_read_bit(PIO_MUX_STATE, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c
new file mode 100644 (file)
index 0000000..3a4bcf3
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * arch/arm/mach-pnx4008/irq.c
+ *
+ * PNX4008 IRQ controller driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irq.h>
+
+static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
+
+static void pnx4008_mask_irq(unsigned int irq)
+{
+       __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
+}
+
+static void pnx4008_unmask_irq(unsigned int irq)
+{
+       __raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq));  /* unmask interrupt */
+}
+
+static void pnx4008_mask_ack_irq(unsigned int irq)
+{
+       __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
+       __raw_writel(INTC_BIT(irq), INTC_SR(irq));      /* clear interrupt status */
+}
+
+static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
+{
+       switch (type) {
+       case IRQT_RISING:
+               __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));        /*edge sensitive */
+               __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));        /*rising edge */
+               set_irq_handler(irq, do_edge_IRQ);
+               break;
+       case IRQT_FALLING:
+               __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));        /*edge sensitive */
+               __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));       /*falling edge */
+               set_irq_handler(irq, do_edge_IRQ);
+               break;
+       case IRQT_LOW:
+               __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));       /*level sensitive */
+               __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));       /*low level */
+               set_irq_handler(irq, do_level_IRQ);
+               break;
+       case IRQT_HIGH:
+               __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));       /*level sensitive */
+               __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));        /* high level */
+               set_irq_handler(irq, do_level_IRQ);
+               break;
+
+       /* IRQT_BOTHEDGE is not supported */
+       default:
+               printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
+               return -1;
+       }
+       return 0;
+}
+
+static struct irqchip pnx4008_irq_chip = {
+       .ack = pnx4008_mask_ack_irq,
+       .mask = pnx4008_mask_irq,
+       .unmask = pnx4008_unmask_irq,
+       .set_type = pnx4008_set_irq_type,
+};
+
+void __init pnx4008_init_irq(void)
+{
+       unsigned int i;
+
+       /* configure IRQ's */
+       for (i = 0; i < NR_IRQS; i++) {
+               set_irq_flags(i, IRQF_VALID);
+               set_irq_chip(i, &pnx4008_irq_chip);
+               pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
+       }
+
+       /* configure and enable IRQ 0,1,30,31 (cascade interrupts) */
+       pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
+       pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
+       pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
+       pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
+
+       /* mask all others */
+       __raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
+                       (1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
+               INTC_ER(MAIN_BASE_INT));
+       __raw_writel(0, INTC_ER(SIC1_BASE_INT));
+       __raw_writel(0, INTC_ER(SIC2_BASE_INT));
+}
+
diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c
new file mode 100644 (file)
index 0000000..3649cd3
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * arch/arm/mach-pnx4008/pm.c
+ *
+ * Power Management driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pm.h>
+#include <linux/rtc.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/clock.h>
+
+#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
+
+static void *saved_sram;
+
+static struct clk *pll4_clk;
+
+static inline void pnx4008_standby(void)
+{
+       void (*pnx4008_cpu_standby_ptr) (void);
+
+       local_irq_disable();
+       local_fiq_disable();
+
+       clk_disable(pll4_clk);
+
+       /*saving portion of SRAM to be used by suspend function. */
+       memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
+
+       /*make sure SRAM copy gets physically written into SDRAM.
+          SDRAM will be placed into self-refresh during power down */
+       flush_cache_all();
+
+       /*copy suspend function into SRAM */
+       memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
+
+       /*do suspend */
+       pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
+       pnx4008_cpu_standby_ptr();
+
+       /*restoring portion of SRAM that was used by suspend function */
+       memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
+
+       clk_enable(pll4_clk);
+
+       local_fiq_enable();
+       local_irq_enable();
+}
+
+static inline void pnx4008_suspend(void)
+{
+       void (*pnx4008_cpu_suspend_ptr) (void);
+
+       local_irq_disable();
+       local_fiq_disable();
+
+       clk_disable(pll4_clk);
+
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+       /*saving portion of SRAM to be used by suspend function. */
+       memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
+
+       /*make sure SRAM copy gets physically written into SDRAM.
+          SDRAM will be placed into self-refresh during power down */
+       flush_cache_all();
+
+       /*copy suspend function into SRAM */
+       memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
+
+       /*do suspend */
+       pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
+       pnx4008_cpu_suspend_ptr();
+
+       /*restoring portion of SRAM that was used by suspend function */
+       memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
+
+       clk_enable(pll4_clk);
+
+       local_fiq_enable();
+       local_irq_enable();
+}
+
+static int pnx4008_pm_enter(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               pnx4008_standby();
+               break;
+       case PM_SUSPEND_MEM:
+               pnx4008_suspend();
+               break;
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int pnx4008_pm_prepare(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               break;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+               break;
+
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int pnx4008_pm_finish(suspend_state_t state)
+{
+       return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops pnx4008_pm_ops = {
+       .prepare = pnx4008_pm_prepare,
+       .enter = pnx4008_pm_enter,
+       .finish = pnx4008_pm_finish,
+};
+
+static int __init pnx4008_pm_init(void)
+{
+       u32 sram_size_to_allocate;
+
+       pll4_clk = clk_get(0, "ck_pll4");
+       if (IS_ERR(pll4_clk)) {
+               printk(KERN_ERR
+                      "PM Suspend cannot acquire ARM(PLL4) clock control\n");
+               return PTR_ERR(pll4_clk);
+       }
+
+       if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
+               sram_size_to_allocate = pnx4008_cpu_standby_sz;
+       else
+               sram_size_to_allocate = pnx4008_cpu_suspend_sz;
+
+       saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
+       if (!saved_sram) {
+               printk(KERN_ERR
+                      "PM Suspend: cannot allocate memory to save portion of SRAM\n");
+               clk_put(pll4_clk);
+               return -ENOMEM;
+       }
+
+       pm_set_ops(&pnx4008_pm_ops);
+       return 0;
+}
+
+late_initcall(pnx4008_pm_init);
diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c
new file mode 100644 (file)
index 0000000..95a1b3f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/serial.c
+ *
+ *  PNX4008 UART initialization
+ *
+ *  Copyright: MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/platform.h>
+#include <asm/hardware.h>
+
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/arch/clock.h>
+
+#define UART_3         0
+#define UART_4         1
+#define UART_5         2
+#define UART_6         3
+#define UART_UNKNOWN   (-1)
+
+#define UART3_BASE_VA  IO_ADDRESS(PNX4008_UART3_BASE)
+#define UART4_BASE_VA  IO_ADDRESS(PNX4008_UART4_BASE)
+#define UART5_BASE_VA  IO_ADDRESS(PNX4008_UART5_BASE)
+#define UART6_BASE_VA  IO_ADDRESS(PNX4008_UART6_BASE)
+
+#define UART_FCR_OFFSET                8
+#define UART_FIFO_SIZE         64
+
+void pnx4008_uart_init(void)
+{
+       u32 tmp;
+       int i = UART_FIFO_SIZE;
+
+       __raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET);
+       __raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET);
+
+       /* Send a NULL to fix the UART HW bug */
+       __raw_writel(0x00, UART5_BASE_VA);
+       __raw_writel(0x00, UART3_BASE_VA);
+
+       while (i--) {
+               tmp = __raw_readl(UART5_BASE_VA);
+               tmp = __raw_readl(UART3_BASE_VA);
+       }
+       __raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET);
+       __raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET);
+
+       /* setup wakeup interrupt */
+       start_int_set_rising_edge(SE_U3_RX_INT);
+       start_int_ack(SE_U3_RX_INT);
+       start_int_umask(SE_U3_RX_INT);
+
+       start_int_set_rising_edge(SE_U5_RX_INT);
+       start_int_ack(SE_U5_RX_INT);
+       start_int_umask(SE_U5_RX_INT);
+}
+
diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S
new file mode 100644 (file)
index 0000000..fea1e17
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * linux/arch/arm/mach-pnx4008/sleep.S
+ *
+ * PNX4008 support for STOP mode and SDRAM self-refresh
+ *
+ * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define PWR_CTRL_REG_OFFS 0x44
+
+#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
+#define MPMC_STATUS_REG_OFFS 0x4
+
+               .text
+
+ENTRY(pnx4008_cpu_suspend)
+       @this function should be entered in Direct run mode.
+
+       @ save registers on stack
+       stmfd   sp!, {r0 - r6, lr}
+
+       @ setup Power Manager base address in r4
+       @ and put it's value in r5
+       mov     r4, #(PWRMAN_VA_BASE & 0xff000000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+       ldr     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ setup SDRAM controller base address in r2
+       @ and put it's value in r3
+       mov     r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+       ldr     r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ do save current bit settings in r1
+       mov     r1, r5
+
+       @ set SDRAM self-refresh bit
+       orr     r5, r5, #(1 << 9)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ set SDRAM self-refresh bit latch
+       orr     r5, r5, #(1 << 8)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get into self-refresh mode
+2:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #(1 << 2)
+       beq     2b
+
+       @ to prepare SDRAM to get out of self-refresh mode after wakeup
+       orr     r5, r5, #(1 << 7)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ do enter stop mode
+       orr     r5, r5, #(1 << 0)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       @ sleeping now...
+
+       @ coming out of STOP mode into Direct Run mode
+       @ clear STOP mode and SDRAM self-refresh bits
+       str     r1, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get out self-refresh mode
+3:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #5
+       bne     3b
+
+       @ restore regs and return
+       ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_suspend_sz)
+       .word   . - pnx4008_cpu_suspend
+
+ENTRY(pnx4008_cpu_standby)
+       @ save registers on stack
+       stmfd   sp!, {r0 - r6, lr}
+
+       @ setup Power Manager base address in r4
+       @ and put it's value in r5
+       mov     r4, #(PWRMAN_VA_BASE & 0xff000000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+       ldr     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ setup SDRAM controller base address in r2
+       @ and put it's value in r3
+       mov     r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+       ldr     r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ do save current bit settings in r1
+       mov     r1, r5
+
+       @ set SDRAM self-refresh bit
+       orr     r5, r5, #(1 << 9)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ set SDRAM self-refresh bit latch
+       orr     r5, r5, #(1 << 8)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get into self-refresh mode
+2:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #(1 << 2)
+       beq     2b
+
+       @ set 'get out of self-refresh mode after wakeup' bit
+       orr     r5, r5, #(1 << 7)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       mcr     p15, 0, r0, c7, c0, 4   @ kinda sleeping now...
+
+       @ set SDRAM self-refresh bit latch
+       orr     r5, r5, #(1 << 8)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get out self-refresh mode
+3:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #5
+       bne     3b
+
+       @ restore regs and return
+       ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_standby_sz)
+       .word   . - pnx4008_cpu_standby
+
+ENTRY(pnx4008_cache_clean_invalidate)
+       stmfd   sp!, {r0 - r6, lr}
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
+#else
+1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
+       bne     1b
+#endif
+       ldmfd   sp!, {r0 - r6, pc}
diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c
new file mode 100644 (file)
index 0000000..b986065
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * arch/arm/mach-pnx4008/time.c
+ *
+ * PNX4008 Timers
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/mach/time.h>
+#include <asm/errno.h>
+
+/*! Note: all timers are UPCOUNTING */
+
+/*!
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long pnx4008_gettimeoffset(void)
+{
+       u32 ticks_to_match =
+           __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER);
+       u32 elapsed = LATCH - ticks_to_match;
+       return (elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*!
+ * IRQ handler for the timer
+ */
+static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id,
+                                          struct pt_regs *regs)
+{
+       if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
+
+               write_seqlock(&xtime_lock);
+
+               do {
+                       timer_tick(regs);
+
+                       /*
+                        * this algorithm takes care of possible delay
+                        * for this interrupt handling longer than a normal
+                        * timer period
+                        */
+                       __raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH,
+                                    HSTIM_MATCH0);
+                       __raw_writel(MATCH0_INT, HSTIM_INT);    /* clear interrupt */
+
+                       /*
+                        * The goal is to keep incrementing HSTIM_MATCH0
+                        * register until HSTIM_MATCH0 indicates time after
+                        * what HSTIM_COUNTER indicates.
+                        */
+               } while ((signed)
+                        (__raw_readl(HSTIM_MATCH0) -
+                         __raw_readl(HSTIM_COUNTER)) < 0);
+
+               write_sequnlock(&xtime_lock);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction pnx4008_timer_irq = {
+       .name = "PNX4008 Tick Timer",
+       .flags = IRQF_DISABLED | IRQF_TIMER,
+       .handler = pnx4008_timer_interrupt
+};
+
+/*!
+ * Set up timer and timer interrupt.
+ */
+static __init void pnx4008_setup_timer(void)
+{
+       __raw_writel(RESET_COUNT, MSTIM_CTRL);
+       while (__raw_readl(MSTIM_COUNTER)) ;    /* wait for reset to complete. 100% guarantee event */
+       __raw_writel(0, MSTIM_CTRL);    /* stop the timer */
+       __raw_writel(0, MSTIM_MCTRL);
+
+       __raw_writel(RESET_COUNT, HSTIM_CTRL);
+       while (__raw_readl(HSTIM_COUNTER)) ;    /* wait for reset to complete. 100% guarantee event */
+       __raw_writel(0, HSTIM_CTRL);
+       __raw_writel(0, HSTIM_MCTRL);
+       __raw_writel(0, HSTIM_CCR);
+       __raw_writel(12, HSTIM_PMATCH); /* scale down to 1 MHZ */
+       __raw_writel(LATCH, HSTIM_MATCH0);
+       __raw_writel(MR0_INT, HSTIM_MCTRL);
+
+       setup_irq(HSTIMER_INT, &pnx4008_timer_irq);
+
+       __raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL);        /*start timer, stop when JTAG active */
+}
+
+/* Timer Clock Control in PM register */
+#define TIMCLK_CTRL_REG  IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC))
+#define WATCHDOG_CLK_EN                   1
+#define TIMER_CLK_EN                      2    /* HS and MS timers? */
+
+static u32 timclk_ctrl_reg_save;
+
+void pnx4008_timer_suspend(void)
+{
+       timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG);
+       __raw_writel(0, TIMCLK_CTRL_REG);       /* disable timers */
+}
+
+void pnx4008_timer_resume(void)
+{
+       __raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG);    /* enable timers */
+}
+
+struct sys_timer pnx4008_timer = {
+       .init = pnx4008_setup_timer,
+       .offset = pnx4008_gettimeoffset,
+       .suspend = pnx4008_timer_suspend,
+       .resume = pnx4008_timer_resume,
+};
+
diff --git a/arch/arm/mach-pxa/leds-trizeps4.c b/arch/arm/mach-pxa/leds-trizeps4.c
new file mode 100644 (file)
index 0000000..2271d20
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * linux/arch/arm/mach-pxa/leds-trizeps4.c
+ *
+ *  Author:    Jürgen Schindele
+ *  Created:   20 02, 2006
+ *  Copyright: Jürgen Schindele
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/types.h>
+#include <asm/leds.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/trizeps4.h>
+
+#include "leds.h"
+
+#define LED_STATE_ENABLED      1
+#define LED_STATE_CLAIMED      2
+
+#define SYS_BUSY               0x01
+#define HEARTBEAT              0x02
+#define BLINK                  0x04
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void trizeps4_leds_event(led_event_t evt)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       switch (evt) {
+       case led_start:
+               hw_led_state = 0;
+               pxa_gpio_mode( GPIO_SYS_BUSY_LED  | GPIO_OUT);          /* LED1 */
+               pxa_gpio_mode( GPIO_HEARTBEAT_LED | GPIO_OUT);          /* LED2 */
+               led_state = LED_STATE_ENABLED;
+               break;
+
+       case led_stop:
+               led_state &= ~LED_STATE_ENABLED;
+               break;
+
+       case led_claim:
+               led_state |= LED_STATE_CLAIMED;
+               hw_led_state = 0;
+               break;
+
+       case led_release:
+               led_state &= ~LED_STATE_CLAIMED;
+               hw_led_state = 0;
+               break;
+
+#ifdef CONFIG_LEDS_TIMER
+       case led_timer:
+               hw_led_state ^= HEARTBEAT;
+               break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+       case led_idle_start:
+               hw_led_state &= ~SYS_BUSY;
+               break;
+
+       case led_idle_end:
+               hw_led_state |= SYS_BUSY;
+               break;
+#endif
+
+       case led_halted:
+               break;
+
+       case led_green_on:
+               hw_led_state |= BLINK;
+               break;
+
+       case led_green_off:
+               hw_led_state &= ~BLINK;
+               break;
+
+       case led_amber_on:
+               break;
+
+       case led_amber_off:
+               break;
+
+       case led_red_on:
+               break;
+
+       case led_red_off:
+               break;
+
+       default:
+               break;
+       }
+
+       if  (led_state & LED_STATE_ENABLED) {
+               switch (hw_led_state) {
+                       case 0:
+                               GPSR(GPIO_SYS_BUSY_LED)  |= GPIO_bit(GPIO_SYS_BUSY_LED);
+                               GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED);
+                               break;
+                       case 1:
+                               GPCR(GPIO_SYS_BUSY_LED)  |= GPIO_bit(GPIO_SYS_BUSY_LED);
+                               GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED);
+                               break;
+                       case 2:
+                               GPSR(GPIO_SYS_BUSY_LED)  |= GPIO_bit(GPIO_SYS_BUSY_LED);
+                               GPCR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED);
+                               break;
+                       case 3:
+                               GPCR(GPIO_SYS_BUSY_LED)  |= GPIO_bit(GPIO_SYS_BUSY_LED);
+                               GPCR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED);
+                               break;
+               }
+       }
+       else {
+               /* turn all off */
+               GPSR(GPIO_SYS_BUSY_LED)  |= GPIO_bit(GPIO_SYS_BUSY_LED);
+               GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED);
+       }
+
+       local_irq_restore(flags);
+}
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
new file mode 100644 (file)
index 0000000..7c3007d
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ *  linux/arch/arm/mach-pxa/trizeps4.c
+ *
+ *  Support for the Keith und Koep Trizeps4 Module Platform.
+ *
+ *  Author:    Jürgen Schindele
+ *  Created:   20 02, 2006
+ *  Copyright: Jürgen Schindele
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/trizeps4.h>
+#include <asm/arch/audio.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/ohci.h>
+
+#include "generic.h"
+
+/********************************************************************************************
+ * ONBOARD FLASH
+ ********************************************************************************************/
+static struct mtd_partition trizeps4_partitions[] = {
+       {
+               .name =         "Bootloader",
+               .size =         0x00040000,
+               .offset =       0,
+               .mask_flags =   MTD_WRITEABLE  /* force read-only */
+       },{
+               .name =         "Kernel",
+               .size =         0x00400000,
+               .offset =       0x00040000
+       },{
+               .name =         "Filesystem",
+               .size =         MTDPART_SIZ_FULL,
+               .offset =       0x00440000
+       }
+};
+
+static struct flash_platform_data trizeps4_flash_data[] = {
+       {
+               .map_name       = "cfi_probe",
+               .parts          = trizeps4_partitions,
+               .nr_parts       = ARRAY_SIZE(trizeps4_partitions)
+       }
+};
+
+static struct resource flash_resource = {
+       .start  = PXA_CS0_PHYS,
+       .end    = PXA_CS0_PHYS + SZ_64M - 1,
+       .flags  = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+       .name           = "pxa2xx-flash",
+       .id             = 0,
+       .dev = {
+               .platform_data = &trizeps4_flash_data,
+       },
+       .resource = &flash_resource,
+       .num_resources = 1,
+};
+
+/********************************************************************************************
+ * DAVICOM DM9000 Ethernet
+ ********************************************************************************************/
+static struct resource dm9000_resources[] = {
+       [0] = {
+               .start  = TRIZEPS4_ETH_PHYS+0x300,
+               .end    = TRIZEPS4_ETH_PHYS+0x400-1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = TRIZEPS4_ETH_PHYS+0x8300,
+               .end    = TRIZEPS4_ETH_PHYS+0x8400-1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start  = TRIZEPS4_ETH_IRQ,
+               .end    = TRIZEPS4_ETH_IRQ,
+               .flags  = (IORESOURCE_IRQ | IRQT_RISING),
+       },
+};
+
+static struct platform_device dm9000_device = {
+       .name           = "dm9000",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(dm9000_resources),
+       .resource       = dm9000_resources,
+};
+
+/********************************************************************************************
+ * PXA270 serial ports
+ ********************************************************************************************/
+static struct plat_serial8250_port tri_serial_ports[] = {
+#ifdef CONFIG_SERIAL_PXA
+       /* this uses the own PXA driver */
+       {
+               0,
+       },
+#else
+       /* this uses the generic 8520 driver */
+       [0] = {
+               .membase        = (void *)&FFUART,
+               .irq            = IRQ_FFUART,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM32,
+               .regshift       = 2,
+               .uartclk        = (921600*16),
+       },
+       [1] = {
+               .membase        = (void *)&BTUART,
+               .irq            = IRQ_BTUART,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM32,
+               .regshift       = 2,
+               .uartclk        = (921600*16),
+       },
+       {
+               0,
+       },
+#endif
+};
+
+static struct platform_device uart_devices = {
+       .name           = "serial8250",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = tri_serial_ports,
+       },
+       .num_resources  = 0,
+       .resource       = NULL,
+};
+
+/********************************************************************************************
+ * PXA270 ac97 sound codec
+ ********************************************************************************************/
+static struct platform_device ac97_audio_device = {
+       .name           = "pxa2xx-ac97",
+       .id             = -1,
+};
+
+static struct platform_device * trizeps4_devices[] __initdata = {
+       &flash_device,
+       &uart_devices,
+       &dm9000_device,
+       &ac97_audio_device,
+};
+
+#ifdef CONFIG_MACH_TRIZEPS4_CONXS
+static short trizeps_conxs_bcr;
+
+/* PCCARD power switching supports only 3,3V */
+void board_pcmcia_power(int power)
+{
+       if (power) {
+               /* switch power on, put in reset and enable buffers */
+               trizeps_conxs_bcr |= power;
+               trizeps_conxs_bcr |= ConXS_BCR_CF_RESET;
+               trizeps_conxs_bcr &= ~(ConXS_BCR_CF_BUF_EN);
+               ConXS_BCR = trizeps_conxs_bcr;
+               /* wait a little */
+               udelay(2000);
+               /* take reset away */
+               trizeps_conxs_bcr &= ~(ConXS_BCR_CF_RESET);
+               ConXS_BCR = trizeps_conxs_bcr;
+               udelay(2000);
+       } else {
+               /* put in reset */
+               trizeps_conxs_bcr |= ConXS_BCR_CF_RESET;
+               ConXS_BCR = trizeps_conxs_bcr;
+               udelay(1000);
+               /* switch power off */
+               trizeps_conxs_bcr &= ~(0xf);
+               ConXS_BCR = trizeps_conxs_bcr;
+
+       }
+       pr_debug("%s: o%s 0x%x\n", __FUNCTION__, power ? "n": "ff", trizeps_conxs_bcr);
+}
+
+/* backlight power switching for LCD panel */
+static void board_backlight_power(int on)
+{
+       if (on) {
+               trizeps_conxs_bcr |= ConXS_BCR_L_DISP;
+       } else {
+               trizeps_conxs_bcr &= ~ConXS_BCR_L_DISP;
+       }
+       pr_debug("%s: o%s 0x%x\n", __FUNCTION__, on ? "n" : "ff", trizeps_conxs_bcr);
+       ConXS_BCR = trizeps_conxs_bcr;
+}
+
+/* Powersupply for MMC/SD cardslot */
+static void board_mci_power(struct device *dev, unsigned int vdd)
+{
+       struct pxamci_platform_data* p_d = dev->platform_data;
+
+       if (( 1 << vdd) & p_d->ocr_mask) {
+               pr_debug("%s: on\n", __FUNCTION__);
+               /* FIXME fill in values here */
+       } else {
+               pr_debug("%s: off\n", __FUNCTION__);
+               /* FIXME fill in values here */
+       }
+}
+
+static short trizeps_conxs_ircr;
+
+/* Switch modes and Power for IRDA receiver */
+static void board_irda_mode(struct device *dev, int mode)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (mode & IR_SIRMODE) {
+               /* Slow mode */
+               trizeps_conxs_ircr &= ~ConXS_IRCR_MODE;
+       } else if (mode & IR_FIRMODE) {
+               /* Fast mode */
+               trizeps_conxs_ircr |= ConXS_IRCR_MODE;
+       }
+       if (mode & IR_OFF) {
+               trizeps_conxs_ircr |= ConXS_IRCR_SD;
+       } else {
+               trizeps_conxs_ircr &= ~ConXS_IRCR_SD;
+       }
+       /* FIXME write values to register */
+       local_irq_restore(flags);
+}
+
+#else
+/* for other baseboards define dummies */
+void board_pcmcia_power(int power)     {;}
+#define board_backlight_power          NULL
+#define board_mci_power                        NULL
+#define board_irda_mode                        NULL
+
+#endif         /* CONFIG_MACH_TRIZEPS4_CONXS */
+EXPORT_SYMBOL(board_pcmcia_power);
+
+static int trizeps4_mci_init(struct device *dev, irqreturn_t (*mci_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+       int err;
+       /* setup GPIO for PXA27x MMC controller */
+       pxa_gpio_mode(GPIO32_MMCCLK_MD);
+       pxa_gpio_mode(GPIO112_MMCCMD_MD);
+       pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+       pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+       pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+       pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+
+       pxa_gpio_mode(GPIO_MMC_DET | GPIO_IN);
+
+       err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int,
+                         IRQF_DISABLED | IRQF_TRIGGER_RISING,
+                         "MMC card detect", data);
+       if (err) {
+               printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+               return -1;
+       }
+       return 0;
+}
+
+static void trizeps4_mci_exit(struct device *dev, void *data)
+{
+       free_irq(TRIZEPS4_MMC_IRQ, data);
+}
+
+static struct pxamci_platform_data trizeps4_mci_platform_data = {
+       .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
+       .init           = trizeps4_mci_init,
+       .exit           = trizeps4_mci_exit,
+       .setpower       = board_mci_power,
+};
+
+static struct pxaficp_platform_data trizeps4_ficp_platform_data = {
+       .transceiver_cap  = IR_SIRMODE | IR_FIRMODE | IR_OFF,
+       .transceiver_mode = board_irda_mode,
+};
+
+static int trizeps4_ohci_init(struct device *dev)
+{
+       /* setup Port1 GPIO pin. */
+       pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN);  /* USBHPWR1 */
+       pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
+
+       /* Set the Power Control Polarity Low and Power Sense
+          Polarity Low to active low. */
+       UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+               ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+       return 0;
+}
+
+static void trizeps4_ohci_exit(struct device *dev)
+{
+       ;
+}
+
+static struct pxaohci_platform_data trizeps4_ohci_platform_data = {
+       .port_mode      = PMM_PERPORT_MODE,
+       .init           = trizeps4_ohci_init,
+       .exit           = trizeps4_ohci_exit,
+};
+
+static struct map_desc trizeps4_io_desc[] __initdata = {
+       {       /* ConXS CFSR */
+               .virtual        = TRIZEPS4_CFSR_VIRT,
+               .pfn            = __phys_to_pfn(TRIZEPS4_CFSR_PHYS),
+               .length         = 0x00001000,
+               .type           = MT_DEVICE
+       },
+       {       /* ConXS BCR */
+               .virtual        = TRIZEPS4_BOCR_VIRT,
+               .pfn            = __phys_to_pfn(TRIZEPS4_BOCR_PHYS),
+               .length         = 0x00001000,
+               .type           = MT_DEVICE
+       },
+       {       /* ConXS IRCR */
+               .virtual        = TRIZEPS4_IRCR_VIRT,
+               .pfn            = __phys_to_pfn(TRIZEPS4_IRCR_PHYS),
+               .length         = 0x00001000,
+               .type           = MT_DEVICE
+       },
+       {       /* ConXS DCR */
+               .virtual        = TRIZEPS4_DICR_VIRT,
+               .pfn            = __phys_to_pfn(TRIZEPS4_DICR_PHYS),
+               .length         = 0x00001000,
+               .type           = MT_DEVICE
+       },
+       {       /* ConXS UPSR */
+               .virtual        = TRIZEPS4_UPSR_VIRT,
+               .pfn            = __phys_to_pfn(TRIZEPS4_UPSR_PHYS),
+               .length         = 0x00001000,
+               .type           = MT_DEVICE
+       }
+};
+
+static struct pxafb_mach_info sharp_lcd __initdata = {
+    .pixclock          = 78000,
+    .xres              = 640,
+    .yres              = 480,
+    .bpp               = 8,
+    .hsync_len         = 4,
+    .left_margin       = 4,
+    .right_margin      = 4,
+    .vsync_len         = 2,
+    .upper_margin      = 0,
+    .lower_margin      = 0,
+    .sync              = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+    .cmap_greyscale    = 0,
+    .cmap_inverse      = 0,
+    .cmap_static       = 0,
+    .lccr0             = LCCR0_Color | LCCR0_Pas | LCCR0_Dual,
+    .lccr3             = 0x0340ff02,
+    .pxafb_backlight_power = board_backlight_power,
+};
+
+static void __init trizeps4_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+}
+
+static void __init trizeps4_init(void)
+{
+       platform_add_devices(trizeps4_devices, ARRAY_SIZE(trizeps4_devices));
+
+       set_pxa_fb_info(&sharp_lcd);
+
+       pxa_set_mci_info(&trizeps4_mci_platform_data);
+       pxa_set_ficp_info(&trizeps4_ficp_platform_data);
+       pxa_set_ohci_info(&trizeps4_ohci_platform_data);
+}
+
+static void __init trizeps4_map_io(void)
+{
+       pxa_map_io();
+       iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc));
+
+       /* for DiskOnChip */
+       pxa_gpio_mode(GPIO15_nCS_1_MD);
+
+       /* for off-module PIC on ConXS board */
+       pxa_gpio_mode(GPIO_PIC | GPIO_IN);
+
+       /* UCB1400 irq */
+       pxa_gpio_mode(GPIO_UCB1400 | GPIO_IN);
+
+       /* for DM9000 LAN */
+       pxa_gpio_mode(GPIO78_nCS_2_MD);
+       pxa_gpio_mode(GPIO_DM9000 | GPIO_IN);
+
+       /* for PCMCIA device */
+       pxa_gpio_mode(GPIO_PCD | GPIO_IN);
+       pxa_gpio_mode(GPIO_PRDY | GPIO_IN);
+
+       /* for I2C adapter */
+       pxa_gpio_mode(GPIO117_I2CSCL_MD);
+       pxa_gpio_mode(GPIO118_I2CSDA_MD);
+
+       /* MMC_DET s.o. */
+       pxa_gpio_mode(GPIO_MMC_DET | GPIO_IN);
+
+       /* whats that for ??? */
+       pxa_gpio_mode(GPIO79_nCS_3_MD);
+
+       pxa_gpio_mode( GPIO_SYS_BUSY_LED  | GPIO_OUT);          /* LED1 */
+       pxa_gpio_mode( GPIO_HEARTBEAT_LED | GPIO_OUT);          /* LED2 */
+
+#ifdef CONFIG_MACH_TRIZEPS4_CONXS
+#ifdef CONFIG_IDE_PXA_CF
+       /* if boot direct from compact flash dont disable power */
+       trizeps_conxs_bcr = 0x0009;
+#else
+       /* this is the reset value */
+       trizeps_conxs_bcr = 0x00A0;
+#endif
+       ConXS_BCR = trizeps_conxs_bcr;
+#endif
+
+       PWER  = 0x00000002;
+       PFER  = 0x00000000;
+       PRER  = 0x00000002;
+       PGSR0 = 0x0158C000;
+       PGSR1 = 0x00FF0080;
+       PGSR2 = 0x0001C004;
+       /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
+       PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
+       /* MAINTAINER("Jürgen Schindele") */
+       .phys_io        = 0x40000000,
+       .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+       .boot_params    = TRIZEPS4_SDRAM_BASE + 0x100,
+       .fixup          = trizeps4_fixup,
+       .init_machine   = trizeps4_init,
+       .map_io         = trizeps4_map_io,
+       .init_irq       = pxa_init_irq,
+       .timer          = &pxa_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
new file mode 100644 (file)
index 0000000..3a4ca7f
--- /dev/null
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
+ * loans of SMDK2413 to work with.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include "s3c2410.h"
+#include "s3c2412.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+#include "common-smdk.h"
+
+static struct map_desc smdk2413_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
+       [0] = {
+               .hwport      = 0,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       [1] = {
+               .hwport      = 1,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x03,
+               .ufcon       = 0x51,
+       },
+       /* IR port */
+       [2] = {
+               .hwport      = 2,
+               .flags       = 0,
+               .ucon        = 0x3c5,
+               .ulcon       = 0x43,
+               .ufcon       = 0x51,
+       }
+};
+
+static struct platform_device *smdk2413_devices[] __initdata = {
+       &s3c_device_usb,
+       //&s3c_device_lcd,
+       &s3c_device_wdt,
+       &s3c_device_i2c,
+       &s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2413_board __initdata = {
+       .devices       = smdk2413_devices,
+       .devices_count = ARRAY_SIZE(smdk2413_devices)
+};
+
+static void __init smdk2413_fixup(struct machine_desc *desc,
+                                 struct tag *tags, char **cmdline,
+                                 struct meminfo *mi)
+{
+       if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+               mi->nr_banks=1;
+               mi->bank[0].start = 0x30000000;
+               mi->bank[0].size = SZ_64M;
+               mi->bank[0].node = 0;
+       }
+}
+
+static void __init smdk2413_map_io(void)
+{
+       s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
+       s3c24xx_init_clocks(12000000);
+       s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+       s3c24xx_set_board(&smdk2413_board);
+}
+
+static void __init smdk2413_machine_init(void)
+{
+       smdk_machine_init();
+}
+
+MACHINE_START(S3C2413, "S3C2413")
+       /* Maintainer: Ben Dooks <ben@fluff.org> */
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+
+       .fixup          = smdk2413_fixup,
+       .init_irq       = s3c24xx_init_irq,
+       .map_io         = smdk2413_map_io,
+       .init_machine   = smdk2413_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
+
+MACHINE_START(SMDK2413, "SMDK2413")
+       /* Maintainer: Ben Dooks <ben@fluff.org> */
+       .phys_io        = S3C2410_PA_UART,
+       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+       .boot_params    = S3C2410_SDRAM_PA + 0x100,
+
+       .fixup          = smdk2413_fixup,
+       .init_irq       = s3c24xx_init_irq,
+       .map_io         = smdk2413_map_io,
+       .init_machine   = smdk2413_machine_init,
+       .timer          = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
new file mode 100644 (file)
index 0000000..9971866
--- /dev/null
@@ -0,0 +1,271 @@
+/* linux/arch/arm/mach-s3c2410/clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410,S3C2440,S3C2442 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
+{
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
+
+       clkcon = __raw_readl(S3C2410_CLKCON);
+
+       if (enable)
+               clkcon |= clocks;
+       else
+               clkcon &= ~clocks;
+
+       /* ensure none of the special function bits set */
+       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+
+       __raw_writel(clkcon, S3C2410_CLKCON);
+
+       return 0;
+}
+
+static int s3c2410_upll_enable(struct clk *clk, int enable)
+{
+       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+       unsigned long orig = clkslow;
+
+       if (enable)
+               clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
+       else
+               clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
+
+       __raw_writel(clkslow, S3C2410_CLKSLOW);
+
+       /* if we started the UPLL, then allow to settle */
+
+       if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+               udelay(200);
+
+       return 0;
+}
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "nand",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_NAND,
+       }, {
+               .name           = "sdi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_SDI,
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_ADC,
+       }, {
+               .name           = "i2c",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_IIC,
+       }, {
+               .name           = "iis",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_IIS,
+       }, {
+               .name           = "spi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_SPI,
+       }
+};
+
+static struct clk init_clocks[] = {
+       {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_LCDC,
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_GPIO,
+       }, {
+               .name           = "usb-host",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_USBH,
+       }, {
+               .name           = "usb-device",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_USBD,
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_PWMT,
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_UART0,
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_UART1,
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_UART2,
+       }, {
+               .name           = "rtc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2410_clkcon_enable,
+               .ctrlbit        = S3C2410_CLKCON_RTC,
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_p,
+               .ctrlbit        = 0,
+       }, {
+               .name           = "usb-bus-host",
+               .id             = -1,
+               .parent         = &clk_usb_bus,
+       }, {
+               .name           = "usb-bus-gadget",
+               .id             = -1,
+               .parent         = &clk_usb_bus,
+       },
+};
+
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
+
+int __init s3c2410_baseclk_add(void)
+{
+       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+       unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+       struct clk *clkp;
+       struct clk *xtal;
+       int ret;
+       int ptr;
+
+       clk_upll.enable = s3c2410_upll_enable;
+
+       if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+               printk(KERN_ERR "failed to register usb bus clock\n");
+
+       /* register clocks from clock array */
+
+       clkp = init_clocks;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               /* ensure that we note the clock state */
+
+               clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       /* We must be careful disabling the clocks we are not intending to
+        * be using at boot time, as subsytems such as the LCD which do
+        * their own DMA requests to the bus can cause the system to lockup
+        * if they where in the middle of requesting bus access.
+        *
+        * Disabling the LCD clock if the LCD is active is very dangerous,
+        * and therefore the bootloader should be careful to not enable
+        * the LCD clock if it is not needed.
+       */
+
+       /* install (and disable) the clocks we do not need immediately */
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+
+               s3c2410_clkcon_enable(clkp, 0);
+       }
+
+       /* show the clock-slow value */
+
+       xtal = clk_get(NULL, "xtal");
+
+       printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+              print_mhz(clk_get_rate(xtal) /
+                        ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+              (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+              (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+              (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
+
+       return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c
new file mode 100644 (file)
index 0000000..c95ed3e
--- /dev/null
@@ -0,0 +1,711 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412,S3C2413 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+int s3c2412_clkcon_enable(struct clk *clk, int enable)
+{
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
+
+       clkcon = __raw_readl(S3C2410_CLKCON);
+
+       if (enable)
+               clkcon |= clocks;
+       else
+               clkcon &= ~clocks;
+
+       __raw_writel(clkcon, S3C2410_CLKCON);
+
+       return 0;
+}
+
+static int s3c2412_upll_enable(struct clk *clk, int enable)
+{
+       unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+       unsigned long orig = upllcon;
+
+       if (!enable)
+               upllcon |= S3C2412_PLLCON_OFF;
+       else
+               upllcon &= ~S3C2412_PLLCON_OFF;
+
+       __raw_writel(upllcon, S3C2410_UPLLCON);
+
+       /* allow ~150uS for the PLL to settle and lock */
+
+       if (enable && (orig & S3C2412_PLLCON_OFF))
+               udelay(150);
+
+       return 0;
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+       .name           = "extclk",
+       .id             = -1,
+};
+
+static struct clk clk_erefclk = {
+       .name           = "erefclk",
+       .id             = -1,
+};
+
+static struct clk clk_urefclk = {
+       .name           = "urefclk",
+       .id             = -1,
+};
+
+static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+       if (parent == &clk_urefclk)
+               clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
+       else if (parent == &clk_upll)
+               clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       __raw_writel(clksrc, S3C2412_CLKSRC);
+       return 0;
+}
+
+static struct clk clk_usysclk = {
+       .name           = "usysclk",
+       .id             = -1,
+       .parent         = &clk_xtal,
+       .set_parent     = s3c2412_setparent_usysclk,
+};
+
+static struct clk clk_mrefclk = {
+       .name           = "mrefclk",
+       .parent         = &clk_xtal,
+       .id             = -1,
+};
+
+static struct clk clk_mdivclk = {
+       .name           = "mdivclk",
+       .parent         = &clk_xtal,
+       .id             = -1,
+};
+
+static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+       if (parent == &clk_usysclk)
+               clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
+       else if (parent == &clk_h)
+               clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       __raw_writel(clksrc, S3C2412_CLKSRC);
+       return 0;
+}
+
+static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
+                                             unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       int div;
+
+       if (rate > parent_rate)
+               return parent_rate;
+
+       div = parent_rate / rate;
+       if (div > 2)
+               div = 2;
+
+       return parent_rate / div;
+}
+
+static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+       return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
+}
+
+static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+       rate = s3c2412_roundrate_usbsrc(clk, rate);
+
+       if ((parent_rate / rate) == 2)
+               clkdivn |= S3C2412_CLKDIVN_USB48DIV;
+       else
+               clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
+
+       __raw_writel(clkdivn, S3C2410_CLKDIVN);
+       return 0;
+}
+
+static struct clk clk_usbsrc = {
+       .name           = "usbsrc",
+       .id             = -1,
+       .get_rate       = s3c2412_getrate_usbsrc,
+       .set_rate       = s3c2412_setrate_usbsrc,
+       .round_rate     = s3c2412_roundrate_usbsrc,
+       .set_parent     = s3c2412_setparent_usbsrc,
+};
+
+static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+       if (parent == &clk_mdivclk)
+               clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
+       else if (parent == &clk_upll)
+               clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       __raw_writel(clksrc, S3C2412_CLKSRC);
+       return 0;
+}
+
+static struct clk clk_msysclk = {
+       .name           = "msysclk",
+       .id             = -1,
+       .set_parent     = s3c2412_setparent_msysclk,
+};
+
+/* these next clocks have an divider immediately after them,
+ * so we can register them with their divider and leave out the
+ * intermediate clock stage
+*/
+static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
+                                             unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       int div;
+
+       if (rate > parent_rate)
+               return parent_rate;
+
+       /* note, we remove the +/- 1 calculations as they cancel out */
+
+       div = (rate / parent_rate);
+
+       if (div < 1)
+               div = 1;
+       else if (div > 16)
+               div = 16;
+
+       return parent_rate / div;
+}
+
+static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+       if (parent == &clk_erefclk)
+               clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
+       else if (parent == &clk_mpll)
+               clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       __raw_writel(clksrc, S3C2412_CLKSRC);
+       return 0;
+}
+
+static unsigned long s3c2412_getrate_uart(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+       div &= S3C2412_CLKDIVN_UARTDIV_MASK;
+       div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+       rate = s3c2412_roundrate_clksrc(clk, rate);
+
+       clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
+       clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2410_CLKDIVN);
+       return 0;
+}
+
+static struct clk clk_uart = {
+       .name           = "uartclk",
+       .id             = -1,
+       .get_rate       = s3c2412_getrate_uart,
+       .set_rate       = s3c2412_setrate_uart,
+       .set_parent     = s3c2412_setparent_uart,
+       .round_rate     = s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+       if (parent == &clk_erefclk)
+               clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
+       else if (parent == &clk_mpll)
+               clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       __raw_writel(clksrc, S3C2412_CLKSRC);
+       return 0;
+}
+
+static unsigned long s3c2412_getrate_i2s(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+       div &= S3C2412_CLKDIVN_I2SDIV_MASK;
+       div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+       rate = s3c2412_roundrate_clksrc(clk, rate);
+
+       clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
+       clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2410_CLKDIVN);
+       return 0;
+}
+
+static struct clk clk_i2s = {
+       .name           = "i2sclk",
+       .id             = -1,
+       .get_rate       = s3c2412_getrate_i2s,
+       .set_rate       = s3c2412_setrate_i2s,
+       .set_parent     = s3c2412_setparent_i2s,
+       .round_rate     = s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+       if (parent == &clk_usysclk)
+               clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
+       else if (parent == &clk_h)
+               clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
+       else
+               return -EINVAL;
+
+       clk->parent = parent;
+
+       __raw_writel(clksrc, S3C2412_CLKSRC);
+       return 0;
+}
+static unsigned long s3c2412_getrate_cam(struct clk *clk)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+       div &= S3C2412_CLKDIVN_CAMDIV_MASK;
+       div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+       return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+       rate = s3c2412_roundrate_clksrc(clk, rate);
+
+       clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
+       clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+       __raw_writel(clkdivn, S3C2410_CLKDIVN);
+       return 0;
+}
+
+static struct clk clk_cam = {
+       .name           = "camif-upll", /* same as 2440 name */
+       .id             = -1,
+       .get_rate       = s3c2412_getrate_cam,
+       .set_rate       = s3c2412_setrate_cam,
+       .set_parent     = s3c2412_setparent_cam,
+       .round_rate     = s3c2412_roundrate_clksrc,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "nand",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_NAND,
+       }, {
+               .name           = "sdi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_SDI,
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_ADC,
+       }, {
+               .name           = "i2c",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_IIC,
+       }, {
+               .name           = "iis",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_IIS,
+       }, {
+               .name           = "spi",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_SPI,
+       }
+};
+
+static struct clk init_clocks[] = {
+       {
+               .name           = "dma",
+               .id             = 0,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_DMA0,
+       }, {
+               .name           = "dma",
+               .id             = 1,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_DMA1,
+       }, {
+               .name           = "dma",
+               .id             = 2,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_DMA2,
+       }, {
+               .name           = "dma",
+               .id             = 3,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_DMA3,
+       }, {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_LCDC,
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_GPIO,
+       }, {
+               .name           = "usb-host",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_USBH,
+       }, {
+               .name           = "usb-device",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_USBD,
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_PWMT,
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_UART0,
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_UART1,
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_UART2,
+       }, {
+               .name           = "rtc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_RTC,
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_p,
+               .ctrlbit        = 0,
+       }, {
+               .name           = "usb-bus-gadget",
+               .id             = -1,
+               .parent         = &clk_usb_bus,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_USB_DEV48,
+       }, {
+               .name           = "usb-bus-host",
+               .id             = -1,
+               .parent         = &clk_usb_bus,
+               .enable         = s3c2412_clkcon_enable,
+               .ctrlbit        = S3C2412_CLKCON_USB_HOST48,
+       }
+};
+
+/* clocks to add where we need to check their parentage */
+
+struct clk_init {
+       struct clk      *clk;
+       unsigned int     bit;
+       struct clk      *src_0;
+       struct clk      *src_1;
+};
+
+struct clk_init clks_src[] __initdata = {
+       {
+               .clk    = &clk_usysclk,
+               .bit    = S3C2412_CLKSRC_USBCLK_HCLK,
+               .src_0  = &clk_urefclk,
+               .src_1  = &clk_upll,
+       }, {
+               .clk    = &clk_i2s,
+               .bit    = S3C2412_CLKSRC_I2SCLK_MPLL,
+               .src_0  = &clk_erefclk,
+               .src_1  = &clk_mpll,
+       }, {
+               .clk    = &clk_cam,
+               .bit    = S3C2412_CLKSRC_CAMCLK_HCLK,
+               .src_0  = &clk_usysclk,
+               .src_1  = &clk_h,
+       }, {
+               .clk    = &clk_msysclk,
+               .bit    = S3C2412_CLKSRC_MSYSCLK_MPLL,
+               .src_0  = &clk_mdivclk,
+               .src_1  = &clk_mpll,
+       }, {
+               .clk    = &clk_uart,
+               .bit    = S3C2412_CLKSRC_UARTCLK_MPLL,
+               .src_0  = &clk_erefclk,
+               .src_1  = &clk_mpll,
+       }, {
+               .clk    = &clk_usbsrc,
+               .bit    = S3C2412_CLKSRC_USBCLK_HCLK,
+               .src_0  = &clk_usysclk,
+               .src_1  = &clk_h,
+       },
+};
+
+/* s3c2412_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static void __init s3c2412_clk_initparents(void)
+{
+       unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+       struct clk_init *cip = clks_src;
+       struct clk *src;
+       int ptr;
+       int ret;
+
+       for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
+               ret = s3c24xx_register_clock(cip->clk);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              cip->clk->name, ret);
+               }
+
+               src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
+
+               printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
+               clk_set_parent(cip->clk, src);
+       }
+}
+
+/* clocks to add straight away */
+
+struct clk *clks[] __initdata = {
+       &clk_ext,
+       &clk_usb_bus,
+       &clk_erefclk,
+       &clk_urefclk,
+       &clk_mrefclk,
+};
+
+int __init s3c2412_baseclk_add(void)
+{
+       unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+       struct clk *clkp;
+       int ret;
+       int ptr;
+
+       clk_upll.enable = s3c2412_upll_enable;
+       clk_usb_bus.parent = &clk_usbsrc;
+       clk_usb_bus.rate = 0x0;
+
+       s3c2412_clk_initparents();
+
+       for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+               clkp = clks[ptr];
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       /* ensure usb bus clock is within correct rate of 48MHz */
+
+       if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
+               printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
+
+               /* for the moment, let's use the UPLL, and see if we can
+                * get 48MHz */
+
+               clk_set_parent(&clk_usysclk, &clk_upll);
+               clk_set_parent(&clk_usbsrc, &clk_usysclk);
+               clk_set_rate(&clk_usbsrc, 48*1000*1000);
+       }
+
+       printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+              (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
+              print_mhz(clk_get_rate(&clk_upll)),
+              print_mhz(clk_get_rate(&clk_usb_bus)));
+
+       /* register clocks from clock array */
+
+       clkp = init_clocks;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               /* ensure that we note the clock state */
+
+               clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       /* We must be careful disabling the clocks we are not intending to
+        * be using at boot time, as subsytems such as the LCD which do
+        * their own DMA requests to the bus can cause the system to lockup
+        * if they where in the middle of requesting bus access.
+        *
+        * Disabling the LCD clock if the LCD is active is very dangerous,
+        * and therefore the bootloader should be careful to not enable
+        * the LCD clock if it is not needed.
+       */
+
+       /* install (and disable) the clocks we do not need immediately */
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+
+               s3c2412_clkcon_enable(clkp, 0);
+       }
+
+       return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2410/s3c2412-irq.c
new file mode 100644 (file)
index 0000000..c80ec93
--- /dev/null
@@ -0,0 +1,130 @@
+/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "irq.h"
+
+/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
+ * having them turn up in both the INT* and the EINT* registers. Whilst
+ * both show the status, they both now need to be acked when the IRQs
+ * go off.
+*/
+
+static void
+s3c2412_irq_mask(unsigned int irqno)
+{
+       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+       unsigned long mask;
+
+       mask = __raw_readl(S3C2410_INTMSK);
+       __raw_writel(mask | bitval, S3C2410_INTMSK);
+
+       mask = __raw_readl(S3C2412_EINTMASK);
+       __raw_writel(mask | bitval, S3C2412_EINTMASK);
+}
+
+static inline void
+s3c2412_irq_ack(unsigned int irqno)
+{
+       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+       __raw_writel(bitval, S3C2412_EINTPEND);
+       __raw_writel(bitval, S3C2410_SRCPND);
+       __raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c2412_irq_maskack(unsigned int irqno)
+{
+       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+       unsigned long mask;
+
+       mask = __raw_readl(S3C2410_INTMSK);
+       __raw_writel(mask|bitval, S3C2410_INTMSK);
+
+       mask = __raw_readl(S3C2412_EINTMASK);
+       __raw_writel(mask | bitval, S3C2412_EINTMASK);
+
+       __raw_writel(bitval, S3C2412_EINTPEND);
+       __raw_writel(bitval, S3C2410_SRCPND);
+       __raw_writel(bitval, S3C2410_INTPND);
+}
+
+static void
+s3c2412_irq_unmask(unsigned int irqno)
+{
+       unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+       unsigned long mask;
+
+       mask = __raw_readl(S3C2412_EINTMASK);
+       __raw_writel(mask & ~bitval, S3C2412_EINTMASK);
+
+       mask = __raw_readl(S3C2410_INTMSK);
+       __raw_writel(mask & ~bitval, S3C2410_INTMSK);
+}
+
+static struct irqchip s3c2412_irq_eint0t4 = {
+       .ack       = s3c2412_irq_ack,
+       .mask      = s3c2412_irq_mask,
+       .unmask    = s3c2412_irq_unmask,
+       .set_wake  = s3c_irq_wake,
+       .set_type  = s3c_irqext_type,
+};
+
+static int s3c2412_irq_add(struct sys_device *sysdev)
+{
+       unsigned int irqno;
+
+       for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+               set_irq_chip(irqno, &s3c2412_irq_eint0t4);
+               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       return 0;
+}
+
+static struct sysdev_driver s3c2412_irq_driver = {
+       .add            = s3c2412_irq_add,
+};
+
+static int s3c2412_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_irq_driver);
+}
+
+arch_initcall(s3c2412_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
new file mode 100644 (file)
index 0000000..2d163f7
--- /dev/null
@@ -0,0 +1,224 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.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.
+ *
+ * Modifications:
+ *     16-May-2003 BJD  Created initial version
+ *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
+ *     05-Sep-2003 BJD  Moved to kernel v2.6
+ *     18-Jan-2004 BJD  Added serial port configuration
+ *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
+ *     28-Sep-2004 BJD  Updates for new serial port bits
+ *     04-Nov-2004 BJD  Updated UART configuration process
+ *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
+ *     13-Aug-2005 DA   Removed UART from initial I/O mappings
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/proc-fns.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/idle.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-power.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2412.h"
+#include "cpu.h"
+#include "devs.h"
+#include "clock.h"
+#include "pm.h"
+
+#ifndef CONFIG_CPU_S3C2412_ONLY
+void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+#endif
+
+/* Initial IO mappings */
+
+static struct map_desc s3c2412_iodesc[] __initdata = {
+       IODESC_ENT(CLKPWR),
+       IODESC_ENT(LCD),
+       IODESC_ENT(TIMER),
+       IODESC_ENT(ADC),
+       IODESC_ENT(WATCHDOG),
+};
+
+/* uart registration process */
+
+void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
+
+       /* rename devices that are s3c2412/s3c2413 specific */
+       s3c_device_sdi.name  = "s3c2412-sdi";
+       s3c_device_nand.name = "s3c2412-nand";
+}
+
+/* s3c2412_idle
+ *
+ * use the standard idle call by ensuring the idle mode
+ * in power config, then issuing the idle co-processor
+ * instruction
+*/
+
+static void s3c2412_idle(void)
+{
+       unsigned long tmp;
+
+       /* ensure our idle mode is to go to idle */
+
+       tmp = __raw_readl(S3C2412_PWRCFG);
+       tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK;
+       tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE;
+       __raw_writel(tmp, S3C2412_PWRCFG);
+
+       cpu_do_idle();
+}
+
+/* s3c2412_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+*/
+
+void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
+{
+       /* move base of IO */
+
+       s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+
+       /* set our idle function */
+
+       s3c24xx_idle = s3c2412_idle;
+
+       /* register our io-tables */
+
+       iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
+       iotable_init(mach_desc, mach_size);
+}
+
+void __init s3c2412_init_clocks(int xtal)
+{
+       unsigned long tmp;
+       unsigned long fclk;
+       unsigned long hclk;
+       unsigned long pclk;
+
+       /* now we've got our machine bits initialised, work out what
+        * clocks we've got */
+
+       fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
+
+       tmp = __raw_readl(S3C2410_CLKDIVN);
+
+       /* work out clock scalings */
+
+       hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+       hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
+       pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+
+       /* print brieft summary of clocks, etc */
+
+       printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+              print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+       /* initialise the clocks here, to allow other things like the
+        * console to use them
+        */
+
+       s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+       s3c2412_baseclk_add();
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2412 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+#ifdef CONFIG_PM
+static struct sleep_save s3c2412_sleep[] = {
+       SAVE_ITEM(S3C2412_DSC0),
+       SAVE_ITEM(S3C2412_DSC1),
+       SAVE_ITEM(S3C2413_GPJDAT),
+       SAVE_ITEM(S3C2413_GPJCON),
+       SAVE_ITEM(S3C2413_GPJUP),
+
+       /* save the sleep configuration anyway, just in case these
+        * get damaged during wakeup */
+
+       SAVE_ITEM(S3C2412_GPBSLPCON),
+       SAVE_ITEM(S3C2412_GPCSLPCON),
+       SAVE_ITEM(S3C2412_GPDSLPCON),
+       SAVE_ITEM(S3C2412_GPESLPCON),
+       SAVE_ITEM(S3C2412_GPFSLPCON),
+       SAVE_ITEM(S3C2412_GPGSLPCON),
+       SAVE_ITEM(S3C2412_GPHSLPCON),
+       SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
+{
+       s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+       return 0;
+}
+
+static int s3c2412_resume(struct sys_device *dev)
+{
+       s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+       return 0;
+}
+
+#else
+#define s3c2412_suspend NULL
+#define s3c2412_resume  NULL
+#endif
+
+struct sysdev_class s3c2412_sysclass = {
+       set_kset_name("s3c2412-core"),
+       .suspend        = s3c2412_suspend,
+       .resume         = s3c2412_resume
+};
+
+static int __init s3c2412_core_init(void)
+{
+       return sysdev_class_register(&s3c2412_sysclass);
+}
+
+core_initcall(s3c2412_core_init);
+
+static struct sys_device s3c2412_sysdev = {
+       .cls            = &s3c2412_sysclass,
+};
+
+int __init s3c2412_init(void)
+{
+       printk("S3C2412: Initialising architecture\n");
+
+       return sysdev_register(&s3c2412_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h
new file mode 100644 (file)
index 0000000..c6e5603
--- /dev/null
@@ -0,0 +1,29 @@
+/* arch/arm/mach-s3c2410/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/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c
new file mode 100644 (file)
index 0000000..d9f54b5
--- /dev/null
@@ -0,0 +1,171 @@
+/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2442 Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* S3C2442 extended clock support */
+
+static unsigned long s3c2442_camif_upll_round(struct clk *clk,
+                                             unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       int div;
+
+       if (rate > parent_rate)
+               return parent_rate;
+
+       div = parent_rate / rate;
+
+       if (div == 3)
+               return parent_rate / 3;
+
+       /* note, we remove the +/- 1 calculations for the divisor */
+
+       div /= 2;
+
+       if (div < 1)
+               div = 1;
+       else if (div > 16)
+               div = 16;
+
+       return parent_rate / (div * 2);
+}
+
+static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+       rate = s3c2442_camif_upll_round(clk, rate);
+
+       camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
+
+       if (rate == parent_rate) {
+               camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
+       } else if ((parent_rate / rate) == 3) {
+               camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+               camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
+       } else {
+               camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
+               camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+               camdivn |= (((parent_rate / rate) / 2) - 1);
+       }
+
+       __raw_writel(camdivn, S3C2440_CAMDIVN);
+
+       return 0;
+}
+
+/* Extra S3C2442 clocks */
+
+static struct clk s3c2442_clk_cam = {
+       .name           = "camif",
+       .id             = -1,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2442_clk_cam_upll = {
+       .name           = "camif-upll",
+       .id             = -1,
+       .set_rate       = s3c2442_camif_upll_setrate,
+       .round_rate     = s3c2442_camif_upll_round,
+};
+
+static int s3c2442_clk_add(struct sys_device *sysdev)
+{
+       unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+       unsigned long clkdivn;
+       struct clk *clk_h;
+       struct clk *clk_p;
+       struct clk *clk_upll;
+
+       printk("S3C2442: Clock Support, DVS %s\n",
+              (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+       clk_p = clk_get(NULL, "pclk");
+       clk_h = clk_get(NULL, "hclk");
+       clk_upll = clk_get(NULL, "upll");
+
+       if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
+               printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
+               return -EINVAL;
+       }
+
+       /* check rate of UPLL, and if it is near 96MHz, then change
+        * to using half the UPLL rate for the system */
+
+       if (clk_get_rate(clk_upll) > (94 * MHZ)) {
+               clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+
+               mutex_lock(&clocks_mutex);
+
+               clkdivn = __raw_readl(S3C2410_CLKDIVN);
+               clkdivn |= S3C2440_CLKDIVN_UCLK;
+               __raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+               mutex_unlock(&clocks_mutex);
+       }
+
+       s3c2442_clk_cam.parent = clk_h;
+       s3c2442_clk_cam_upll.parent = clk_upll;
+
+       s3c24xx_register_clock(&s3c2442_clk_cam);
+       s3c24xx_register_clock(&s3c2442_clk_cam_upll);
+
+       clk_disable(&s3c2442_clk_cam);
+
+       return 0;
+}
+
+static struct sysdev_driver s3c2442_clk_driver = {
+       .add    = s3c2442_clk_add,
+};
+
+static __init int s3c2442_clk_init(void)
+{
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c
new file mode 100644 (file)
index 0000000..debae24
--- /dev/null
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2442.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct sys_device s3c2442_sysdev = {
+       .cls            = &s3c2442_sysclass,
+};
+
+int __init s3c2442_init(void)
+{
+       printk("S3C2442: Initialising architecture\n");
+
+       return sysdev_register(&s3c2442_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h
new file mode 100644 (file)
index 0000000..0ae37d2
--- /dev/null
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s3c2410/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/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
new file mode 100644 (file)
index 0000000..44c5aff
--- /dev/null
@@ -0,0 +1,142 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "pm.h"
+#include "irq.h"
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+                             struct irqdesc *desc,
+                             struct pt_regs *regs)
+{
+       unsigned int subsrc, submsk;
+       struct irqdesc *mydesc;
+
+       /* read the current pending interrupts, and the mask
+        * for what it is available */
+
+       subsrc = __raw_readl(S3C2410_SUBSRCPND);
+       submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+       subsrc &= ~submsk;
+       subsrc >>= 11;
+       subsrc &= 3;
+
+       if (subsrc != 0) {
+               if (subsrc & 1) {
+                       mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+                       desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
+               }
+               if (subsrc & 2) {
+                       mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+                       desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
+               }
+       }
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irqchip s3c_irq_cam = {
+       .mask       = s3c_irq_cam_mask,
+       .unmask     = s3c_irq_cam_unmask,
+       .ack        = s3c_irq_cam_ack,
+};
+
+static int s3c244x_irq_add(struct sys_device *sysdev)
+{
+       unsigned int irqno;
+
+       set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
+       set_irq_handler(IRQ_NFCON, do_level_IRQ);
+       set_irq_flags(IRQ_NFCON, IRQF_VALID);
+
+       /* add chained handler for camera */
+
+       set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
+       set_irq_handler(IRQ_CAM, do_level_IRQ);
+       set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+
+       for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
+               set_irq_chip(irqno, &s3c_irq_cam);
+               set_irq_handler(irqno, do_level_IRQ);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
+       return 0;
+}
+
+static struct sysdev_driver s3c2440_irq_driver = {
+       .add    = s3c244x_irq_add,
+};
+
+static int s3c2440_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
+}
+
+arch_initcall(s3c2440_irq_init);
+
+static struct sysdev_driver s3c2442_irq_driver = {
+       .add    = s3c244x_irq_add,
+};
+
+static int s3c2442_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver);
+}
+
+arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c
new file mode 100644 (file)
index 0000000..9a22582
--- /dev/null
@@ -0,0 +1,185 @@
+/* linux/arch/arm/mach-s3c2410/s3c244x.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 and S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2410.h"
+#include "s3c2440.h"
+#include "s3c244x.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct map_desc s3c244x_iodesc[] __initdata = {
+       IODESC_ENT(CLKPWR),
+       IODESC_ENT(TIMER),
+       IODESC_ENT(WATCHDOG),
+       IODESC_ENT(LCD),
+       IODESC_ENT(ADC),
+       IODESC_ENT(USBHOST),
+};
+
+/* uart initialisation */
+
+void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
+{
+       /* register our io-tables */
+
+       iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
+       iotable_init(mach_desc, size);
+
+       /* rename any peripherals used differing from the s3c2410 */
+
+       s3c_device_i2c.name  = "s3c2440-i2c";
+       s3c_device_nand.name = "s3c2440-nand";
+       s3c_device_usbgadget.name = "s3c2440-usbgadget";
+}
+
+void __init s3c244x_init_clocks(int xtal)
+{
+       unsigned long clkdiv;
+       unsigned long camdiv;
+       unsigned long hclk, fclk, pclk;
+       int hdiv = 1;
+
+       /* now we've got our machine bits initialised, work out what
+        * clocks we've got */
+
+       fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
+
+       clkdiv = __raw_readl(S3C2410_CLKDIVN);
+       camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+       /* work out clock scalings */
+
+       switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+       case S3C2440_CLKDIVN_HDIVN_1:
+               hdiv = 1;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_2:
+               hdiv = 2;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_4_8:
+               hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_3_6:
+               hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+               break;
+       }
+
+       hclk = fclk / hdiv;
+       pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+
+       /* print brief summary of clocks, etc */
+
+       printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+              print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+       /* initialise the clocks here, to allow other things like the
+        * console to use them, and to add new ones after the initialisation
+        */
+
+       s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+       s3c2410_baseclk_add();
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save s3c244x_sleep[] = {
+       SAVE_ITEM(S3C2440_DSC0),
+       SAVE_ITEM(S3C2440_DSC1),
+       SAVE_ITEM(S3C2440_GPJDAT),
+       SAVE_ITEM(S3C2440_GPJCON),
+       SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
+{
+       s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+       return 0;
+}
+
+static int s3c244x_resume(struct sys_device *dev)
+{
+       s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+       return 0;
+}
+
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
+
+struct sysdev_class s3c2440_sysclass = {
+       set_kset_name("s3c2440-core"),
+       .suspend        = s3c244x_suspend,
+       .resume         = s3c244x_resume
+};
+
+struct sysdev_class s3c2442_sysclass = {
+       set_kset_name("s3c2442-core"),
+       .suspend        = s3c244x_suspend,
+       .resume         = s3c244x_resume
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2440_core_init(void)
+{
+       return sysdev_class_register(&s3c2440_sysclass);
+}
+
+core_initcall(s3c2440_core_init);
+
+static int __init s3c2442_core_init(void)
+{
+       return sysdev_class_register(&s3c2442_sysclass);
+}
+
+core_initcall(s3c2442_core_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h
new file mode 100644 (file)
index 0000000..3e7f5f7
--- /dev/null
@@ -0,0 +1,25 @@
+/* arch/arm/mach-s3c2410/s3c2440.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and 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.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#define s3c244x_map_io NULL
+#endif
diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c
new file mode 100644 (file)
index 0000000..62066f3
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  linux/arch/arm/mm/iomap.c
+ *
+ * Map IO port and PCI memory spaces so that {read,write}[bwl] can
+ * be used to access this memory.
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+
+#ifdef __io
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       return __io(port);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif
+
+#ifdef CONFIG_PCI
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len   = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       if ((unsigned long)addr >= VMALLOC_START &&
+           (unsigned long)addr < VMALLOC_END)
+               iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+#endif
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
new file mode 100644 (file)
index 0000000..1464ed8
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  linux/arch/arm/mm/nommu.c
+ *
+ * ARM uCLinux supporting functions.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/page.h>
+
+void flush_dcache_page(struct page *page)
+{
+       __cpuc_flush_dcache_page(page_address(page));
+}
+EXPORT_SYMBOL(flush_dcache_page);
+
+void __iomem *__ioremap_pfn(unsigned long pfn, unsigned long offset,
+                           size_t size, unsigned long flags)
+{
+       if (pfn >= (0x100000000ULL >> PAGE_SHIFT))
+               return NULL;
+       return (void __iomem *) (offset + (pfn << PAGE_SHIFT));
+}
+EXPORT_SYMBOL(__ioremap_pfn);
+
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+                       unsigned long flags)
+{
+       return (void __iomem *)phys_addr;
+}
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(__iounmap);
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
new file mode 100644 (file)
index 0000000..17647a5
--- /dev/null
@@ -0,0 +1,67 @@
+#include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/hpet.h>
+#include <linux/init.h>
+
+#include <asm/hpet.h>
+#include <asm/io.h>
+
+#define HPET_MASK      CLOCKSOURCE_MASK(32)
+#define HPET_SHIFT     22
+
+/* FSEC = 10^-15 NSEC = 10^-9 */
+#define FSEC_PER_NSEC  1000000
+
+static void *hpet_ptr;
+
+static cycle_t read_hpet(void)
+{
+       return (cycle_t)readl(hpet_ptr);
+}
+
+static struct clocksource clocksource_hpet = {
+       .name           = "hpet",
+       .rating         = 250,
+       .read           = read_hpet,
+       .mask           = HPET_MASK,
+       .mult           = 0, /* set below */
+       .shift          = HPET_SHIFT,
+       .is_continuous  = 1,
+};
+
+static int __init init_hpet_clocksource(void)
+{
+       unsigned long hpet_period;
+       void __iomem* hpet_base;
+       u64 tmp;
+
+       if (!is_hpet_enabled())
+               return -ENODEV;
+
+       /* calculate the hpet address: */
+       hpet_base =
+               (void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+       hpet_ptr = hpet_base + HPET_COUNTER;
+
+       /* calculate the frequency: */
+       hpet_period = readl(hpet_base + HPET_PERIOD);
+
+       /*
+        * hpet period is in femto seconds per cycle
+        * so we need to convert this to ns/cyc units
+        * aproximated by mult/2^shift
+        *
+        *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
+        *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
+        *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
+        *  (fsec/cyc << shift)/1000000 = mult
+        *  (hpet_period << shift)/FSEC_PER_NSEC = mult
+        */
+       tmp = (u64)hpet_period << HPET_SHIFT;
+       do_div(tmp, FSEC_PER_NSEC);
+       clocksource_hpet.mult = (u32)tmp;
+
+       return clocksource_register(&clocksource_hpet);
+}
+
+module_init(init_hpet_clocksource);
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
new file mode 100644 (file)
index 0000000..477b24d
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * i8253.c  8253/PIT functions
+ *
+ */
+#include <linux/clocksource.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/sysdev.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/smp.h>
+#include <asm/delay.h>
+#include <asm/i8253.h>
+#include <asm/io.h>
+
+#include "io_ports.h"
+
+DEFINE_SPINLOCK(i8253_lock);
+EXPORT_SYMBOL(i8253_lock);
+
+void setup_pit_timer(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&i8253_lock, flags);
+       outb_p(0x34,PIT_MODE);          /* binary, mode 2, LSB/MSB, ch 0 */
+       udelay(10);
+       outb_p(LATCH & 0xff , PIT_CH0); /* LSB */
+       udelay(10);
+       outb(LATCH >> 8 , PIT_CH0);     /* MSB */
+       spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+/*
+ * Since the PIT overflows every tick, its not very useful
+ * to just read by itself. So use jiffies to emulate a free
+ * running counter:
+ */
+static cycle_t pit_read(void)
+{
+       unsigned long flags;
+       int count;
+       u32 jifs;
+       static int old_count;
+       static u32 old_jifs;
+
+       spin_lock_irqsave(&i8253_lock, flags);
+        /*
+        * Although our caller may have the read side of xtime_lock,
+        * this is now a seqlock, and we are cheating in this routine
+        * by having side effects on state that we cannot undo if
+        * there is a collision on the seqlock and our caller has to
+        * retry.  (Namely, old_jifs and old_count.)  So we must treat
+        * jiffies as volatile despite the lock.  We read jiffies
+        * before latching the timer count to guarantee that although
+        * the jiffies value might be older than the count (that is,
+        * the counter may underflow between the last point where
+        * jiffies was incremented and the point where we latch the
+        * count), it cannot be newer.
+        */
+       jifs = jiffies;
+       outb_p(0x00, PIT_MODE); /* latch the count ASAP */
+       count = inb_p(PIT_CH0); /* read the latched count */
+       count |= inb_p(PIT_CH0) << 8;
+
+       /* VIA686a test code... reset the latch if count > max + 1 */
+       if (count > LATCH) {
+               outb_p(0x34, PIT_MODE);
+               outb_p(LATCH & 0xff, PIT_CH0);
+               outb(LATCH >> 8, PIT_CH0);
+               count = LATCH - 1;
+       }
+
+       /*
+        * It's possible for count to appear to go the wrong way for a
+        * couple of reasons:
+        *
+        *  1. The timer counter underflows, but we haven't handled the
+        *     resulting interrupt and incremented jiffies yet.
+        *  2. Hardware problem with the timer, not giving us continuous time,
+        *     the counter does small "jumps" upwards on some Pentium systems,
+        *     (see c't 95/10 page 335 for Neptun bug.)
+        *
+        * Previous attempts to handle these cases intelligently were
+        * buggy, so we just do the simple thing now.
+        */
+       if (count > old_count && jifs == old_jifs) {
+               count = old_count;
+       }
+       old_count = count;
+       old_jifs = jifs;
+
+       spin_unlock_irqrestore(&i8253_lock, flags);
+
+       count = (LATCH - 1) - count;
+
+       return (cycle_t)(jifs * LATCH) + count;
+}
+
+static struct clocksource clocksource_pit = {
+       .name   = "pit",
+       .rating = 110,
+       .read   = pit_read,
+       .mask   = CLOCKSOURCE_MASK(32),
+       .mult   = 0,
+       .shift  = 20,
+};
+
+static int __init init_pit_clocksource(void)
+{
+       if (num_possible_cpus() > 4) /* PIT does not scale! */
+               return 0;
+
+       clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
+       return clocksource_register(&clocksource_pit);
+}
+module_init(init_pit_clocksource);
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
new file mode 100644 (file)
index 0000000..650b746
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * This code largely moved from arch/i386/kernel/timer/timer_tsc.c
+ * which was originally moved from arch/i386/kernel/time.c.
+ * See comments there for proper credits.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/workqueue.h>
+#include <linux/cpufreq.h>
+#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+
+#include <asm/delay.h>
+#include <asm/tsc.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+
+#include "mach_timer.h"
+
+/*
+ * On some systems the TSC frequency does not
+ * change with the cpu frequency. So we need
+ * an extra value to store the TSC freq
+ */
+unsigned int tsc_khz;
+
+int tsc_disable __cpuinitdata = 0;
+
+#ifdef CONFIG_X86_TSC
+static int __init tsc_setup(char *str)
+{
+       printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, "
+                               "cannot disable TSC.\n");
+       return 1;
+}
+#else
+/*
+ * disable flag for tsc. Takes effect by clearing the TSC cpu flag
+ * in cpu/common.c
+ */
+static int __init tsc_setup(char *str)
+{
+       tsc_disable = 1;
+
+       return 1;
+}
+#endif
+
+__setup("notsc", tsc_setup);
+
+/*
+ * code to mark and check if the TSC is unstable
+ * due to cpufreq or due to unsynced TSCs
+ */
+static int tsc_unstable;
+
+static inline int check_tsc_unstable(void)
+{
+       return tsc_unstable;
+}
+
+void mark_tsc_unstable(void)
+{
+       tsc_unstable = 1;
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
+/* Accellerators for sched_clock()
+ * convert from cycles(64bits) => nanoseconds (64bits)
+ *  basic equation:
+ *             ns = cycles / (freq / ns_per_sec)
+ *             ns = cycles * (ns_per_sec / freq)
+ *             ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *             ns = cycles * (10^6 / cpu_khz)
+ *
+ *     Then we use scaling math (suggested by george@mvista.com) to get:
+ *             ns = cycles * (10^6 * SC / cpu_khz) / SC
+ *             ns = cycles * cyc2ns_scale / SC
+ *
+ *     And since SC is a constant power of two, we can convert the div
+ *  into a shift.
+ *
+ *  We can use khz divisor instead of mhz to keep a better percision, since
+ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
+ *  (mathieu.desnoyers@polymtl.ca)
+ *
+ *                     -johnstul@us.ibm.com "math is hard, lets go shopping!"
+ */
+static unsigned long cyc2ns_scale __read_mostly;
+
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+{
+       cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+}
+
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+       return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+}
+
+#ifndef CONFIG_XEN
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+       unsigned long long this_offset;
+
+       /*
+        * in the NUMA case we dont use the TSC as they are not
+        * synchronized across all CPUs.
+        */
+#ifndef CONFIG_NUMA
+       if (!cpu_khz || check_tsc_unstable())
+#endif
+               /* no locking but a rare wrong value is not a big deal */
+               return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
+
+       /* read the Time Stamp Counter: */
+       rdtscll(this_offset);
+
+       /* return the value in ns */
+       return cycles_2_ns(this_offset);
+}
+#endif
+
+static unsigned long calculate_cpu_khz(void)
+{
+       unsigned long long start, end;
+       unsigned long count;
+       u64 delta64;
+       int i;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       /* run 3 times to ensure the cache is warm */
+       for (i = 0; i < 3; i++) {
+               mach_prepare_counter();
+               rdtscll(start);
+               mach_countup(&count);
+               rdtscll(end);
+       }
+       /*
+        * Error: ECTCNEVERSET
+        * The CTC wasn't reliable: we got a hit on the very first read,
+        * or the CPU was so fast/slow that the quotient wouldn't fit in
+        * 32 bits..
+        */
+       if (count <= 1)
+               goto err;
+
+       delta64 = end - start;
+
+       /* cpu freq too fast: */
+       if (delta64 > (1ULL<<32))
+               goto err;
+
+       /* cpu freq too slow: */
+       if (delta64 <= CALIBRATE_TIME_MSEC)
+               goto err;
+
+       delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */
+       do_div(delta64,CALIBRATE_TIME_MSEC);
+
+       local_irq_restore(flags);
+       return (unsigned long)delta64;
+err:
+       local_irq_restore(flags);
+       return 0;
+}
+
+int recalibrate_cpu_khz(void)
+{
+#ifndef CONFIG_SMP
+       unsigned long cpu_khz_old = cpu_khz;
+
+       if (cpu_has_tsc) {
+               cpu_khz = calculate_cpu_khz();
+               tsc_khz = cpu_khz;
+               cpu_data[0].loops_per_jiffy =
+                       cpufreq_scale(cpu_data[0].loops_per_jiffy,
+                                       cpu_khz_old, cpu_khz);
+               return 0;
+       } else
+               return -ENODEV;
+#else
+       return -ENODEV;
+#endif
+}
+
+EXPORT_SYMBOL(recalibrate_cpu_khz);
+
+void tsc_init(void)
+{
+       if (!cpu_has_tsc || tsc_disable)
+               return;
+
+       cpu_khz = calculate_cpu_khz();
+       tsc_khz = cpu_khz;
+
+       if (!cpu_khz)
+               return;
+
+       printk("Detected %lu.%03lu MHz processor.\n",
+                               (unsigned long)cpu_khz / 1000,
+                               (unsigned long)cpu_khz % 1000);
+
+       set_cyc2ns_scale(cpu_khz);
+       use_tsc_delay();
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+static unsigned int cpufreq_delayed_issched = 0;
+static unsigned int cpufreq_init = 0;
+static struct work_struct cpufreq_delayed_get_work;
+
+static void handle_cpufreq_delayed_get(void *v)
+{
+       unsigned int cpu;
+
+       for_each_online_cpu(cpu)
+               cpufreq_get(cpu);
+
+       cpufreq_delayed_issched = 0;
+}
+
+/*
+ * if we notice cpufreq oddness, schedule a call to cpufreq_get() as it tries
+ * to verify the CPU frequency the timing core thinks the CPU is running
+ * at is still correct.
+ */
+static inline void cpufreq_delayed_get(void)
+{
+       if (cpufreq_init && !cpufreq_delayed_issched) {
+               cpufreq_delayed_issched = 1;
+               printk(KERN_DEBUG "Checking if CPU frequency changed.\n");
+               schedule_work(&cpufreq_delayed_get_work);
+       }
+}
+
+/*
+ * if the CPU frequency is scaled, TSC-based delays will need a different
+ * loops_per_jiffy value to function properly.
+ */
+static unsigned int ref_freq = 0;
+static unsigned long loops_per_jiffy_ref = 0;
+static unsigned long cpu_khz_ref = 0;
+
+static int
+time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
+{
+       struct cpufreq_freqs *freq = data;
+
+       if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
+               write_seqlock_irq(&xtime_lock);
+
+       if (!ref_freq) {
+               if (!freq->old){
+                       ref_freq = freq->new;
+                       goto end;
+               }
+               ref_freq = freq->old;
+               loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
+               cpu_khz_ref = cpu_khz;
+       }
+
+       if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+           (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+           (val == CPUFREQ_RESUMECHANGE)) {
+               if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+                       cpu_data[freq->cpu].loops_per_jiffy =
+                               cpufreq_scale(loops_per_jiffy_ref,
+                                               ref_freq, freq->new);
+
+               if (cpu_khz) {
+
+                       if (num_online_cpus() == 1)
+                               cpu_khz = cpufreq_scale(cpu_khz_ref,
+                                               ref_freq, freq->new);
+                       if (!(freq->flags & CPUFREQ_CONST_LOOPS)) {
+                               tsc_khz = cpu_khz;
+                               set_cyc2ns_scale(cpu_khz);
+                               /*
+                                * TSC based sched_clock turns
+                                * to junk w/ cpufreq
+                                */
+                               mark_tsc_unstable();
+                       }
+               }
+       }
+end:
+       if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
+               write_sequnlock_irq(&xtime_lock);
+
+       return 0;
+}
+
+static struct notifier_block time_cpufreq_notifier_block = {
+       .notifier_call  = time_cpufreq_notifier
+};
+
+static int __init cpufreq_tsc(void)
+{
+       int ret;
+
+       INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+       ret = cpufreq_register_notifier(&time_cpufreq_notifier_block,
+                                       CPUFREQ_TRANSITION_NOTIFIER);
+       if (!ret)
+               cpufreq_init = 1;
+
+       return ret;
+}
+
+core_initcall(cpufreq_tsc);
+
+#endif
+
+/* clock source code */
+
+static unsigned long current_tsc_khz = 0;
+static int tsc_update_callback(void);
+
+static cycle_t read_tsc(void)
+{
+       cycle_t ret;
+
+       rdtscll(ret);
+
+       return ret;
+}
+
+static struct clocksource clocksource_tsc = {
+       .name                   = "tsc",
+       .rating                 = 300,
+       .read                   = read_tsc,
+       .mask                   = CLOCKSOURCE_MASK(64),
+       .mult                   = 0, /* to be set */
+       .shift                  = 22,
+       .update_callback        = tsc_update_callback,
+       .is_continuous          = 1,
+};
+
+static int tsc_update_callback(void)
+{
+       int change = 0;
+
+       /* check to see if we should switch to the safe clocksource: */
+       if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
+               clocksource_tsc.rating = 50;
+               clocksource_reselect();
+               change = 1;
+       }
+
+       /* only update if tsc_khz has changed: */
+       if (current_tsc_khz != tsc_khz) {
+               current_tsc_khz = tsc_khz;
+               clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+                                                       clocksource_tsc.shift);
+               change = 1;
+       }
+
+       return change;
+}
+
+static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
+{
+       printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
+                      d->ident);
+       mark_tsc_unstable();
+       return 0;
+}
+
+/* List of systems that have known TSC problems */
+static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
+       {
+        .callback = dmi_mark_tsc_unstable,
+        .ident = "IBM Thinkpad 380XD",
+        .matches = {
+                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+                    DMI_MATCH(DMI_BOARD_NAME, "2635FA0"),
+                    },
+        },
+        {}
+};
+
+#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
+static struct timer_list verify_tsc_freq_timer;
+
+/* XXX - Probably should add locking */
+static void verify_tsc_freq(unsigned long unused)
+{
+       static u64 last_tsc;
+       static unsigned long last_jiffies;
+
+       u64 now_tsc, interval_tsc;
+       unsigned long now_jiffies, interval_jiffies;
+
+
+       if (check_tsc_unstable())
+               return;
+
+       rdtscll(now_tsc);
+       now_jiffies = jiffies;
+
+       if (!last_jiffies) {
+               goto out;
+       }
+
+       interval_jiffies = now_jiffies - last_jiffies;
+       interval_tsc = now_tsc - last_tsc;
+       interval_tsc *= HZ;
+       do_div(interval_tsc, cpu_khz*1000);
+
+       if (interval_tsc < (interval_jiffies * 3 / 4)) {
+               printk("TSC appears to be running slowly. "
+                       "Marking it as unstable\n");
+               mark_tsc_unstable();
+               return;
+       }
+
+out:
+       last_tsc = now_tsc;
+       last_jiffies = now_jiffies;
+       /* set us up to go off on the next interval: */
+       mod_timer(&verify_tsc_freq_timer,
+               jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
+}
+
+/*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+static __init int unsynchronized_tsc(void)
+{
+       /*
+        * Intel systems are normally all synchronized.
+        * Exceptions must mark TSC as unstable:
+        */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+               return 0;
+
+       /* assume multi socket systems are not synchronized: */
+       return num_possible_cpus() > 1;
+}
+
+static int __init init_tsc_clocksource(void)
+{
+
+       if (cpu_has_tsc && tsc_khz && !tsc_disable) {
+               /* check blacklist */
+               dmi_check_system(bad_tsc_dmi_table);
+
+               if (unsynchronized_tsc()) /* mark unstable if unsynced */
+                       mark_tsc_unstable();
+               current_tsc_khz = tsc_khz;
+               clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+                                                       clocksource_tsc.shift);
+               /* lower the rating if we already know its unstable: */
+               if (check_tsc_unstable())
+                       clocksource_tsc.rating = 50;
+
+               init_timer(&verify_tsc_freq_timer);
+               verify_tsc_freq_timer.function = verify_tsc_freq;
+               verify_tsc_freq_timer.expires =
+                       jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL);
+               add_timer(&verify_tsc_freq_timer);
+
+               return clocksource_register(&clocksource_tsc);
+       }
+
+       return 0;
+}
+
+module_init(init_tsc_clocksource);
diff --git a/arch/i386/mach-xen/irqflags.c b/arch/i386/mach-xen/irqflags.c
new file mode 100644 (file)
index 0000000..c990ca5
--- /dev/null
@@ -0,0 +1,99 @@
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <asm/irqflags.h>
+#include <asm/hypervisor.h>
+
+/* interrupt control.. */
+
+/* 
+ * The use of 'barrier' in the following reflects their use as local-lock
+ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+ * critical operations are executed. All critical operations must complete
+ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+ * includes these barriers, for example.
+ */
+
+unsigned long __raw_local_save_flags(void)
+{
+       struct vcpu_info *_vcpu;
+       unsigned long flags;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       flags = _vcpu->evtchn_upcall_mask;
+       preempt_enable();
+
+       return flags;
+}
+EXPORT_SYMBOL(__raw_local_save_flags);
+
+void raw_local_irq_restore(unsigned long flags)
+{
+       struct vcpu_info *_vcpu;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       if ((_vcpu->evtchn_upcall_mask = flags) == 0) {
+               barrier(); /* unmask then check (avoid races) */
+               if (unlikely(_vcpu->evtchn_upcall_pending))
+                       force_evtchn_callback();
+               preempt_enable();
+       } else
+               preempt_enable_no_resched();
+
+}
+EXPORT_SYMBOL(raw_local_irq_restore);
+
+void raw_local_irq_disable(void)
+{
+       struct vcpu_info *_vcpu;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       _vcpu->evtchn_upcall_mask = 1;
+       preempt_enable_no_resched();
+}
+EXPORT_SYMBOL(raw_local_irq_disable);
+
+void raw_local_irq_enable(void)
+{
+       struct vcpu_info *_vcpu;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       _vcpu->evtchn_upcall_mask = 0;
+       barrier(); /* unmask then check (avoid races) */
+       if (unlikely(_vcpu->evtchn_upcall_pending))
+               force_evtchn_callback();
+       preempt_enable();
+}
+EXPORT_SYMBOL(raw_local_irq_enable);
+
+/* Cannot use preempt_enable() here as we would recurse in preempt_sched(). */
+int raw_irqs_disabled(void)
+{
+       struct vcpu_info *_vcpu;
+       int disabled;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       disabled = (_vcpu->evtchn_upcall_mask != 0);
+       preempt_enable_no_resched();
+       return disabled;
+}
+EXPORT_SYMBOL(raw_irqs_disabled);
+
+unsigned long __raw_local_irq_save(void)
+{
+       struct vcpu_info *_vcpu;
+       unsigned long flags;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       flags = _vcpu->evtchn_upcall_mask;
+       _vcpu->evtchn_upcall_mask = 1;
+       preempt_enable_no_resched();
+
+       return flags;
+}
+EXPORT_SYMBOL(__raw_local_irq_save);
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
new file mode 100644 (file)
index 0000000..92d7d0c
--- /dev/null
@@ -0,0 +1,37 @@
+#include <asm-i386/unistd.h>
+
+unsigned ia32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned ia32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned ia32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned ia32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int ia32_classify_syscall(unsigned syscall)
+{
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 1;
+       }
+}
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
new file mode 100644 (file)
index 0000000..0468255
--- /dev/null
@@ -0,0 +1,64 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_IA32_SUPPORT
+       extern int ia32_classify_syscall(unsigned);
+       if (abi == AUDIT_ARCH_I386)
+               return ia32_classify_syscall(syscall);
+#endif
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_execve:
+               return 5;
+       default:
+               return 0;
+       }
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_IA32_SUPPORT
+       extern __u32 ia32_dir_class[];
+       extern __u32 ia32_write_class[];
+       extern __u32 ia32_read_class[];
+       extern __u32 ia32_chattr_class[];
+       audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
+       audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+#endif
+       audit_register_class(AUDIT_CLASS_WRITE, write_class);
+       audit_register_class(AUDIT_CLASS_READ, read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+       return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile
new file mode 100644 (file)
index 0000000..c2b4f94
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for Xen components
+#
+
+obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \
+        hypervisor.o pci-dma-xen.o util.o
+
+pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o
diff --git a/arch/ia64/xen/drivers/README b/arch/ia64/xen/drivers/README
new file mode 100644 (file)
index 0000000..33aecaa
--- /dev/null
@@ -0,0 +1,2 @@
+This is a temporary location for source/Makefiles that need to be
+patched/reworked in drivers/xen to work with xenlinux/ia64.
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
new file mode 100644 (file)
index 0000000..3996865
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Support routines for Xen hypercalls
+ *
+ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+/* To clear vpsr.ic, vpsr.i needs to be cleared first */
+#define XEN_CLEAR_PSR_IC                               \
+       mov r14=1;                                      \
+       movl r15=XSI_PSR_I_ADDR;                        \
+       movl r2=XSI_PSR_IC;                             \
+       ;;                                              \
+       ld8 r15=[r15];                                  \
+       ld4 r3=[r2];                                    \
+       ;;                                              \
+       ld1 r16=[r15];                                  \
+       ;;                                              \
+       st1 [r15]=r14;                                  \
+       st4 [r2]=r0;                                    \
+       ;;
+
+/* First restore vpsr.ic, and then vpsr.i */
+#define XEN_RESTORE_PSR_IC                             \
+       st4 [r2]=r3;                                    \
+       st1 [r15]=r16;                                  \
+       ;;
+
+GLOBAL_ENTRY(xen_get_ivr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=cr.ivr;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_IVR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_get_ivr)
+
+GLOBAL_ENTRY(xen_get_tpr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=cr.tpr;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_TPR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_get_tpr)
+
+GLOBAL_ENTRY(xen_set_tpr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov cr.tpr=r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_TPR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_set_tpr)
+
+GLOBAL_ENTRY(xen_eoi)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov cr.eoi=r0;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_EOI
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_eoi)
+
+GLOBAL_ENTRY(xen_thash)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   thash r8=r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_THASH
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_thash)
+
+GLOBAL_ENTRY(xen_set_itm)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov cr.itm=r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_ITM
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_set_itm)
+
+GLOBAL_ENTRY(xen_ptcga)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   ptc.ga r32,r33;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       mov r9=r33
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_PTC_GA
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_ptcga)
+
+GLOBAL_ENTRY(xen_get_rr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=rr[r32];;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_RR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_get_rr)
+
+GLOBAL_ENTRY(xen_set_rr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov rr[r32]=r33;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       mov r9=r33
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_RR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_set_rr)
+
+GLOBAL_ENTRY(xen_set_kr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.ne p7,p0=r8,r0;;
+(p7)   br.cond.spnt.few 1f;
+       ;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar0=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar1=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar2=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar3=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar4=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar5=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar6=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar7=r9
+(p7)   br.ret.sptk.many rp;;
+
+1:     mov r8=r32
+       mov r9=r33
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_KR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_set_kr)
+
+GLOBAL_ENTRY(xen_fc)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   fc r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_FC
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_fc)
+
+GLOBAL_ENTRY(xen_get_cpuid)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=cpuid[r32];;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_CPUID
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_get_cpuid)
+
+GLOBAL_ENTRY(xen_get_pmd)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=pmd[r32];;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_PMD
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_get_pmd)
+
+#ifdef CONFIG_IA32_SUPPORT
+GLOBAL_ENTRY(xen_get_eflag)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=ar24;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_EFLAG
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_get_eflag)
+       
+// some bits aren't set if pl!=0, see SDM vol1 3.1.8
+GLOBAL_ENTRY(xen_set_eflag)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov ar24=r32
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_EFLAG
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_set_eflag)
+#endif
+
+GLOBAL_ENTRY(xen_send_ipi)
+        mov r14=r32
+        mov r15=r33
+        mov r2=0x400
+        break 0x1000
+        ;;
+        br.ret.sptk.many rp
+        ;;
+END(xen_send_ipi)
+
+#ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT
+// Those are vdso specialized.
+// In fsys mode, call, ret can't be used.
+GLOBAL_ENTRY(xen_rsm_be_i)
+       ld8 r22=[r22]
+       ;; 
+       st1 [r22]=r20
+       st4 [r23]=r0
+       XEN_HYPER_RSM_BE
+       st4 [r23]=r20
+       brl.cond.sptk   .vdso_rsm_be_i_ret
+       ;; 
+END(xen_rsm_be_i)
+
+GLOBAL_ENTRY(xen_get_psr)
+       mov r31=r8
+       mov r25=IA64_PSR_IC
+       st4 [r23]=r0
+       XEN_HYPER_GET_PSR
+       ;; 
+       st4 [r23]=r20
+       or r29=r8,r25 // vpsr.ic was cleared for hyperprivop
+       mov r8=r31
+       brl.cond.sptk   .vdso_get_psr_ret
+       ;; 
+END(xen_get_psr)
+
+       // see xen_ssm_i() in privop.h
+       // r22 = &vcpu->evtchn_mask
+       // r23 = &vpsr.ic
+       // r24 = &vcpu->pending_interruption
+       // r25 = tmp
+       // r31 = tmp
+       // p11 = tmp
+       // p14 = tmp
+#define XEN_SET_PSR_I                  \
+       ld4 r31=[r22];                  \
+       ld4 r25=[r24];                  \
+       ;;                              \
+       st4 [r22]=r0;                   \
+       cmp.ne.unc p14,p0=r0,r31;       \
+       ;;                              \
+(p14)  cmp.ne.unc p11,p0=r0,r25;       \
+       ;;                              \
+(p11)  st4 [r22]=r20;                  \
+(p11)  st4 [r23]=r0;                   \
+(p11)  XEN_HYPER_SSM_I;
+               
+GLOBAL_ENTRY(xen_ssm_i_0)
+       XEN_SET_PSR_I
+       brl.cond.sptk   .vdso_ssm_i_0_ret
+       ;; 
+END(xen_ssm_i_0)
+
+GLOBAL_ENTRY(xen_ssm_i_1)
+       XEN_SET_PSR_I
+       brl.cond.sptk   .vdso_ssm_i_1_ret
+       ;; 
+END(xen_ssm_i_1)
+#endif
diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c
new file mode 100644 (file)
index 0000000..0b28604
--- /dev/null
@@ -0,0 +1,833 @@
+/******************************************************************************
+ * include/asm-ia64/shadow.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+//#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <asm/page.h>
+#include <asm/hypervisor.h>
+#include <asm/hypercall.h>
+#include <xen/interface/memory.h>
+#include <xen/balloon.h>
+
+shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)XSI_BASE;
+EXPORT_SYMBOL(HYPERVISOR_shared_info);
+
+start_info_t *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);
+
+int running_on_xen;
+EXPORT_SYMBOL(running_on_xen);
+
+//XXX xen/ia64 copy_from_guest() is broken.
+//    This is a temporal work around until it is fixed.
+//    used by balloon.c netfront.c
+
+// get_xen_guest_handle is defined only when __XEN_TOOLS__ is defined
+// if the definition in arch-ia64.h is changed, this must be updated.
+#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
+
+int
+ia64_xenmem_reservation_op(unsigned long op,
+                          struct xen_memory_reservation* reservation__)
+{
+       struct xen_memory_reservation reservation = *reservation__;
+       unsigned long* frame_list;
+       unsigned long nr_extents = reservation__->nr_extents;
+       int ret = 0;
+       get_xen_guest_handle(frame_list, reservation__->extent_start);
+
+       BUG_ON(op != XENMEM_increase_reservation &&
+              op != XENMEM_decrease_reservation &&
+              op != XENMEM_populate_physmap);
+
+       while (nr_extents > 0) {
+               int tmp_ret;
+               volatile unsigned long dummy;
+
+               set_xen_guest_handle(reservation.extent_start, frame_list);
+               reservation.nr_extents = nr_extents;
+
+               dummy = frame_list[0];// re-install tlb entry before hypercall
+               tmp_ret = ____HYPERVISOR_memory_op(op, &reservation);
+               if (tmp_ret < 0) {
+                       if (ret == 0) {
+                               ret = tmp_ret;
+                       }
+                       break;
+               }
+               if (tmp_ret == 0) {
+                       //XXX dirty work around for skbuff_ctor()
+                       //    of a non-privileged domain, 
+                       if ((op == XENMEM_increase_reservation ||
+                            op == XENMEM_populate_physmap) &&
+                           !is_initial_xendomain() &&
+                           reservation.extent_order > 0)
+                               return ret;
+               }
+               frame_list += tmp_ret;
+               nr_extents -= tmp_ret;
+               ret += tmp_ret;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(ia64_xenmem_reservation_op);
+
+//XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear()
+// move those to lib/contiguous_bitmap?
+//XXX discontigmem/sparsemem
+
+/*
+ * Bitmap is indexed by page number. If bit is set, the page is part of a
+ * xen_create_contiguous_region() area of memory.
+ */
+unsigned long *contiguous_bitmap;
+
+void
+contiguous_bitmap_init(unsigned long end_pfn)
+{
+       unsigned long size = (end_pfn + 2 * BITS_PER_LONG) >> 3;
+       contiguous_bitmap = alloc_bootmem_low_pages(size);
+       BUG_ON(!contiguous_bitmap);
+       memset(contiguous_bitmap, 0, size);
+}
+
+#if 0
+int
+contiguous_bitmap_test(void* p)
+{
+       return test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap);
+}
+#endif
+
+static void contiguous_bitmap_set(
+       unsigned long first_page, unsigned long nr_pages)
+{
+       unsigned long start_off, end_off, curr_idx, end_idx;
+
+       curr_idx  = first_page / BITS_PER_LONG;
+       start_off = first_page & (BITS_PER_LONG-1);
+       end_idx   = (first_page + nr_pages) / BITS_PER_LONG;
+       end_off   = (first_page + nr_pages) & (BITS_PER_LONG-1);
+
+       if (curr_idx == end_idx) {
+               contiguous_bitmap[curr_idx] |=
+                       ((1UL<<end_off)-1) & -(1UL<<start_off);
+       } else {
+               contiguous_bitmap[curr_idx] |= -(1UL<<start_off);
+               while ( ++curr_idx < end_idx )
+                       contiguous_bitmap[curr_idx] = ~0UL;
+               contiguous_bitmap[curr_idx] |= (1UL<<end_off)-1;
+       }
+}
+
+static void contiguous_bitmap_clear(
+       unsigned long first_page, unsigned long nr_pages)
+{
+       unsigned long start_off, end_off, curr_idx, end_idx;
+
+       curr_idx  = first_page / BITS_PER_LONG;
+       start_off = first_page & (BITS_PER_LONG-1);
+       end_idx   = (first_page + nr_pages) / BITS_PER_LONG;
+       end_off   = (first_page + nr_pages) & (BITS_PER_LONG-1);
+
+       if (curr_idx == end_idx) {
+               contiguous_bitmap[curr_idx] &=
+                       -(1UL<<end_off) | ((1UL<<start_off)-1);
+       } else {
+               contiguous_bitmap[curr_idx] &= (1UL<<start_off)-1;
+               while ( ++curr_idx != end_idx )
+                       contiguous_bitmap[curr_idx] = 0;
+               contiguous_bitmap[curr_idx] &= -(1UL<<end_off);
+       }
+}
+
+// __xen_create_contiguous_region(), __xen_destroy_contiguous_region()
+// are based on i386 xen_create_contiguous_region(),
+// xen_destroy_contiguous_region()
+
+/* Protected by balloon_lock. */
+#define MAX_CONTIG_ORDER 7
+static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
+
+/* Ensure multi-page extents are contiguous in machine memory. */
+int
+__xen_create_contiguous_region(unsigned long vstart,
+                              unsigned int order, unsigned int address_bits)
+{
+       unsigned long error = 0;
+       unsigned long gphys = __pa(vstart);
+       unsigned long start_gpfn = gphys >> PAGE_SHIFT;
+       unsigned long num_gpfn = 1 << order;
+       unsigned long i;
+       unsigned long flags;
+
+       unsigned long *in_frames = discontig_frames, out_frame;
+       int success;
+       struct xen_memory_exchange exchange = {
+               .in = {
+                       .nr_extents   = num_gpfn,
+                       .extent_order = 0,
+                       .domid        = DOMID_SELF
+               },
+               .out = {
+                        .nr_extents   = 1,
+                        .extent_order = order,
+                        .address_bits = address_bits,
+                        .domid        = DOMID_SELF
+                },
+               .nr_exchanged = 0
+       };
+
+       if (unlikely(order > MAX_CONTIG_ORDER))
+               return -ENOMEM;
+       
+       set_xen_guest_handle(exchange.in.extent_start, in_frames);
+       set_xen_guest_handle(exchange.out.extent_start, &out_frame);
+
+       scrub_pages(vstart, num_gpfn);
+
+       balloon_lock(flags);
+
+       /* Get a new contiguous memory extent. */
+       for (i = 0; i < num_gpfn; i++) {
+               in_frames[i] = start_gpfn + i;
+       }
+       out_frame = start_gpfn;
+       error = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+       success = (exchange.nr_exchanged == num_gpfn);
+       BUG_ON(!success && ((exchange.nr_exchanged != 0) || (error == 0)));
+       BUG_ON(success && (error != 0));
+       if (unlikely(error == -ENOSYS)) {
+               /* Compatibility when XENMEM_exchange is unsupported. */
+               error = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                            &exchange.in);
+               BUG_ON(error != num_gpfn);
+               error = HYPERVISOR_memory_op(XENMEM_populate_physmap,
+                                            &exchange.out);
+               if (error != 1) {
+                       /* Couldn't get special memory: fall back to normal. */
+                       for (i = 0; i < num_gpfn; i++) {
+                               in_frames[i] = start_gpfn + i;
+                       }
+                       error = HYPERVISOR_memory_op(XENMEM_populate_physmap,
+                                                    &exchange.in);
+                       BUG_ON(error != num_gpfn);
+                       success = 0;
+               } else
+                       success = 1;
+       }
+       if (success)
+               contiguous_bitmap_set(start_gpfn, num_gpfn);
+#if 0
+       if (success) {
+               unsigned long mfn;
+               unsigned long mfn_prev = ~0UL;
+               for (i = 0; i < num_gpfn; i++) {
+                       mfn = pfn_to_mfn_for_dma(start_gpfn + i);
+                       if (mfn_prev != ~0UL && mfn != mfn_prev + 1) {
+                               xprintk("\n");
+                               xprintk("%s:%d order %d "
+                                       "start 0x%lx bus 0x%lx "
+                                       "machine 0x%lx\n",
+                                       __func__, __LINE__, order,
+                                       vstart, virt_to_bus((void*)vstart),
+                                       phys_to_machine_for_dma(gphys));
+                               xprintk("mfn: ");
+                               for (i = 0; i < num_gpfn; i++) {
+                                       mfn = pfn_to_mfn_for_dma(
+                                               start_gpfn + i);
+                                       xprintk("0x%lx ", mfn);
+                               }
+                               xprintk("\n");
+                               break;
+                       }
+                       mfn_prev = mfn;
+               }
+       }
+#endif
+       balloon_unlock(flags);
+       return success? 0: -ENOMEM;
+}
+
+void
+__xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+       unsigned long flags;
+       unsigned long error = 0;
+       unsigned long start_gpfn = __pa(vstart) >> PAGE_SHIFT;
+       unsigned long num_gpfn = 1UL << order;
+       unsigned long i;
+
+       unsigned long *out_frames = discontig_frames, in_frame;
+       int            success;
+       struct xen_memory_exchange exchange = {
+               .in = {
+                       .nr_extents   = 1,
+                       .extent_order = order,
+                       .domid        = DOMID_SELF
+               },
+               .out = {
+                        .nr_extents   = num_gpfn,
+                        .extent_order = 0,
+                        .address_bits = 0,
+                        .domid        = DOMID_SELF
+                },
+               .nr_exchanged = 0
+        };
+       
+
+       if (!test_bit(start_gpfn, contiguous_bitmap))
+               return;
+
+       if (unlikely(order > MAX_CONTIG_ORDER))
+               return;
+
+       set_xen_guest_handle(exchange.in.extent_start, &in_frame);
+       set_xen_guest_handle(exchange.out.extent_start, out_frames);
+
+       scrub_pages(vstart, num_gpfn);
+
+       balloon_lock(flags);
+
+       contiguous_bitmap_clear(start_gpfn, num_gpfn);
+
+        /* Do the exchange for non-contiguous MFNs. */
+       in_frame = start_gpfn;
+       for (i = 0; i < num_gpfn; i++) {
+               out_frames[i] = start_gpfn + i;
+       }
+       error = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+       success = (exchange.nr_exchanged == 1);
+       BUG_ON(!success && ((exchange.nr_exchanged != 0) || (error == 0)));
+       BUG_ON(success && (error != 0));
+       if (unlikely(error == -ENOSYS)) {
+                /* Compatibility when XENMEM_exchange is unsupported. */
+               error = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                            &exchange.in);
+               BUG_ON(error != 1);
+
+               error = HYPERVISOR_memory_op(XENMEM_populate_physmap,
+                                            &exchange.out);
+               BUG_ON(error != num_gpfn);
+       }
+       balloon_unlock(flags);
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+// grant table hack
+// cmd: GNTTABOP_xxx
+
+#include <linux/mm.h>
+#include <xen/interface/xen.h>
+#include <xen/gnttab.h>
+
+static void
+gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
+{
+       uint32_t flags;
+
+       flags = uop->flags;
+
+       if (flags & GNTMAP_host_map) {
+               if (flags & GNTMAP_application_map) {
+                       xprintd("GNTMAP_application_map is not supported yet: flags 0x%x\n", flags);
+                       BUG();
+               }
+               if (flags & GNTMAP_contains_pte) {
+                       xprintd("GNTMAP_contains_pte is not supported yet flags 0x%x\n", flags);
+                       BUG();
+               }
+       } else if (flags & GNTMAP_device_map) {
+               xprintd("GNTMAP_device_map is not supported yet 0x%x\n", flags);
+               BUG();//XXX not yet. actually this flag is not used.
+       } else {
+               BUG();
+       }
+}
+
+int
+HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
+{
+       __u64 va1, va2, pa1, pa2;
+
+       if (cmd == GNTTABOP_map_grant_ref) {
+               unsigned int i;
+               for (i = 0; i < count; i++) {
+                       gnttab_map_grant_ref_pre(
+                               (struct gnttab_map_grant_ref*)uop + i);
+               }
+       }
+       va1 = (__u64)uop & PAGE_MASK;
+       pa1 = pa2 = 0;
+       if ((REGION_NUMBER(va1) == 5) &&
+           ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) {
+               pa1 = ia64_tpa(va1);
+               if (cmd <= GNTTABOP_transfer) {
+                       static uint32_t uop_size[GNTTABOP_transfer + 1] = {
+                               sizeof(struct gnttab_map_grant_ref),
+                               sizeof(struct gnttab_unmap_grant_ref),
+                               sizeof(struct gnttab_setup_table),
+                               sizeof(struct gnttab_dump_table),
+                               sizeof(struct gnttab_transfer),
+                       };
+                       va2 = (__u64)uop + (uop_size[cmd] * count) - 1;
+                       va2 &= PAGE_MASK;
+                       if (va1 != va2) {
+                               /* maximum size of uop is 2pages */
+                               BUG_ON(va2 > va1 + PAGE_SIZE);
+                               pa2 = ia64_tpa(va2);
+                       }
+               }
+       }
+       return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2);
+}
+EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
+
+///////////////////////////////////////////////////////////////////////////
+// PageForeign(), SetPageForeign(), ClearPageForeign()
+
+struct address_space xen_ia64_foreign_dummy_mapping;
+EXPORT_SYMBOL(xen_ia64_foreign_dummy_mapping);
+
+///////////////////////////////////////////////////////////////////////////
+// foreign mapping
+#include <linux/efi.h>
+#include <asm/meminit.h> // for IA64_GRANULE_SIZE, GRANULEROUND{UP,DOWN}()
+
+static unsigned long privcmd_resource_min = 0;
+// Xen/ia64 currently can handle pseudo physical address bits up to
+// (PAGE_SHIFT * 3)
+static unsigned long privcmd_resource_max = GRANULEROUNDDOWN((1UL << (PAGE_SHIFT * 3)) - 1);
+static unsigned long privcmd_resource_align = IA64_GRANULE_SIZE;
+
+static unsigned long
+md_end_addr(const efi_memory_desc_t *md)
+{
+       return md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+}
+
+#define XEN_IA64_PRIVCMD_LEAST_GAP_SIZE        (1024 * 1024 * 1024UL)
+static int
+xen_ia64_privcmd_check_size(unsigned long start, unsigned long end)
+{
+       return (start < end &&
+               (end - start) > XEN_IA64_PRIVCMD_LEAST_GAP_SIZE);
+}
+
+static int __init
+xen_ia64_privcmd_init(void)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       u64 efi_desc_size;
+       efi_memory_desc_t *md;
+       unsigned long tmp_min;
+       unsigned long tmp_max;
+       unsigned long gap_size;
+       unsigned long prev_end;
+
+       if (!is_running_on_xen())
+               return -1;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       // at first check the used highest address
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               // nothing
+       }
+       md = p - efi_desc_size;
+       privcmd_resource_min = GRANULEROUNDUP(md_end_addr(md));
+       if (xen_ia64_privcmd_check_size(privcmd_resource_min,
+                                       privcmd_resource_max)) {
+               goto out;
+       }
+
+       // the used highest address is too large. try to find the largest gap.
+       tmp_min = privcmd_resource_max;
+       tmp_max = 0;
+       gap_size = 0;
+       prev_end = 0;
+       for (p = efi_map_start;
+            p < efi_map_end - efi_desc_size;
+            p += efi_desc_size) {
+               unsigned long end;
+               efi_memory_desc_t* next;
+               unsigned long next_start;
+
+               md = p;
+               end = md_end_addr(md);
+               if (end > privcmd_resource_max) {
+                       break;
+               }
+               if (end < prev_end) {
+                       // work around. 
+                       // Xen may pass incompletely sorted memory
+                       // descriptors like
+                       // [x, x + length]
+                       // [x, x]
+                       // this order should be reversed.
+                       continue;
+               }
+               next = p + efi_desc_size;
+               next_start = next->phys_addr;
+               if (next_start > privcmd_resource_max) {
+                       next_start = privcmd_resource_max;
+               }
+               if (end < next_start && gap_size < (next_start - end)) {
+                       tmp_min = end;
+                       tmp_max = next_start;
+                       gap_size = tmp_max - tmp_min;
+               }
+               prev_end = end;
+       }
+
+       privcmd_resource_min = GRANULEROUNDUP(tmp_min);
+       if (xen_ia64_privcmd_check_size(privcmd_resource_min, tmp_max)) {
+               privcmd_resource_max = tmp_max;
+               goto out;
+       }
+
+       privcmd_resource_min = tmp_min;
+       privcmd_resource_max = tmp_max;
+       if (!xen_ia64_privcmd_check_size(privcmd_resource_min,
+                                        privcmd_resource_max)) {
+               // Any large enough gap isn't found.
+               // go ahead anyway with the warning hoping that large region
+               // won't be requested.
+               printk(KERN_WARNING "xen privcmd: large enough region for privcmd mmap is not found.\n");
+       }
+
+out:
+       printk(KERN_INFO "xen privcmd uses pseudo physical addr range [0x%lx, 0x%lx] (%ldMB)\n",
+              privcmd_resource_min, privcmd_resource_max, 
+              (privcmd_resource_max - privcmd_resource_min) >> 20);
+       BUG_ON(privcmd_resource_min >= privcmd_resource_max);
+       return 0;
+}
+late_initcall(xen_ia64_privcmd_init);
+
+struct xen_ia64_privcmd_entry {
+       atomic_t        map_count;
+#define INVALID_GPFN   (~0UL)
+       unsigned long   gpfn;
+};
+
+struct xen_ia64_privcmd_range {
+       atomic_t                        ref_count;
+       unsigned long                   pgoff; // in PAGE_SIZE
+       struct resource*                res;
+
+       unsigned long                   num_entries;
+       struct xen_ia64_privcmd_entry   entries[0];
+};
+
+struct xen_ia64_privcmd_vma {
+       struct xen_ia64_privcmd_range*  range;
+
+       unsigned long                   num_entries;
+       struct xen_ia64_privcmd_entry*  entries;
+};
+
+static void
+xen_ia64_privcmd_init_entry(struct xen_ia64_privcmd_entry* entry)
+{
+       atomic_set(&entry->map_count, 0);
+       entry->gpfn = INVALID_GPFN;
+}
+
+static int
+xen_ia64_privcmd_entry_mmap(struct vm_area_struct* vma,
+                           unsigned long addr,
+                           struct xen_ia64_privcmd_range* privcmd_range,
+                           int i,
+                           unsigned long mfn,
+                           pgprot_t prot,
+                           domid_t domid)
+{
+       int error = 0;
+       struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+       unsigned long gpfn;
+       unsigned long flags;
+
+       if ((addr & ~PAGE_MASK) != 0 || mfn == INVALID_MFN) {
+               error = -EINVAL;
+               goto out;
+       }
+
+       if (entry->gpfn != INVALID_GPFN) {
+               error = -EBUSY;
+               goto out;
+       }
+       gpfn = (privcmd_range->res->start >> PAGE_SHIFT) + i;
+
+       flags = ASSIGN_writable;
+       if (pgprot_val(prot) == PROT_READ) {
+               flags = ASSIGN_readonly;
+       }
+       error = HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
+       if (error != 0) {
+               goto out;
+       }
+
+       prot = vma->vm_page_prot;
+       error = remap_pfn_range(vma, addr, gpfn, 1 << PAGE_SHIFT, prot);
+       if (error != 0) {
+               error = HYPERVISOR_zap_physmap(gpfn, 0);
+               if (error) {
+                       BUG();//XXX
+               }
+       } else {
+               atomic_inc(&entry->map_count);
+               entry->gpfn = gpfn;
+       }
+
+out:
+       return error;
+}
+
+static void
+xen_ia64_privcmd_entry_munmap(struct xen_ia64_privcmd_range* privcmd_range,
+                             int i)
+{
+       struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+       unsigned long gpfn = entry->gpfn;
+       //gpfn = (privcmd_range->res->start >> PAGE_SHIFT) +
+       //      (vma->vm_pgoff - privcmd_range->pgoff);
+       int error;
+
+       error = HYPERVISOR_zap_physmap(gpfn, 0);
+       if (error) {
+               BUG();//XXX
+       }
+       entry->gpfn = INVALID_GPFN;
+}
+
+static void
+xen_ia64_privcmd_entry_open(struct xen_ia64_privcmd_range* privcmd_range,
+                           int i)
+{
+       struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+       if (entry->gpfn != INVALID_GPFN) {
+               atomic_inc(&entry->map_count);
+       } else {
+               BUG_ON(atomic_read(&entry->map_count) != 0);
+       }
+}
+
+static void
+xen_ia64_privcmd_entry_close(struct xen_ia64_privcmd_range* privcmd_range,
+                            int i)
+{
+       struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i];
+       if (entry->gpfn != INVALID_GPFN &&
+           atomic_dec_and_test(&entry->map_count)) {
+               xen_ia64_privcmd_entry_munmap(privcmd_range, i);
+       }
+}
+
+static void xen_ia64_privcmd_vma_open(struct vm_area_struct* vma);
+static void xen_ia64_privcmd_vma_close(struct vm_area_struct* vma);
+
+struct vm_operations_struct xen_ia64_privcmd_vm_ops = {
+       .open = &xen_ia64_privcmd_vma_open,
+       .close = &xen_ia64_privcmd_vma_close,
+};
+
+static void
+__xen_ia64_privcmd_vma_open(struct vm_area_struct* vma,
+                           struct xen_ia64_privcmd_vma* privcmd_vma,
+                           struct xen_ia64_privcmd_range* privcmd_range)
+{
+       unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff;
+       unsigned long num_entries = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       unsigned long i;
+
+       BUG_ON(entry_offset < 0);
+       BUG_ON(entry_offset + num_entries > privcmd_range->num_entries);
+
+       privcmd_vma->range = privcmd_range;
+       privcmd_vma->num_entries = num_entries;
+       privcmd_vma->entries = &privcmd_range->entries[entry_offset];
+       vma->vm_private_data = privcmd_vma;
+       for (i = 0; i < privcmd_vma->num_entries; i++) {
+               xen_ia64_privcmd_entry_open(privcmd_range, entry_offset + i);
+       }
+
+       vma->vm_private_data = privcmd_vma;
+       vma->vm_ops = &xen_ia64_privcmd_vm_ops;
+}
+
+static void
+xen_ia64_privcmd_vma_open(struct vm_area_struct* vma)
+{
+       struct xen_ia64_privcmd_vma* privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data;
+       struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range;
+
+       atomic_inc(&privcmd_range->ref_count);
+       // vm_op->open() can't fail.
+       privcmd_vma = kmalloc(sizeof(*privcmd_vma), GFP_KERNEL | __GFP_NOFAIL);
+
+       __xen_ia64_privcmd_vma_open(vma, privcmd_vma, privcmd_range);
+}
+
+static void
+xen_ia64_privcmd_vma_close(struct vm_area_struct* vma)
+{
+       struct xen_ia64_privcmd_vma* privcmd_vma =
+               (struct xen_ia64_privcmd_vma*)vma->vm_private_data;
+       struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range;
+       unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff;
+       unsigned long i;
+
+       for (i = 0; i < privcmd_vma->num_entries; i++) {
+               xen_ia64_privcmd_entry_close(privcmd_range, entry_offset + i);
+       }
+       vma->vm_private_data = NULL;
+       kfree(privcmd_vma);
+
+       if (atomic_dec_and_test(&privcmd_range->ref_count)) {
+#if 1
+               for (i = 0; i < privcmd_range->num_entries; i++) {
+                       struct xen_ia64_privcmd_entry* entry =
+                               &privcmd_range->entries[i];
+                       BUG_ON(atomic_read(&entry->map_count) != 0);
+                       BUG_ON(entry->gpfn != INVALID_GPFN);
+               }
+#endif
+               release_resource(privcmd_range->res);
+               kfree(privcmd_range->res);
+               vfree(privcmd_range);
+       }
+}
+
+int
+privcmd_mmap(struct file * file, struct vm_area_struct * vma)
+{
+       int error;
+       unsigned long size = vma->vm_end - vma->vm_start;
+       unsigned long num_entries = size >> PAGE_SHIFT;
+       struct xen_ia64_privcmd_range* privcmd_range = NULL;
+       struct xen_ia64_privcmd_vma* privcmd_vma = NULL;
+       struct resource* res = NULL;
+       unsigned long i;
+       BUG_ON(!is_running_on_xen());
+
+       BUG_ON(file->private_data != NULL);
+
+       error = -ENOMEM;
+       privcmd_range =
+               vmalloc(sizeof(*privcmd_range) +
+                       sizeof(privcmd_range->entries[0]) * num_entries);
+       if (privcmd_range == NULL) {
+               goto out_enomem0;
+       }
+       privcmd_vma = kmalloc(sizeof(*privcmd_vma), GFP_KERNEL);
+       if (privcmd_vma == NULL) {
+               goto out_enomem1;
+       }
+       res = kzalloc(sizeof(*res), GFP_KERNEL);
+       if (res == NULL) {
+               goto out_enomem1;
+       }
+       res->name = "Xen privcmd mmap";
+       error = allocate_resource(&iomem_resource, res, size,
+                                 privcmd_resource_min, privcmd_resource_max,
+                                 privcmd_resource_align, NULL, NULL);
+       if (error) {
+               goto out_enomem1;
+       }
+       privcmd_range->res = res;
+
+       /* DONTCOPY is essential for Xen as copy_page_range is broken. */
+       vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP;
+
+       atomic_set(&privcmd_range->ref_count, 1);
+       privcmd_range->pgoff = vma->vm_pgoff;
+       privcmd_range->num_entries = num_entries;
+       for (i = 0; i < privcmd_range->num_entries; i++) {
+               xen_ia64_privcmd_init_entry(&privcmd_range->entries[i]);
+       }
+
+       __xen_ia64_privcmd_vma_open(vma, privcmd_vma, privcmd_range);
+       return 0;
+
+out_enomem1:
+       kfree(res);
+       kfree(privcmd_vma);
+out_enomem0:
+       vfree(privcmd_range);
+       return error;
+}
+
+int
+direct_remap_pfn_range(struct vm_area_struct *vma,
+                      unsigned long address,   // process virtual address
+                      unsigned long mfn,       // mfn, mfn + 1, ... mfn + size/PAGE_SIZE
+                      unsigned long size,
+                      pgprot_t prot,
+                      domid_t  domid)          // target domain
+{
+       struct xen_ia64_privcmd_vma* privcmd_vma =
+               (struct xen_ia64_privcmd_vma*)vma->vm_private_data;
+       struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range;
+       unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff;
+
+       unsigned long i;
+       unsigned long offset;
+       int error = 0;
+       BUG_ON(!is_running_on_xen());
+
+#if 0
+       if (prot != vm->vm_page_prot) {
+               return -EINVAL;
+       }
+#endif
+
+       i = (address - vma->vm_start) >> PAGE_SHIFT;
+       for (offset = 0; offset < size; offset += PAGE_SIZE) {
+               error = xen_ia64_privcmd_entry_mmap(vma, (address + offset) & PAGE_MASK, privcmd_range, entry_offset + i, mfn, prot, domid);
+               if (error != 0) {
+                       break;
+               }
+
+               i++;
+               mfn++;
+        }
+
+       return error;
+}
+
+
+/* Called after suspend, to resume time.  */
+void
+time_resume(void)
+{
+       extern void ia64_cpu_local_tick(void);
+
+       /* Just trigger a tick.  */
+       ia64_cpu_local_tick();
+}
diff --git a/arch/ia64/xen/util.c b/arch/ia64/xen/util.c
new file mode 100644 (file)
index 0000000..03ac495
--- /dev/null
@@ -0,0 +1,115 @@
+/******************************************************************************
+ * arch/ia64/xen/util.c
+ * This file is the ia64 counterpart of drivers/xen/util.c
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/mm.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <xen/driver_util.h>
+
+struct vm_struct *alloc_vm_area(unsigned long size)
+{
+       int order;
+       unsigned long virt;
+       unsigned long nr_pages;
+       struct vm_struct* area;
+       
+       order = get_order(size);
+       virt = __get_free_pages(GFP_KERNEL, order);
+       if (virt == 0) {
+               goto err0;
+       }
+       nr_pages = 1 << order;
+       scrub_pages(virt, nr_pages);
+       
+       area = kmalloc(sizeof(*area), GFP_KERNEL);
+       if (area == NULL) {
+               goto err1;
+       }
+       
+        area->flags = VM_IOREMAP;//XXX
+        area->addr = (void*)virt;
+        area->size = size;
+        area->pages = NULL; //XXX
+        area->nr_pages = nr_pages;
+        area->phys_addr = 0;   /* xenbus_map_ring_valloc uses this field!  */
+
+       return area;
+
+err1:
+       free_pages(virt, order);
+err0:
+       return NULL;
+       
+}
+EXPORT_SYMBOL_GPL(alloc_vm_area);
+
+void free_vm_area(struct vm_struct *area)
+{
+       unsigned int order = get_order(area->size);
+       unsigned long i;
+       unsigned long phys_addr = __pa(area->addr);
+
+       // This area is used for foreign page mappping.
+       // So underlying machine page may not be assigned.
+       for (i = 0; i < (1 << order); i++) {
+               unsigned long ret;
+               unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i;
+               struct xen_memory_reservation reservation = {
+                       .nr_extents   = 1,
+                       .address_bits = 0,
+                       .extent_order = 0,
+                       .domid        = DOMID_SELF
+               };
+               set_xen_guest_handle(reservation.extent_start, &gpfn);
+               ret = HYPERVISOR_memory_op(XENMEM_populate_physmap,
+                                          &reservation);
+               BUG_ON(ret != 1);
+       }
+       free_pages((unsigned long)area->addr, order);
+       kfree(area);
+}
+EXPORT_SYMBOL_GPL(free_vm_area);
+
+void lock_vm_area(struct vm_struct *area)
+{
+       // nothing
+}
+EXPORT_SYMBOL_GPL(lock_vm_area);
+
+void unlock_vm_area(struct vm_struct *area)
+{
+       // nothing
+}
+EXPORT_SYMBOL_GPL(unlock_vm_area);
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/arch/ia64/xen/xenentry.S b/arch/ia64/xen/xenentry.S
new file mode 100644 (file)
index 0000000..ad9e79a
--- /dev/null
@@ -0,0 +1,867 @@
+/*
+ * ia64/xen/entry.S
+ *
+ * Alternate kernel routines for Xen.  Heavily leveraged from
+ *   ia64/kernel/entry.S
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Dan Magenheimer <dan.magenheimer@.hp.com>
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/cache.h>
+#include <asm/errno.h>
+#include <asm/kregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
+#include <asm/percpu.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+#ifdef CONFIG_XEN
+#include "xenminstate.h"
+#else
+#include "minstate.h"
+#endif
+
+/*
+ * prev_task <- ia64_switch_to(struct task_struct *next)
+ *     With Ingo's new scheduler, interrupts are disabled when this routine gets
+ *     called.  The code starting at .map relies on this.  The rest of the code
+ *     doesn't care about the interrupt masking status.
+ */
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_switch_to)
+       .prologue
+       alloc r16=ar.pfs,1,0,0,0
+       movl r22=running_on_xen;;
+       ld4 r22=[r22];;
+       cmp.eq p7,p0=r22,r0
+(p7)   br.cond.sptk.many __ia64_switch_to;;
+#else
+GLOBAL_ENTRY(ia64_switch_to)
+       .prologue
+       alloc r16=ar.pfs,1,0,0,0
+#endif
+       DO_SAVE_SWITCH_STACK
+       .body
+
+       adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
+       movl r25=init_task
+       mov r27=IA64_KR(CURRENT_STACK)
+       adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
+       dep r20=0,in0,61,3              // physical address of "next"
+       ;;
+       st8 [r22]=sp                    // save kernel stack pointer of old task
+       shr.u r26=r20,IA64_GRANULE_SHIFT
+       cmp.eq p7,p6=r25,in0
+       ;;
+#ifdef CONFIG_XEN
+       movl r8=XSI_PSR_IC
+       ;;
+       st4 [r8]=r0     // force psr.ic off for hyperprivop(s)
+       ;;
+#endif
+       /*
+        * If we've already mapped this task's page, we can skip doing it again.
+        */
+(p6)   cmp.eq p7,p6=r26,r27
+(p6)   br.cond.dpnt .map
+       ;;
+.done:
+#ifdef CONFIG_XEN
+       // psr.ic already off
+       // update "current" application register
+       mov r8=IA64_KR_CURRENT
+       mov r9=in0;;
+       XEN_HYPER_SET_KR
+       ld8 sp=[r21]                    // load kernel stack pointer of new task
+       movl r27=XSI_PSR_IC
+       mov r8=1
+       ;;
+       st4 [r27]=r8                    // psr.ic back on
+#else
+       ld8 sp=[r21]                    // load kernel stack pointer of new task
+       mov IA64_KR(CURRENT)=in0        // update "current" application register
+#endif
+       mov r8=r13                      // return pointer to previously running task
+       mov r13=in0                     // set "current" pointer
+       ;;
+       DO_LOAD_SWITCH_STACK
+
+#ifdef CONFIG_SMP
+       sync.i                          // ensure "fc"s done by this CPU are visible on other CPUs
+#endif
+       br.ret.sptk.many rp             // boogie on out in new context
+
+.map:
+#ifdef CONFIG_XEN
+       // psr.ic already off
+#else
+       rsm psr.ic                      // interrupts (psr.i) are already disabled here
+#endif
+       movl r25=PAGE_KERNEL
+       ;;
+       srlz.d
+       or r23=r25,r20                  // construct PA | page properties
+       mov r25=IA64_GRANULE_SHIFT<<2
+       ;;
+#ifdef CONFIG_XEN
+       movl r8=XSI_ITIR
+       ;;
+       st8 [r8]=r25
+       ;;
+       movl r8=XSI_IFA
+       ;;
+       st8 [r8]=in0                     // VA of next task...
+       ;;
+       mov r25=IA64_TR_CURRENT_STACK
+       // remember last page we mapped...
+       mov r8=IA64_KR_CURRENT_STACK
+       mov r9=r26;;
+       XEN_HYPER_SET_KR;;
+#else
+       mov cr.itir=r25
+       mov cr.ifa=in0                  // VA of next task...
+       ;;
+       mov r25=IA64_TR_CURRENT_STACK
+       mov IA64_KR(CURRENT_STACK)=r26  // remember last page we mapped...
+#endif
+       ;;
+       itr.d dtr[r25]=r23              // wire in new mapping...
+#ifndef CONFIG_XEN
+       ssm psr.ic                      // reenable the psr.ic bit
+       ;;
+       srlz.d
+#endif
+       br.cond.sptk .done
+#ifdef CONFIG_XEN
+END(xen_switch_to)
+#else
+END(ia64_switch_to)
+#endif
+
+       /*
+        * Invoke a system call, but do some tracing before and after the call.
+        * We MUST preserve the current register frame throughout this routine
+        * because some system calls (such as ia64_execve) directly
+        * manipulate ar.pfs.
+        */
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_trace_syscall)
+       PT_REGS_UNWIND_INFO(0)
+       movl r16=running_on_xen;;
+       ld4 r16=[r16];;
+       cmp.eq p7,p0=r16,r0
+(p7)   br.cond.sptk.many __ia64_trace_syscall;;
+#else
+GLOBAL_ENTRY(ia64_trace_syscall)
+       PT_REGS_UNWIND_INFO(0)
+#endif
+       /*
+        * We need to preserve the scratch registers f6-f11 in case the system
+        * call is sigreturn.
+        */
+       adds r16=PT(F6)+16,sp
+       adds r17=PT(F7)+16,sp
+       ;;
+       stf.spill [r16]=f6,32
+       stf.spill [r17]=f7,32
+       ;;
+       stf.spill [r16]=f8,32
+       stf.spill [r17]=f9,32
+       ;;
+       stf.spill [r16]=f10
+       stf.spill [r17]=f11
+       br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args
+       adds r16=PT(F6)+16,sp
+       adds r17=PT(F7)+16,sp
+       ;;
+       ldf.fill f6=[r16],32
+       ldf.fill f7=[r17],32
+       ;;
+       ldf.fill f8=[r16],32
+       ldf.fill f9=[r17],32
+       ;;
+       ldf.fill f10=[r16]
+       ldf.fill f11=[r17]
+       // the syscall number may have changed, so re-load it and re-calculate the
+       // syscall entry-point:
+       adds r15=PT(R15)+16,sp                  // r15 = &pt_regs.r15 (syscall #)
+       ;;
+       ld8 r15=[r15]
+       mov r3=NR_syscalls - 1
+       ;;
+       adds r15=-1024,r15
+       movl r16=sys_call_table
+       ;;
+       shladd r20=r15,3,r16                    // r20 = sys_call_table + 8*(syscall-1024)
+       cmp.leu p6,p7=r15,r3
+       ;;
+(p6)   ld8 r20=[r20]                           // load address of syscall entry point
+(p7)   movl r20=sys_ni_syscall
+       ;;
+       mov b6=r20
+       br.call.sptk.many rp=b6                 // do the syscall
+.strace_check_retval:
+       cmp.lt p6,p0=r8,r0                      // syscall failed?
+       adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
+       adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
+       mov r10=0
+(p6)   br.cond.sptk strace_error               // syscall failed ->
+       ;;                                      // avoid RAW on r10
+.strace_save_retval:
+.mem.offset 0,0; st8.spill [r2]=r8             // store return value in slot for r8
+.mem.offset 8,0; st8.spill [r3]=r10            // clear error indication in slot for r10
+       br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value
+.ret3:
+(pUStk)        cmp.eq.unc p6,p0=r0,r0                  // p6 <- pUStk
+       br.cond.sptk .work_pending_syscall_end
+
+strace_error:
+       ld8 r3=[r2]                             // load pt_regs.r8
+       sub r9=0,r8                             // negate return value to get errno value
+       ;;
+       cmp.ne p6,p0=r3,r0                      // is pt_regs.r8!=0?
+       adds r3=16,r2                           // r3=&pt_regs.r10
+       ;;
+(p6)   mov r10=-1
+(p6)   mov r8=r9
+       br.cond.sptk .strace_save_retval
+#ifdef CONFIG_XEN
+END(xen_trace_syscall)
+#else
+END(ia64_trace_syscall)
+#endif
+
+/*
+ * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
+ *     need to switch to bank 0 and doesn't restore the scratch registers.
+ *     To avoid leaking kernel bits, the scratch registers are set to
+ *     the following known-to-be-safe values:
+ *
+ *               r1: restored (global pointer)
+ *               r2: cleared
+ *               r3: 1 (when returning to user-level)
+ *           r8-r11: restored (syscall return value(s))
+ *              r12: restored (user-level stack pointer)
+ *              r13: restored (user-level thread pointer)
+ *              r14: set to __kernel_syscall_via_epc
+ *              r15: restored (syscall #)
+ *          r16-r17: cleared
+ *              r18: user-level b6
+ *              r19: cleared
+ *              r20: user-level ar.fpsr
+ *              r21: user-level b0
+ *              r22: cleared
+ *              r23: user-level ar.bspstore
+ *              r24: user-level ar.rnat
+ *              r25: user-level ar.unat
+ *              r26: user-level ar.pfs
+ *              r27: user-level ar.rsc
+ *              r28: user-level ip
+ *              r29: user-level psr
+ *              r30: user-level cfm
+ *              r31: user-level pr
+ *           f6-f11: cleared
+ *               pr: restored (user-level pr)
+ *               b0: restored (user-level rp)
+ *               b6: restored
+ *               b7: set to __kernel_syscall_via_epc
+ *          ar.unat: restored (user-level ar.unat)
+ *           ar.pfs: restored (user-level ar.pfs)
+ *           ar.rsc: restored (user-level ar.rsc)
+ *          ar.rnat: restored (user-level ar.rnat)
+ *      ar.bspstore: restored (user-level ar.bspstore)
+ *          ar.fpsr: restored (user-level ar.fpsr)
+ *           ar.ccv: cleared
+ *           ar.csd: cleared
+ *           ar.ssd: cleared
+ */
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_leave_syscall)
+       PT_REGS_UNWIND_INFO(0)
+       movl r22=running_on_xen;;
+       ld4 r22=[r22];;
+       cmp.eq p7,p0=r22,r0
+(p7)   br.cond.sptk.many __ia64_leave_syscall;;
+#else
+ENTRY(ia64_leave_syscall)
+       PT_REGS_UNWIND_INFO(0)
+#endif
+       /*
+        * work.need_resched etc. mustn't get changed by this CPU before it returns to
+        * user- or fsys-mode, hence we disable interrupts early on.
+        *
+        * p6 controls whether current_thread_info()->flags needs to be check for
+        * extra work.  We always check for extra work when returning to user-level.
+        * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+        * is 0.  After extra work processing has been completed, execution
+        * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+        * needs to be redone.
+        */
+#ifdef CONFIG_PREEMPT
+       rsm psr.i                               // disable interrupts
+       cmp.eq pLvSys,p0=r0,r0                  // pLvSys=1: leave from syscall
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+       ;;
+       .pred.rel.mutex pUStk,pKStk
+(pKStk) ld4 r21=[r20]                  // r21 <- preempt_count
+(pUStk)        mov r21=0                       // r21 <- 0
+       ;;
+       cmp.eq p6,p0=r21,r0             // p6 <- pUStk || (preempt_count == 0)
+#else /* !CONFIG_PREEMPT */
+#ifdef CONFIG_XEN
+       movl r2=XSI_PSR_I_ADDR
+       mov r18=1
+       ;;
+       ld8 r2=[r2]
+       ;;
+(pUStk)        st1 [r2]=r18
+#else
+(pUStk)        rsm psr.i
+#endif
+       cmp.eq pLvSys,p0=r0,r0          // pLvSys=1: leave from syscall
+(pUStk)        cmp.eq.unc p6,p0=r0,r0          // p6 <- pUStk
+#endif
+.work_processed_syscall:
+       adds r2=PT(LOADRS)+16,r12
+       adds r3=PT(AR_BSPSTORE)+16,r12
+       adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
+       ;;
+(p6)   ld4 r31=[r18]                           // load current_thread_info()->flags
+       ld8 r19=[r2],PT(B6)-PT(LOADRS)          // load ar.rsc value for "loadrs"
+       nop.i 0
+       ;;
+       mov r16=ar.bsp                          // M2  get existing backing store pointer
+       ld8 r18=[r2],PT(R9)-PT(B6)              // load b6
+(p6)   and r15=TIF_WORK_MASK,r31               // any work other than TIF_SYSCALL_TRACE?
+       ;;
+       ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE)    // load ar.bspstore (may be garbage)
+(p6)   cmp4.ne.unc p6,p0=r15, r0               // any special work pending?
+(p6)   br.cond.spnt .work_pending_syscall
+       ;;
+       // start restoring the state saved on the kernel stack (struct pt_regs):
+       ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
+       ld8 r11=[r3],PT(CR_IIP)-PT(R11)
+(pNonSys) break 0              //      bug check: we shouldn't be here if pNonSys is TRUE!
+       ;;
+       invala                  // M0|1 invalidate ALAT
+#ifdef CONFIG_XEN
+       movl r28=XSI_PSR_I_ADDR
+       movl r29=XSI_PSR_IC
+       ;;
+       ld8 r28=[r28]
+       mov r30=1
+       ;;
+       st1     [r28]=r30
+       st4     [r29]=r0        // note: clears both vpsr.i and vpsr.ic!
+       ;;
+#else
+       rsm psr.i | psr.ic      // M2   turn off interrupts and interruption collection
+#endif
+       cmp.eq p9,p0=r0,r0      // A    set p9 to indicate that we should restore cr.ifs
+
+       ld8 r29=[r2],16         // M0|1 load cr.ipsr
+       ld8 r28=[r3],16         // M0|1 load cr.iip
+       mov r22=r0              // A    clear r22
+       ;;
+       ld8 r30=[r2],16         // M0|1 load cr.ifs
+       ld8 r25=[r3],16         // M0|1 load ar.unat
+(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+       ;;
+       ld8 r26=[r2],PT(B0)-PT(AR_PFS)  // M0|1 load ar.pfs
+(pKStk)        mov r22=psr                     // M2   read PSR now that interrupts are disabled
+       nop 0
+       ;;
+       ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
+       ld8 r27=[r3],PT(PR)-PT(AR_RSC)  // M0|1 load ar.rsc
+       mov f6=f0                       // F    clear f6
+       ;;
+       ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT)    // M0|1 load ar.rnat (may be garbage)
+       ld8 r31=[r3],PT(R1)-PT(PR)              // M0|1 load predicates
+       mov f7=f0                               // F    clear f7
+       ;;
+       ld8 r20=[r2],PT(R12)-PT(AR_FPSR)        // M0|1 load ar.fpsr
+       ld8.fill r1=[r3],16                     // M0|1 load r1
+(pUStk) mov r17=1                              // A
+       ;;
+(pUStk) st1 [r14]=r17                          // M2|3
+       ld8.fill r13=[r3],16                    // M0|1
+       mov f8=f0                               // F    clear f8
+       ;;
+       ld8.fill r12=[r2]                       // M0|1 restore r12 (sp)
+       ld8.fill r15=[r3]                       // M0|1 restore r15
+       mov b6=r18                              // I0   restore b6
+
+       addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A
+       mov f9=f0                                       // F    clear f9
+(pKStk) br.cond.dpnt.many skip_rbs_switch              // B
+
+       srlz.d                          // M0   ensure interruption collection is off (for cover)
+       shr.u r18=r19,16                // I0|1 get byte size of existing "dirty" partition
+#ifdef CONFIG_XEN
+       XEN_HYPER_COVER;
+#else
+       cover                           // B    add current frame into dirty partition & set cr.ifs
+#endif
+       ;;
+(pUStk) ld4 r17=[r17]                  // M0|1 r17 = cpu_data->phys_stacked_size_p8
+       mov r19=ar.bsp                  // M2   get new backing store pointer
+       mov f10=f0                      // F    clear f10
+
+       nop.m 0
+       movl r14=__kernel_syscall_via_epc // X
+       ;;
+       mov.m ar.csd=r0                 // M2   clear ar.csd
+       mov.m ar.ccv=r0                 // M2   clear ar.ccv
+       mov b7=r14                      // I0   clear b7 (hint with __kernel_syscall_via_epc)
+
+       mov.m ar.ssd=r0                 // M2   clear ar.ssd
+       mov f11=f0                      // F    clear f11
+       br.cond.sptk.many rbs_switch    // B
+#ifdef CONFIG_XEN
+END(xen_leave_syscall)
+#else
+END(ia64_leave_syscall)
+#endif
+
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_leave_kernel)
+       PT_REGS_UNWIND_INFO(0)
+       movl r22=running_on_xen;;
+       ld4 r22=[r22];;
+       cmp.eq p7,p0=r22,r0
+(p7)   br.cond.sptk.many __ia64_leave_kernel;;
+#else
+GLOBAL_ENTRY(ia64_leave_kernel)
+       PT_REGS_UNWIND_INFO(0)
+#endif
+       /*
+        * work.need_resched etc. mustn't get changed by this CPU before it returns to
+        * user- or fsys-mode, hence we disable interrupts early on.
+        *
+        * p6 controls whether current_thread_info()->flags needs to be check for
+        * extra work.  We always check for extra work when returning to user-level.
+        * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+        * is 0.  After extra work processing has been completed, execution
+        * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+        * needs to be redone.
+        */
+#ifdef CONFIG_PREEMPT
+       rsm psr.i                               // disable interrupts
+       cmp.eq p0,pLvSys=r0,r0                  // pLvSys=0: leave from kernel
+(pKStk)        adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+       ;;
+       .pred.rel.mutex pUStk,pKStk
+(pKStk)        ld4 r21=[r20]                   // r21 <- preempt_count
+(pUStk)        mov r21=0                       // r21 <- 0
+       ;;
+       cmp.eq p6,p0=r21,r0             // p6 <- pUStk || (preempt_count == 0)
+#else
+#ifdef CONFIG_XEN
+(pUStk)        movl r17=XSI_PSR_I_ADDR
+(pUStk)        mov r31=1
+               ;;
+(pUStk)        ld8 r17=[r17]
+               ;;
+(pUStk)        st1 [r17]=r31
+       ;;
+#else
+(pUStk)        rsm psr.i
+#endif
+       cmp.eq p0,pLvSys=r0,r0          // pLvSys=0: leave from kernel
+(pUStk)        cmp.eq.unc p6,p0=r0,r0          // p6 <- pUStk
+#endif
+.work_processed_kernel:
+       adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+       ;;
+(p6)   ld4 r31=[r17]                           // load current_thread_info()->flags
+       adds r21=PT(PR)+16,r12
+       ;;
+
+       lfetch [r21],PT(CR_IPSR)-PT(PR)
+       adds r2=PT(B6)+16,r12
+       adds r3=PT(R16)+16,r12
+       ;;
+       lfetch [r21]
+       ld8 r28=[r2],8          // load b6
+       adds r29=PT(R24)+16,r12
+
+       ld8.fill r16=[r3],PT(AR_CSD)-PT(R16)
+       adds r30=PT(AR_CCV)+16,r12
+(p6)   and r19=TIF_WORK_MASK,r31               // any work other than TIF_SYSCALL_TRACE?
+       ;;
+       ld8.fill r24=[r29]
+       ld8 r15=[r30]           // load ar.ccv
+(p6)   cmp4.ne.unc p6,p0=r19, r0               // any special work pending?
+       ;;
+       ld8 r29=[r2],16         // load b7
+       ld8 r30=[r3],16         // load ar.csd
+(p6)   br.cond.spnt .work_pending
+       ;;
+       ld8 r31=[r2],16         // load ar.ssd
+       ld8.fill r8=[r3],16
+       ;;
+       ld8.fill r9=[r2],16
+       ld8.fill r10=[r3],PT(R17)-PT(R10)
+       ;;
+       ld8.fill r11=[r2],PT(R18)-PT(R11)
+       ld8.fill r17=[r3],16
+       ;;
+       ld8.fill r18=[r2],16
+       ld8.fill r19=[r3],16
+       ;;
+       ld8.fill r20=[r2],16
+       ld8.fill r21=[r3],16
+       mov ar.csd=r30
+       mov ar.ssd=r31
+       ;;
+#ifdef CONFIG_XEN
+       movl r23=XSI_PSR_I_ADDR
+       movl r22=XSI_PSR_IC
+       ;;
+       ld8 r23=[r23]
+       mov r25=1
+       ;;
+       st1 [r23]=r25
+       st4 [r22]=r0            // note: clears both vpsr.i and vpsr.ic!
+       ;;
+#else
+       rsm psr.i | psr.ic      // initiate turning off of interrupt and interruption collection
+#endif
+       invala                  // invalidate ALAT
+       ;;
+       ld8.fill r22=[r2],24
+       ld8.fill r23=[r3],24
+       mov b6=r28
+       ;;
+       ld8.fill r25=[r2],16
+       ld8.fill r26=[r3],16
+       mov b7=r29
+       ;;
+       ld8.fill r27=[r2],16
+       ld8.fill r28=[r3],16
+       ;;
+       ld8.fill r29=[r2],16
+       ld8.fill r30=[r3],24
+       ;;
+       ld8.fill r31=[r2],PT(F9)-PT(R31)
+       adds r3=PT(F10)-PT(F6),r3
+       ;;
+       ldf.fill f9=[r2],PT(F6)-PT(F9)
+       ldf.fill f10=[r3],PT(F8)-PT(F10)
+       ;;
+       ldf.fill f6=[r2],PT(F7)-PT(F6)
+       ;;
+       ldf.fill f7=[r2],PT(F11)-PT(F7)
+       ldf.fill f8=[r3],32
+       ;;
+       srlz.d  // ensure that inter. collection is off (VHPT is don't care, since text is pinned)
+       mov ar.ccv=r15
+       ;;
+       ldf.fill f11=[r2]
+#ifdef CONFIG_XEN
+       ;;
+       // r16-r31 all now hold bank1 values
+       movl r2=XSI_BANK1_R16
+       movl r3=XSI_BANK1_R16+8
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r16,16
+.mem.offset 8,0; st8.spill [r3]=r17,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r18,16
+.mem.offset 8,0; st8.spill [r3]=r19,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r20,16
+.mem.offset 8,0; st8.spill [r3]=r21,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r22,16
+.mem.offset 8,0; st8.spill [r3]=r23,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r24,16
+.mem.offset 8,0; st8.spill [r3]=r25,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r26,16
+.mem.offset 8,0; st8.spill [r3]=r27,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r28,16
+.mem.offset 8,0; st8.spill [r3]=r29,16
+       ;;
+.mem.offset 0,0; st8.spill [r2]=r30,16
+.mem.offset 8,0; st8.spill [r3]=r31,16
+       ;;
+       movl r2=XSI_BANKNUM;;
+       st4 [r2]=r0;
+#else
+       bsw.0                   // switch back to bank 0 (no stop bit required beforehand...)
+#endif
+       ;;
+(pUStk)        mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
+       adds r16=PT(CR_IPSR)+16,r12
+       adds r17=PT(CR_IIP)+16,r12
+
+(pKStk)        mov r22=psr             // M2 read PSR now that interrupts are disabled
+       nop.i 0
+       nop.i 0
+       ;;
+       ld8 r29=[r16],16        // load cr.ipsr
+       ld8 r28=[r17],16        // load cr.iip
+       ;;
+       ld8 r30=[r16],16        // load cr.ifs
+       ld8 r25=[r17],16        // load ar.unat
+       ;;
+       ld8 r26=[r16],16        // load ar.pfs
+       ld8 r27=[r17],16        // load ar.rsc
+       cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore cr.ifs
+       ;;
+       ld8 r24=[r16],16        // load ar.rnat (may be garbage)
+       ld8 r23=[r17],16        // load ar.bspstore (may be garbage)
+       ;;
+       ld8 r31=[r16],16        // load predicates
+       ld8 r21=[r17],16        // load b0
+       ;;
+       ld8 r19=[r16],16        // load ar.rsc value for "loadrs"
+       ld8.fill r1=[r17],16    // load r1
+       ;;
+       ld8.fill r12=[r16],16
+       ld8.fill r13=[r17],16
+(pUStk)        adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
+       ;;
+       ld8 r20=[r16],16        // ar.fpsr
+       ld8.fill r15=[r17],16
+       ;;
+       ld8.fill r14=[r16],16
+       ld8.fill r2=[r17]
+(pUStk)        mov r17=1
+       ;;
+       ld8.fill r3=[r16]
+(pUStk)        st1 [r18]=r17           // restore current->thread.on_ustack
+       shr.u r18=r19,16        // get byte size of existing "dirty" partition
+       ;;
+       mov r16=ar.bsp          // get existing backing store pointer
+       addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
+       ;;
+       ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
+(pKStk)        br.cond.dpnt skip_rbs_switch
+
+       /*
+        * Restore user backing store.
+        *
+        * NOTE: alloc, loadrs, and cover can't be predicated.
+        */
+(pNonSys) br.cond.dpnt dont_preserve_current_frame
+
+#ifdef CONFIG_XEN
+       XEN_HYPER_COVER;
+#else
+       cover                           // add current frame into dirty partition and set cr.ifs
+#endif
+       ;;
+       mov r19=ar.bsp                  // get new backing store pointer
+rbs_switch:
+       sub r16=r16,r18                 // krbs = old bsp - size of dirty partition
+       cmp.ne p9,p0=r0,r0              // clear p9 to skip restore of cr.ifs
+       ;;
+       sub r19=r19,r16                 // calculate total byte size of dirty partition
+       add r18=64,r18                  // don't force in0-in7 into memory...
+       ;;
+       shl r19=r19,16                  // shift size of dirty partition into loadrs position
+       ;;
+dont_preserve_current_frame:
+       /*
+        * To prevent leaking bits between the kernel and user-space,
+        * we must clear the stacked registers in the "invalid" partition here.
+        * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium,
+        * 5 registers/cycle on McKinley).
+        */
+#      define pRecurse p6
+#      define pReturn  p7
+#ifdef CONFIG_ITANIUM
+#      define Nregs    10
+#else
+#      define Nregs    14
+#endif
+       alloc loc0=ar.pfs,2,Nregs-2,2,0
+       shr.u loc1=r18,9                // RNaTslots <= floor(dirtySize / (64*8))
+       sub r17=r17,r18                 // r17 = (physStackedSize + 8) - dirtySize
+       ;;
+       mov ar.rsc=r19                  // load ar.rsc to be used for "loadrs"
+       shladd in0=loc1,3,r17
+       mov in1=0
+       ;;
+       TEXT_ALIGN(32)
+rse_clear_invalid:
+#ifdef CONFIG_ITANIUM
+       // cycle 0
+ { .mii
+       alloc loc0=ar.pfs,2,Nregs-2,2,0
+       cmp.lt pRecurse,p0=Nregs*8,in0  // if more than Nregs regs left to clear, (re)curse
+       add out0=-Nregs*8,in0
+}{ .mfb
+       add out1=1,in1                  // increment recursion count
+       nop.f 0
+       nop.b 0                         // can't do br.call here because of alloc (WAW on CFM)
+       ;;
+}{ .mfi        // cycle 1
+       mov loc1=0
+       nop.f 0
+       mov loc2=0
+}{ .mib
+       mov loc3=0
+       mov loc4=0
+(pRecurse) br.call.sptk.many b0=rse_clear_invalid
+
+}{ .mfi        // cycle 2
+       mov loc5=0
+       nop.f 0
+       cmp.ne pReturn,p0=r0,in1        // if recursion count != 0, we need to do a br.ret
+}{ .mib
+       mov loc6=0
+       mov loc7=0
+(pReturn) br.ret.sptk.many b0
+}
+#else /* !CONFIG_ITANIUM */
+       alloc loc0=ar.pfs,2,Nregs-2,2,0
+       cmp.lt pRecurse,p0=Nregs*8,in0  // if more than Nregs regs left to clear, (re)curse
+       add out0=-Nregs*8,in0
+       add out1=1,in1                  // increment recursion count
+       mov loc1=0
+       mov loc2=0
+       ;;
+       mov loc3=0
+       mov loc4=0
+       mov loc5=0
+       mov loc6=0
+       mov loc7=0
+(pRecurse) br.call.dptk.few b0=rse_clear_invalid
+       ;;
+       mov loc8=0
+       mov loc9=0
+       cmp.ne pReturn,p0=r0,in1        // if recursion count != 0, we need to do a br.ret
+       mov loc10=0
+       mov loc11=0
+(pReturn) br.ret.dptk.many b0
+#endif /* !CONFIG_ITANIUM */
+#      undef pRecurse
+#      undef pReturn
+       ;;
+       alloc r17=ar.pfs,0,0,0,0        // drop current register frame
+       ;;
+       loadrs
+       ;;
+skip_rbs_switch:
+       mov ar.unat=r25         // M2
+(pKStk)        extr.u r22=r22,21,1     // I0 extract current value of psr.pp from r22
+(pLvSys)mov r19=r0             // A  clear r19 for leave_syscall, no-op otherwise
+       ;;
+(pUStk)        mov ar.bspstore=r23     // M2
+(pKStk)        dep r29=r22,r29,21,1    // I0 update ipsr.pp with psr.pp
+(pLvSys)mov r16=r0             // A  clear r16 for leave_syscall, no-op otherwise
+       ;;
+#ifdef CONFIG_XEN
+       movl r25=XSI_IPSR
+       ;;
+       st8[r25]=r29,XSI_IFS_OFS-XSI_IPSR_OFS
+       ;;
+#else
+       mov cr.ipsr=r29         // M2
+#endif
+       mov ar.pfs=r26          // I0
+(pLvSys)mov r17=r0             // A  clear r17 for leave_syscall, no-op otherwise
+
+#ifdef CONFIG_XEN
+(p9)   st8 [r25]=r30
+       ;;
+       adds r25=XSI_IIP_OFS-XSI_IFS_OFS,r25
+       ;;
+#else
+(p9)   mov cr.ifs=r30          // M2
+#endif
+       mov b0=r21              // I0
+(pLvSys)mov r18=r0             // A  clear r18 for leave_syscall, no-op otherwise
+
+       mov ar.fpsr=r20         // M2
+#ifdef CONFIG_XEN
+       st8     [r25]=r28
+#else
+       mov cr.iip=r28          // M2
+#endif
+       nop 0
+       ;;
+(pUStk)        mov ar.rnat=r24         // M2 must happen with RSE in lazy mode
+       nop 0
+(pLvSys)mov r2=r0
+
+       mov ar.rsc=r27          // M2
+       mov pr=r31,-1           // I0
+#ifdef CONFIG_XEN
+       ;;
+       XEN_HYPER_RFI;
+#else
+       rfi                     // B
+#endif
+
+       /*
+        * On entry:
+        *      r20 = &current->thread_info->pre_count (if CONFIG_PREEMPT)
+        *      r31 = current->thread_info->flags
+        * On exit:
+        *      p6 = TRUE if work-pending-check needs to be redone
+        */
+.work_pending_syscall:
+       add r2=-8,r2
+       add r3=-8,r3
+       ;;
+       st8 [r2]=r8
+       st8 [r3]=r10
+.work_pending:
+       tbit.z p6,p0=r31,TIF_NEED_RESCHED               // current_thread_info()->need_resched==0?
+(p6)   br.cond.sptk.few .notify
+#ifdef CONFIG_PREEMPT
+(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
+       ;;
+(pKStk) st4 [r20]=r21
+       ssm psr.i               // enable interrupts
+#endif
+       br.call.spnt.many rp=schedule
+.ret9: cmp.eq p6,p0=r0,r0                              // p6 <- 1
+#ifdef CONFIG_XEN
+       movl r2=XSI_PSR_I_ADDR
+       mov r20=1
+       ;;
+       ld8 r2=[r2]
+       ;;
+       st1 [r2]=r20
+#else
+       rsm psr.i               // disable interrupts
+#endif
+       ;;
+#ifdef CONFIG_PREEMPT
+(pKStk)        adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+       ;;
+(pKStk)        st4 [r20]=r0            // preempt_count() <- 0
+#endif
+(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+       br.cond.sptk.many .work_processed_kernel        // re-check
+
+.notify:
+(pUStk)        br.call.spnt.many rp=notify_resume_user
+.ret10:        cmp.ne p6,p0=r0,r0                              // p6 <- 0
+(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+       br.cond.sptk.many .work_processed_kernel        // don't re-check
+
+.work_pending_syscall_end:
+       adds r2=PT(R8)+16,r12
+       adds r3=PT(R10)+16,r12
+       ;;
+       ld8 r8=[r2]
+       ld8 r10=[r3]
+       br.cond.sptk.many .work_processed_syscall       // re-check
+
+#ifdef CONFIG_XEN
+END(xen_leave_kernel)
+#else
+END(ia64_leave_kernel)
+#endif
diff --git a/arch/ia64/xen/xenhpski.c b/arch/ia64/xen/xenhpski.c
new file mode 100644 (file)
index 0000000..3bc6cdb
--- /dev/null
@@ -0,0 +1,19 @@
+
+extern unsigned long xen_get_cpuid(int);
+
+int
+running_on_sim(void)
+{
+       int i;
+       long cpuid[6];
+
+       for (i = 0; i < 5; ++i)
+               cpuid[i] = xen_get_cpuid(i);
+       if ((cpuid[0] & 0xff) != 'H') return 0;
+       if ((cpuid[3] & 0xff) != 0x4) return 0;
+       if (((cpuid[3] >> 8) & 0xff) != 0x0) return 0;
+       if (((cpuid[3] >> 16) & 0xff) != 0x0) return 0;
+       if (((cpuid[3] >> 24) & 0x7) != 0x7) return 0;
+       return 1;
+}
+
diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S
new file mode 100644 (file)
index 0000000..9c9e9f2
--- /dev/null
@@ -0,0 +1,2169 @@
+/*
+ * arch/ia64/xen/ivt.S
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+/*
+ * This file defines the interruption vector table used by the CPU.
+ * It does not include one entry per possible cause of interruption.
+ *
+ * The first 20 entries of the table contain 64 bundles each while the
+ * remaining 48 entries contain only 16 bundles each.
+ *
+ * The 64 bundles are used to allow inlining the whole handler for critical
+ * interruptions like TLB misses.
+ *
+ *  For each entry, the comment is as follows:
+ *
+ *             // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ *  entry offset ----/     /         /                  /          /
+ *  entry number ---------/         /                  /          /
+ *  size of the entry -------------/                  /          /
+ *  vector name -------------------------------------/          /
+ *  interruptions triggering this vector ----------------------/
+ *
+ * The table is 32KB in size and must be aligned on 32KB boundary.
+ * (The CPU ignores the 15 lower bits of the address)
+ *
+ * Table is based upon EAS2.6 (Oct 1999)
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/break.h>
+#include <asm/ia32.h>
+#include <asm/kregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_XEN
+#define ia64_ivt xen_ivt
+#endif
+
+#if 1
+# define PSR_DEFAULT_BITS      psr.ac
+#else
+# define PSR_DEFAULT_BITS      0
+#endif
+
+#if 0
+  /*
+   * This lets you track the last eight faults that occurred on the CPU.  Make sure ar.k2 isn't
+   * needed for something else before enabling this...
+   */
+# define DBG_FAULT(i)  mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
+#else
+# define DBG_FAULT(i)
+#endif
+
+#define MINSTATE_VIRT  /* needed by minstate.h */
+#include "xenminstate.h"
+
+#define FAULT(n)                                                                       \
+       mov r31=pr;                                                                     \
+       mov r19=n;;                     /* prepare to save predicates */                \
+       br.sptk.many dispatch_to_fault_handler
+
+       .section .text.ivt,"ax"
+
+       .align 32768    // align on 32KB boundary
+       .global ia64_ivt
+ia64_ivt:
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+ENTRY(vhpt_miss)
+       DBG_FAULT(0)
+       /*
+        * The VHPT vector is invoked when the TLB entry for the virtual page table
+        * is missing.  This happens only as a result of a previous
+        * (the "original") TLB miss, which may either be caused by an instruction
+        * fetch or a data access (or non-access).
+        *
+        * What we do here is normal TLB miss handing for the _original_ miss,
+        * followed by inserting the TLB entry for the virtual page table page
+        * that the VHPT walker was attempting to access.  The latter gets
+        * inserted as long as page table entry above pte level have valid
+        * mappings for the faulting address.  The TLB entry for the original
+        * miss gets inserted only if the pte entry indicates that the page is
+        * present.
+        *
+        * do_page_fault gets invoked in the following cases:
+        *      - the faulting virtual address uses unimplemented address bits
+        *      - the faulting virtual address has no valid page table mapping
+        */
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+#ifdef CONFIG_HUGETLB_PAGE
+       movl r18=PAGE_SHIFT
+       movl r25=XSI_ITIR
+       ;;
+       ld8 r25=[r25]
+#endif
+       ;;
+#else
+       mov r16=cr.ifa                          // get address that caused the TLB miss
+#ifdef CONFIG_HUGETLB_PAGE
+       movl r18=PAGE_SHIFT
+       mov r25=cr.itir
+#endif
+#endif
+       ;;
+#ifdef CONFIG_XEN
+       XEN_HYPER_RSM_PSR_DT;
+#else
+       rsm psr.dt                              // use physical addressing for data
+#endif
+       mov r31=pr                              // save the predicate registers
+       mov r19=IA64_KR(PT_BASE)                // get page table base address
+       shl r21=r16,3                           // shift bit 60 into sign bit
+       shr.u r17=r16,61                        // get the region number into r17
+       ;;
+       shr.u r22=r21,3
+#ifdef CONFIG_HUGETLB_PAGE
+       extr.u r26=r25,2,6
+       ;;
+       cmp.ne p8,p0=r18,r26
+       sub r27=r26,r18
+       ;;
+(p8)   dep r25=r18,r25,2,6
+(p8)   shr r22=r22,r27
+#endif
+       ;;
+       cmp.eq p6,p7=5,r17                      // is IFA pointing into to region 5?
+       shr.u r18=r22,PGDIR_SHIFT               // get bottom portion of pgd index bit
+       ;;
+(p7)   dep r17=r17,r19,(PAGE_SHIFT-3),3        // put region number bits in place
+
+       srlz.d
+       LOAD_PHYSICAL(p6, r19, swapper_pg_dir)  // region 5 is rooted at swapper_pg_dir
+
+       .pred.rel "mutex", p6, p7
+(p6)   shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7)   shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+       ;;
+(p6)   dep r17=r18,r19,3,(PAGE_SHIFT-3)        // r17=pgd_offset for region 5
+(p7)   dep r17=r18,r17,3,(PAGE_SHIFT-6)        // r17=pgd_offset for region[0-4]
+       cmp.eq p7,p6=0,r21                      // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+       shr.u r28=r22,PUD_SHIFT                 // shift pud index into position
+#else
+       shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
+#endif
+       ;;
+       ld8 r17=[r17]                           // get *pgd (may be 0)
+       ;;
+(p7)   cmp.eq p6,p7=r17,r0                     // was pgd_present(*pgd) == NULL?
+#ifdef CONFIG_PGTABLE_4
+       dep r28=r28,r17,3,(PAGE_SHIFT-3)        // r28=pud_offset(pgd,addr)
+       ;;
+       shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
+(p7)   ld8 r29=[r28]                           // get *pud (may be 0)
+       ;;
+(p7)   cmp.eq.or.andcm p6,p7=r29,r0            // was pud_present(*pud) == NULL?
+       dep r17=r18,r29,3,(PAGE_SHIFT-3)        // r17=pmd_offset(pud,addr)
+#else
+       dep r17=r18,r17,3,(PAGE_SHIFT-3)        // r17=pmd_offset(pgd,addr)
+#endif
+       ;;
+(p7)   ld8 r20=[r17]                           // get *pmd (may be 0)
+       shr.u r19=r22,PAGE_SHIFT                // shift pte index into position
+       ;;
+(p7)   cmp.eq.or.andcm p6,p7=r20,r0            // was pmd_present(*pmd) == NULL?
+       dep r21=r19,r20,3,(PAGE_SHIFT-3)        // r21=pte_offset(pmd,addr)
+       ;;
+(p7)   ld8 r18=[r21]                           // read *pte
+#ifdef CONFIG_XEN
+       movl r19=XSI_ISR
+       ;;
+       ld8 r19=[r19]
+#else
+       mov r19=cr.isr                          // cr.isr bit 32 tells us if this is an insn miss
+#endif
+       ;;
+(p7)   tbit.z p6,p7=r18,_PAGE_P_BIT            // page present bit cleared?
+#ifdef CONFIG_XEN
+       movl r22=XSI_IHA
+       ;;
+       ld8 r22=[r22]
+#else
+       mov r22=cr.iha                          // get the VHPT address that caused the TLB miss
+#endif
+       ;;                                      // avoid RAW on p7
+(p7)   tbit.nz.unc p10,p11=r19,32              // is it an instruction TLB miss?
+       dep r23=0,r20,0,PAGE_SHIFT              // clear low bits to get page address
+       ;;
+#ifdef CONFIG_XEN
+       mov r24=r8
+       mov r8=r18
+       ;;
+(p10)  XEN_HYPER_ITC_I
+       ;;
+(p11)  XEN_HYPER_ITC_D
+       ;;
+       mov r8=r24
+       ;;
+#else
+(p10)  itc.i r18                               // insert the instruction TLB entry
+(p11)  itc.d r18                               // insert the data TLB entry
+#endif
+(p6)   br.cond.spnt.many page_fault            // handle bad address/page not present (page fault)
+#ifdef CONFIG_XEN
+       movl r24=XSI_IFA
+       ;;
+       st8 [r24]=r22
+       ;;
+#else
+       mov cr.ifa=r22
+#endif
+
+#ifdef CONFIG_HUGETLB_PAGE
+(p8)   mov cr.itir=r25                         // change to default page-size for VHPT
+#endif
+
+       /*
+        * Now compute and insert the TLB entry for the virtual page table.  We never
+        * execute in a page table page so there is no need to set the exception deferral
+        * bit.
+        */
+       adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
+       ;;
+#ifdef CONFIG_XEN
+(p7)   mov r25=r8
+(p7)   mov r8=r24
+       ;;
+(p7)   XEN_HYPER_ITC_D
+       ;;
+(p7)   mov r8=r25
+       ;;
+#else
+(p7)   itc.d r24
+#endif
+       ;;
+#ifdef CONFIG_SMP
+       /*
+        * Tell the assemblers dependency-violation checker that the above "itc" instructions
+        * cannot possibly affect the following loads:
+        */
+       dv_serialize_data
+
+       /*
+        * Re-check pagetable entry.  If they changed, we may have received a ptc.g
+        * between reading the pagetable and the "itc".  If so, flush the entry we
+        * inserted and retry.  At this point, we have:
+        *
+        * r28 = equivalent of pud_offset(pgd, ifa)
+        * r17 = equivalent of pmd_offset(pud, ifa)
+        * r21 = equivalent of pte_offset(pmd, ifa)
+        *
+        * r29 = *pud
+        * r20 = *pmd
+        * r18 = *pte
+        */
+       ld8 r25=[r21]                           // read *pte again
+       ld8 r26=[r17]                           // read *pmd again
+#ifdef CONFIG_PGTABLE_4
+       ld8 r19=[r28]                           // read *pud again
+#endif
+       cmp.ne p6,p7=r0,r0
+       ;;
+       cmp.ne.or.andcm p6,p7=r26,r20           // did *pmd change
+#ifdef CONFIG_PGTABLE_4
+       cmp.ne.or.andcm p6,p7=r19,r29           // did *pud change
+#endif
+       mov r27=PAGE_SHIFT<<2
+       ;;
+(p6)   ptc.l r22,r27                           // purge PTE page translation
+(p7)   cmp.ne.or.andcm p6,p7=r25,r18           // did *pte change
+       ;;
+(p6)   ptc.l r16,r27                           // purge translation
+#endif
+
+       mov pr=r31,-1                           // restore predicate registers
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI
+       dv_serialize_data
+#else
+       rfi
+#endif
+END(vhpt_miss)
+
+       .org ia64_ivt+0x400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+ENTRY(itlb_miss)
+       DBG_FAULT(1)
+       /*
+        * The ITLB handler accesses the PTE via the virtually mapped linear
+        * page table.  If a nested TLB miss occurs, we switch into physical
+        * mode, walk the page table, and then re-execute the PTE read and
+        * go on normally after that.
+        */
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+#else
+       mov r16=cr.ifa                          // get virtual address
+#endif
+       mov r29=b0                              // save b0
+       mov r31=pr                              // save predicates
+.itlb_fault:
+#ifdef CONFIG_XEN
+       movl r17=XSI_IHA
+       ;;
+       ld8 r17=[r17]                           // get virtual address of L3 PTE
+#else
+       mov r17=cr.iha                          // get virtual address of PTE
+#endif
+       movl r30=1f                             // load nested fault continuation point
+       ;;
+1:     ld8 r18=[r17]                           // read *pte
+       ;;
+       mov b0=r29
+       tbit.z p6,p0=r18,_PAGE_P_BIT            // page present bit cleared?
+(p6)   br.cond.spnt page_fault
+       ;;
+#ifdef CONFIG_XEN
+       mov r19=r8
+       mov r8=r18
+       ;;
+       XEN_HYPER_ITC_I
+       ;;
+       mov r8=r19
+#else
+       itc.i r18
+#endif
+       ;;
+#ifdef CONFIG_SMP
+       /*
+        * Tell the assemblers dependency-violation checker that the above "itc" instructions
+        * cannot possibly affect the following loads:
+        */
+       dv_serialize_data
+
+       ld8 r19=[r17]                           // read *pte again and see if same
+       mov r20=PAGE_SHIFT<<2                   // setup page size for purge
+       ;;
+       cmp.ne p7,p0=r18,r19
+       ;;
+(p7)   ptc.l r16,r20
+#endif
+       mov pr=r31,-1
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI
+       dv_serialize_data
+#else
+       rfi
+#endif
+END(itlb_miss)
+
+       .org ia64_ivt+0x0800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+ENTRY(dtlb_miss)
+       DBG_FAULT(2)
+       /*
+        * The DTLB handler accesses the PTE via the virtually mapped linear
+        * page table.  If a nested TLB miss occurs, we switch into physical
+        * mode, walk the page table, and then re-execute the PTE read and
+        * go on normally after that.
+        */
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+#else
+       mov r16=cr.ifa                          // get virtual address
+#endif
+       mov r29=b0                              // save b0
+       mov r31=pr                              // save predicates
+dtlb_fault:
+#ifdef CONFIG_XEN
+       movl r17=XSI_IHA
+       ;;
+       ld8 r17=[r17]                           // get virtual address of L3 PTE
+#else
+       mov r17=cr.iha                          // get virtual address of PTE
+#endif
+       movl r30=1f                             // load nested fault continuation point
+       ;;
+1:     ld8 r18=[r17]                           // read *pte
+       ;;
+       mov b0=r29
+       tbit.z p6,p0=r18,_PAGE_P_BIT            // page present bit cleared?
+(p6)   br.cond.spnt page_fault
+       ;;
+#ifdef CONFIG_XEN
+       mov r19=r8
+       mov r8=r18
+       ;;
+       XEN_HYPER_ITC_D
+       ;;
+       mov r8=r19
+       ;;
+#else
+       itc.d r18
+#endif
+       ;;
+#ifdef CONFIG_SMP
+       /*
+        * Tell the assemblers dependency-violation checker that the above "itc" instructions
+        * cannot possibly affect the following loads:
+        */
+       dv_serialize_data
+
+       ld8 r19=[r17]                           // read *pte again and see if same
+       mov r20=PAGE_SHIFT<<2                   // setup page size for purge
+       ;;
+       cmp.ne p7,p0=r18,r19
+       ;;
+(p7)   ptc.l r16,r20
+#endif
+       mov pr=r31,-1
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI
+       dv_serialize_data
+#else
+       rfi
+#endif
+END(dtlb_miss)
+
+       .org ia64_ivt+0x0c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+ENTRY(alt_itlb_miss)
+       DBG_FAULT(3)
+#ifdef CONFIG_XEN
+       movl r31=XSI_IPSR
+       ;;
+       ld8 r21=[r31],XSI_IFA_OFS-XSI_IPSR_OFS  // get ipsr, point to ifa
+       movl r17=PAGE_KERNEL
+       ;;
+       ld8 r16=[r31]           // get ifa
+#else
+       mov r16=cr.ifa          // get address that caused the TLB miss
+       movl r17=PAGE_KERNEL
+       mov r21=cr.ipsr
+#endif
+       movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+       mov r31=pr
+       ;;
+#ifdef CONFIG_DISABLE_VHPT
+       shr.u r22=r16,61                        // get the region number into r21
+       ;;
+       cmp.gt p8,p0=6,r22                      // user mode
+       ;;
+#ifndef CONFIG_XEN
+(p8)   thash r17=r16
+       ;;
+(p8)   mov cr.iha=r17
+#endif
+(p8)   mov r29=b0                              // save b0
+(p8)   br.cond.dptk .itlb_fault
+#endif
+       extr.u r23=r21,IA64_PSR_CPL0_BIT,2      // extract psr.cpl
+       and r19=r19,r16         // clear ed, reserved bits, and PTE control bits
+       shr.u r18=r16,57        // move address bit 61 to bit 4
+       ;;
+       andcm r18=0x10,r18      // bit 4=~address-bit(61)
+       cmp.ne p8,p0=r0,r23     // psr.cpl != 0?
+       or r19=r17,r19          // insert PTE control bits into r19
+       ;;
+       or r19=r19,r18          // set bit 4 (uncached) if the access was to region 6
+(p8)   br.cond.spnt page_fault
+       ;;
+#ifdef CONFIG_XEN
+       mov r18=r8
+       mov r8=r19
+       ;;
+       XEN_HYPER_ITC_I
+       ;;
+       mov r8=r18
+       ;;
+       mov pr=r31,-1
+       ;;
+       XEN_HYPER_RFI;
+#else
+       itc.i r19               // insert the TLB entry
+       mov pr=r31,-1
+       rfi
+#endif
+END(alt_itlb_miss)
+
+       .org ia64_ivt+0x1000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+ENTRY(alt_dtlb_miss)
+       DBG_FAULT(4)
+#ifdef CONFIG_XEN
+       movl r31=XSI_IPSR
+       ;;
+       ld8 r21=[r31],XSI_ISR_OFS-XSI_IPSR_OFS  // get ipsr, point to isr
+       movl r17=PAGE_KERNEL
+       ;;
+       ld8 r20=[r31],XSI_IFA_OFS-XSI_ISR_OFS   // get isr, point to ifa
+       movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+       ;;
+       ld8 r16=[r31]           // get ifa
+#else
+       mov r16=cr.ifa          // get address that caused the TLB miss
+       movl r17=PAGE_KERNEL
+       mov r20=cr.isr
+       movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+       mov r21=cr.ipsr
+#endif
+       mov r31=pr
+       ;;
+#ifdef CONFIG_DISABLE_VHPT
+       shr.u r22=r16,61                        // get the region number into r21
+       ;;
+       cmp.gt p8,p0=6,r22                      // access to region 0-5
+       ;;
+#ifndef CONFIG_XEN
+(p8)   thash r17=r16
+       ;;
+(p8)   mov cr.iha=r17
+#endif
+(p8)   mov r29=b0                              // save b0
+(p8)   br.cond.dptk dtlb_fault
+#endif
+       extr.u r23=r21,IA64_PSR_CPL0_BIT,2      // extract psr.cpl
+       and r22=IA64_ISR_CODE_MASK,r20          // get the isr.code field
+       tbit.nz p6,p7=r20,IA64_ISR_SP_BIT       // is speculation bit on?
+       shr.u r18=r16,57                        // move address bit 61 to bit 4
+       and r19=r19,r16                         // clear ed, reserved bits, and PTE control bits
+       tbit.nz p9,p0=r20,IA64_ISR_NA_BIT       // is non-access bit on?
+       ;;
+       andcm r18=0x10,r18      // bit 4=~address-bit(61)
+       cmp.ne p8,p0=r0,r23
+(p9)   cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22  // check isr.code field
+(p8)   br.cond.spnt page_fault
+
+       dep r21=-1,r21,IA64_PSR_ED_BIT,1
+       or r19=r19,r17          // insert PTE control bits into r19
+       ;;
+       or r19=r19,r18          // set bit 4 (uncached) if the access was to region 6
+(p6)   mov cr.ipsr=r21
+       ;;
+#ifdef CONFIG_XEN
+(p7)   mov r18=r8
+(p7)   mov r8=r19
+       ;;
+(p7)   XEN_HYPER_ITC_D
+       ;;
+(p7)   mov r8=r18
+       ;;
+       mov pr=r31,-1
+       ;;
+       XEN_HYPER_RFI;
+#else
+(p7)   itc.d r19               // insert the TLB entry
+       mov pr=r31,-1
+       rfi
+#endif
+END(alt_dtlb_miss)
+
+       .org ia64_ivt+0x1400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
+ENTRY(nested_dtlb_miss)
+       /*
+        * In the absence of kernel bugs, we get here when the virtually mapped linear
+        * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
+        * Access-bit, or Data Access-bit faults).  If the DTLB entry for the virtual page
+        * table is missing, a nested TLB miss fault is triggered and control is
+        * transferred to this point.  When this happens, we lookup the pte for the
+        * faulting address by walking the page table in physical mode and return to the
+        * continuation point passed in register r30 (or call page_fault if the address is
+        * not mapped).
+        *
+        * Input:       r16:    faulting address
+        *              r29:    saved b0
+        *              r30:    continuation address
+        *              r31:    saved pr
+        *
+        * Output:      r17:    physical address of PTE of faulting address
+        *              r29:    saved b0
+        *              r30:    continuation address
+        *              r31:    saved pr
+        *
+        * Clobbered:   b0, r18, r19, r21, r22, psr.dt (cleared)
+        */
+#ifdef CONFIG_XEN
+       XEN_HYPER_RSM_PSR_DT;
+#else
+       rsm psr.dt                              // switch to using physical data addressing
+#endif
+       mov r19=IA64_KR(PT_BASE)                // get the page table base address
+       shl r21=r16,3                           // shift bit 60 into sign bit
+#ifdef CONFIG_XEN
+       movl r18=XSI_ITIR
+       ;;
+       ld8 r18=[r18]
+#else
+       mov r18=cr.itir
+#endif
+       ;;
+       shr.u r17=r16,61                        // get the region number into r17
+       extr.u r18=r18,2,6                      // get the faulting page size
+       ;;
+       cmp.eq p6,p7=5,r17                      // is faulting address in region 5?
+       add r22=-PAGE_SHIFT,r18                 // adjustment for hugetlb address
+       add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+       ;;
+       shr.u r22=r16,r22
+       shr.u r18=r16,r18
+(p7)   dep r17=r17,r19,(PAGE_SHIFT-3),3        // put region number bits in place
+
+       srlz.d
+       LOAD_PHYSICAL(p6, r19, swapper_pg_dir)  // region 5 is rooted at swapper_pg_dir
+
+       .pred.rel "mutex", p6, p7
+(p6)   shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7)   shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+       ;;
+(p6)   dep r17=r18,r19,3,(PAGE_SHIFT-3)        // r17=pgd_offset for region 5
+(p7)   dep r17=r18,r17,3,(PAGE_SHIFT-6)        // r17=pgd_offset for region[0-4]
+       cmp.eq p7,p6=0,r21                      // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+       shr.u r18=r22,PUD_SHIFT                 // shift pud index into position
+#else
+       shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
+#endif
+       ;;
+       ld8 r17=[r17]                           // get *pgd (may be 0)
+       ;;
+(p7)   cmp.eq p6,p7=r17,r0                     // was pgd_present(*pgd) == NULL?
+       dep r17=r18,r17,3,(PAGE_SHIFT-3)        // r17=p[u|m]d_offset(pgd,addr)
+       ;;
+#ifdef CONFIG_PGTABLE_4
+(p7)   ld8 r17=[r17]                           // get *pud (may be 0)
+       shr.u r18=r22,PMD_SHIFT                 // shift pmd index into position
+       ;;
+(p7)   cmp.eq.or.andcm p6,p7=r17,r0            // was pud_present(*pud) == NULL?
+       dep r17=r18,r17,3,(PAGE_SHIFT-3)        // r17=pmd_offset(pud,addr)
+       ;;
+#endif
+(p7)   ld8 r17=[r17]                           // get *pmd (may be 0)
+       shr.u r19=r22,PAGE_SHIFT                // shift pte index into position
+       ;;
+(p7)   cmp.eq.or.andcm p6,p7=r17,r0            // was pmd_present(*pmd) == NULL?
+       dep r17=r19,r17,3,(PAGE_SHIFT-3)        // r17=pte_offset(pmd,addr);
+(p6)   br.cond.spnt page_fault
+       mov b0=r30
+       br.sptk.many b0                         // return to continuation point
+END(nested_dtlb_miss)
+
+       .org ia64_ivt+0x1800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+ENTRY(ikey_miss)
+       DBG_FAULT(6)
+       FAULT(6)
+END(ikey_miss)
+
+       //-----------------------------------------------------------------------------------
+       // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
+ENTRY(page_fault)
+#ifdef CONFIG_XEN
+       XEN_HYPER_SSM_PSR_DT
+#else
+       ssm psr.dt
+       ;;
+       srlz.i
+#endif
+       ;;
+       SAVE_MIN_WITH_COVER
+       alloc r15=ar.pfs,0,0,3,0
+#ifdef CONFIG_XEN
+       movl r3=XSI_ISR
+       ;;
+       ld8 out1=[r3],XSI_IFA_OFS-XSI_ISR_OFS   // get vcr.isr, point to ifa
+       ;;
+       ld8 out0=[r3]                           // get vcr.ifa
+       mov r14=1
+       ;;
+       add r3=XSI_PSR_IC_OFS-XSI_IFA_OFS, r3   // point to vpsr.ic
+       ;;
+       st4 [r3]=r14                            // vpsr.ic = 1
+       adds r3=8,r2                            // set up second base pointer
+       ;;
+#else
+       mov out0=cr.ifa
+       mov out1=cr.isr
+       adds r3=8,r2                            // set up second base pointer
+       ;;
+       ssm psr.ic | PSR_DEFAULT_BITS
+       ;;
+       srlz.i                                  // guarantee that interruption collectin is on
+       ;;
+#endif
+#ifdef CONFIG_XEN
+       br.cond.sptk.many       xen_page_fault
+       ;;
+done_xen_page_fault:
+#endif
+(p15)  ssm psr.i                               // restore psr.i
+       movl r14=ia64_leave_kernel
+       ;;
+       SAVE_REST
+       mov rp=r14
+       ;;
+       adds out2=16,r12                        // out2 = pointer to pt_regs
+       br.call.sptk.many b6=ia64_do_page_fault // ignore return address
+END(page_fault)
+
+       .org ia64_ivt+0x1c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ENTRY(dkey_miss)
+       DBG_FAULT(7)
+       FAULT(7)
+#ifdef CONFIG_XEN
+       // Leaving this code inline above results in an IVT section overflow
+       // There is no particular reason for this code to be here...
+xen_page_fault:
+(p15)  movl r3=XSI_PSR_I_ADDR
+       ;;
+(p15)  ld8 r3=[r3]
+       ;;
+(p15)  st1 [r3]=r0,XSI_PEND_OFS-XSI_PSR_I_ADDR_OFS     // if (p15) vpsr.i = 1
+       mov r14=r0
+       ;;
+(p15)  ld4 r14=[r3]                            // if (pending_interrupts)
+       adds r3=8,r2                            // re-set up second base pointer
+       ;;
+(p15)  cmp.ne  p15,p0=r14,r0
+       ;;
+       br.cond.sptk.many done_xen_page_fault
+       ;;
+#endif
+END(dkey_miss)
+
+       .org ia64_ivt+0x2000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
+ENTRY(dirty_bit)
+       DBG_FAULT(8)
+       /*
+        * What we do here is to simply turn on the dirty bit in the PTE.  We need to
+        * update both the page-table and the TLB entry.  To efficiently access the PTE,
+        * we address it through the virtual page table.  Most likely, the TLB entry for
+        * the relevant virtual page table page is still present in the TLB so we can
+        * normally do this without additional TLB misses.  In case the necessary virtual
+        * page table TLB entry isn't present, we take a nested TLB miss hit where we look
+        * up the physical address of the L3 PTE and then continue at label 1 below.
+        */
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+       ;;
+#else
+       mov r16=cr.ifa                          // get the address that caused the fault
+#endif
+       movl r30=1f                             // load continuation point in case of nested fault
+       ;;
+#ifdef CONFIG_XEN
+       mov r18=r8;
+       mov r8=r16;
+       XEN_HYPER_THASH;;
+       mov r17=r8;
+       mov r8=r18;;
+#else
+       thash r17=r16                           // compute virtual address of L3 PTE
+#endif
+       mov r29=b0                              // save b0 in case of nested fault
+       mov r31=pr                              // save pr
+#ifdef CONFIG_SMP
+       mov r28=ar.ccv                          // save ar.ccv
+       ;;
+1:     ld8 r18=[r17]
+       ;;                                      // avoid RAW on r18
+       mov ar.ccv=r18                          // set compare value for cmpxchg
+       or r25=_PAGE_D|_PAGE_A,r18              // set the dirty and accessed bits
+       tbit.z p7,p6 = r18,_PAGE_P_BIT          // Check present bit
+       ;;
+(p6)   cmpxchg8.acq r26=[r17],r25,ar.ccv       // Only update if page is present
+       mov r24=PAGE_SHIFT<<2
+       ;;
+(p6)   cmp.eq p6,p7=r26,r18                    // Only compare if page is present
+       ;;
+#ifdef CONFIG_XEN
+(p6)   mov r18=r8
+(p6)   mov r8=r25
+       ;;
+(p6)   XEN_HYPER_ITC_D
+       ;;
+(p6)   mov r8=r18
+#else
+(p6)   itc.d r25                               // install updated PTE
+#endif 
+       ;;
+       /*
+        * Tell the assemblers dependency-violation checker that the above "itc" instructions
+        * cannot possibly affect the following loads:
+        */
+       dv_serialize_data
+
+       ld8 r18=[r17]                           // read PTE again
+       ;;
+       cmp.eq p6,p7=r18,r25                    // is it same as the newly installed
+       ;;
+(p7)   ptc.l r16,r24
+       mov b0=r29                              // restore b0
+       mov ar.ccv=r28
+#else
+       ;;
+1:     ld8 r18=[r17]
+       ;;                                      // avoid RAW on r18
+       or r18=_PAGE_D|_PAGE_A,r18              // set the dirty and accessed bits
+       mov b0=r29                              // restore b0
+       ;;
+       st8 [r17]=r18                           // store back updated PTE
+       itc.d r18                               // install updated PTE
+#endif
+       mov pr=r31,-1                           // restore pr
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI
+       dv_serialize_data
+#else
+       rfi
+#endif
+END(dirty_bit)
+
+       .org ia64_ivt+0x2400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+ENTRY(iaccess_bit)
+       DBG_FAULT(9)
+       // Like Entry 8, except for instruction access
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+       ;;
+#else
+       mov r16=cr.ifa                          // get the address that caused the fault
+#endif
+       movl r30=1f                             // load continuation point in case of nested fault
+       mov r31=pr                              // save predicates
+#ifdef CONFIG_ITANIUM
+       /*
+        * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
+        */
+       mov r17=cr.ipsr
+       ;;
+       mov r18=cr.iip
+       tbit.z p6,p0=r17,IA64_PSR_IS_BIT        // IA64 instruction set?
+       ;;
+(p6)   mov r16=r18                             // if so, use cr.iip instead of cr.ifa
+#endif /* CONFIG_ITANIUM */
+       ;;
+#ifdef CONFIG_XEN
+       mov r18=r8;
+       mov r8=r16;
+       XEN_HYPER_THASH;;
+       mov r17=r8;
+       mov r8=r18;;
+#else
+       thash r17=r16                           // compute virtual address of L3 PTE
+#endif
+       mov r29=b0                              // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+       mov r28=ar.ccv                          // save ar.ccv
+       ;;
+1:     ld8 r18=[r17]
+       ;;
+       mov ar.ccv=r18                          // set compare value for cmpxchg
+       or r25=_PAGE_A,r18                      // set the accessed bit
+       tbit.z p7,p6 = r18,_PAGE_P_BIT          // Check present bit
+       ;;
+(p6)   cmpxchg8.acq r26=[r17],r25,ar.ccv       // Only if page present
+       mov r24=PAGE_SHIFT<<2
+       ;;
+(p6)   cmp.eq p6,p7=r26,r18                    // Only if page present
+       ;;
+#ifdef CONFIG_XEN
+       mov r26=r8
+       mov r8=r25
+       ;;
+(p6)   XEN_HYPER_ITC_I
+       ;;
+       mov r8=r26
+       ;;
+#else
+(p6)   itc.i r25                               // install updated PTE
+#endif
+       ;;
+       /*
+        * Tell the assemblers dependency-violation checker that the above "itc" instructions
+        * cannot possibly affect the following loads:
+        */
+       dv_serialize_data
+
+       ld8 r18=[r17]                           // read PTE again
+       ;;
+       cmp.eq p6,p7=r18,r25                    // is it same as the newly installed
+       ;;
+(p7)   ptc.l r16,r24
+       mov b0=r29                              // restore b0
+       mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+       ;;
+1:     ld8 r18=[r17]
+       ;;
+       or r18=_PAGE_A,r18                      // set the accessed bit
+       mov b0=r29                              // restore b0
+       ;;
+       st8 [r17]=r18                           // store back updated PTE
+       itc.i r18                               // install updated PTE
+#endif /* !CONFIG_SMP */
+       mov pr=r31,-1
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI
+       dv_serialize_data
+#else
+       rfi
+#endif
+END(iaccess_bit)
+
+       .org ia64_ivt+0x2800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+ENTRY(daccess_bit)
+       DBG_FAULT(10)
+       // Like Entry 8, except for data access
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+       ;;
+#else
+       mov r16=cr.ifa                          // get the address that caused the fault
+#endif
+       movl r30=1f                             // load continuation point in case of nested fault
+       ;;
+#ifdef CONFIG_XEN
+       mov r18=r8
+       mov r8=r16
+       XEN_HYPER_THASH
+       ;;
+       mov r17=r8
+       mov r8=r18
+       ;;
+#else
+       thash r17=r16                           // compute virtual address of L3 PTE
+#endif
+       mov r31=pr
+       mov r29=b0                              // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+       mov r28=ar.ccv                          // save ar.ccv
+       ;;
+1:     ld8 r18=[r17]
+       ;;                                      // avoid RAW on r18
+       mov ar.ccv=r18                          // set compare value for cmpxchg
+       or r25=_PAGE_A,r18                      // set the dirty bit
+       tbit.z p7,p6 = r18,_PAGE_P_BIT          // Check present bit
+       ;;
+(p6)   cmpxchg8.acq r26=[r17],r25,ar.ccv       // Only if page is present
+       mov r24=PAGE_SHIFT<<2
+       ;;
+(p6)   cmp.eq p6,p7=r26,r18                    // Only if page is present
+       ;;
+#ifdef CONFIG_XEN
+       mov r26=r8
+       mov r8=r25
+       ;;
+(p6)   XEN_HYPER_ITC_D
+       ;;
+       mov r8=r26
+       ;;
+#else
+(p6)   itc.d r25                               // install updated PTE
+#endif
+       /*
+        * Tell the assemblers dependency-violation checker that the above "itc" instructions
+        * cannot possibly affect the following loads:
+        */
+       dv_serialize_data
+       ;;
+       ld8 r18=[r17]                           // read PTE again
+       ;;
+       cmp.eq p6,p7=r18,r25                    // is it same as the newly installed
+       ;;
+(p7)   ptc.l r16,r24
+       mov ar.ccv=r28
+#else
+       ;;
+1:     ld8 r18=[r17]
+       ;;                                      // avoid RAW on r18
+       or r18=_PAGE_A,r18                      // set the accessed bit
+       ;;
+       st8 [r17]=r18                           // store back updated PTE
+       itc.d r18                               // install updated PTE
+#endif
+       mov b0=r29                              // restore b0
+       mov pr=r31,-1
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI
+       dv_serialize_data
+#else
+       rfi
+#endif
+END(daccess_bit)
+
+       .org ia64_ivt+0x2c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+ENTRY(break_fault)
+       /*
+        * The streamlined system call entry/exit paths only save/restore the initial part
+        * of pt_regs.  This implies that the callers of system-calls must adhere to the
+        * normal procedure calling conventions.
+        *
+        *   Registers to be saved & restored:
+        *      CR registers: cr.ipsr, cr.iip, cr.ifs
+        *      AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
+        *      others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
+        *   Registers to be restored only:
+        *      r8-r11: output value from the system call.
+        *
+        * During system call exit, scratch registers (including r15) are modified/cleared
+        * to prevent leaking bits from kernel to user level.
+        */
+       DBG_FAULT(11)
+       mov.m r16=IA64_KR(CURRENT)              // M2 r16 <- current task (12 cyc)
+#ifdef CONFIG_XEN
+       movl r22=XSI_IPSR
+       ;;
+       ld8 r29=[r22],XSI_IIM_OFS-XSI_IPSR_OFS  // get ipsr, point to iip
+#else
+       mov r29=cr.ipsr                         // M2 (12 cyc)
+#endif
+       mov r31=pr                              // I0 (2 cyc)
+
+#ifdef CONFIG_XEN
+       ;;
+       ld8 r17=[r22],XSI_IIP_OFS-XSI_IIM_OFS
+#else
+       mov r17=cr.iim                          // M2 (2 cyc)
+#endif
+       mov.m r27=ar.rsc                        // M2 (12 cyc)
+       mov r18=__IA64_BREAK_SYSCALL            // A
+
+       mov.m ar.rsc=0                          // M2
+       mov.m r21=ar.fpsr                       // M2 (12 cyc)
+       mov r19=b6                              // I0 (2 cyc)
+       ;;
+       mov.m r23=ar.bspstore                   // M2 (12 cyc)
+       mov.m r24=ar.rnat                       // M2 (5 cyc)
+       mov.i r26=ar.pfs                        // I0 (2 cyc)
+
+       invala                                  // M0|1
+       nop.m 0                                 // M
+       mov r20=r1                              // A                    save r1
+
+       nop.m 0
+       movl r30=sys_call_table                 // X
+
+#ifdef CONFIG_XEN
+       ld8 r28=[r22]
+#else
+       mov r28=cr.iip                          // M2 (2 cyc)
+#endif
+       cmp.eq p0,p7=r18,r17                    // I0 is this a system call?
+(p7)   br.cond.spnt non_syscall                // B  no ->
+       //
+       // From this point on, we are definitely on the syscall-path
+       // and we can use (non-banked) scratch registers.
+       //
+///////////////////////////////////////////////////////////////////////
+       mov r1=r16                              // A    move task-pointer to "addl"-addressable reg
+       mov r2=r16                              // A    setup r2 for ia64_syscall_setup
+       add r9=TI_FLAGS+IA64_TASK_SIZE,r16      // A    r9 = &current_thread_info()->flags
+
+       adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
+       adds r15=-1024,r15                      // A    subtract 1024 from syscall number
+       mov r3=NR_syscalls - 1
+       ;;
+       ld1.bias r17=[r16]                      // M0|1 r17 = current->thread.on_ustack flag
+       ld4 r9=[r9]                             // M0|1 r9 = current_thread_info()->flags
+       extr.u r8=r29,41,2                      // I0   extract ei field from cr.ipsr
+
+       shladd r30=r15,3,r30                    // A    r30 = sys_call_table + 8*(syscall-1024)
+       addl r22=IA64_RBS_OFFSET,r1             // A    compute base of RBS
+       cmp.leu p6,p7=r15,r3                    // A    syscall number in range?
+       ;;
+
+       lfetch.fault.excl.nt1 [r22]             // M0|1 prefetch RBS
+(p6)   ld8 r30=[r30]                           // M0|1 load address of syscall entry point
+       tnat.nz.or p7,p0=r15                    // I0   is syscall nr a NaT?
+
+       mov.m ar.bspstore=r22                   // M2   switch to kernel RBS
+       cmp.eq p8,p9=2,r8                       // A    isr.ei==2?
+       ;;
+
+(p8)   mov r8=0                                // A    clear ei to 0
+(p7)   movl r30=sys_ni_syscall                 // X
+
+(p8)   adds r28=16,r28                         // A    switch cr.iip to next bundle
+(p9)   adds r8=1,r8                            // A    increment ei to next slot
+       nop.i 0
+       ;;
+
+       mov.m r25=ar.unat                       // M2 (5 cyc)
+       dep r29=r8,r29,41,2                     // I0   insert new ei into cr.ipsr
+       adds r15=1024,r15                       // A    restore original syscall number
+       //
+       // If any of the above loads miss in L1D, we'll stall here until
+       // the data arrives.
+       //
+///////////////////////////////////////////////////////////////////////
+       st1 [r16]=r0                            // M2|3 clear current->thread.on_ustack flag
+       mov b6=r30                              // I0   setup syscall handler branch reg early
+       cmp.eq pKStk,pUStk=r0,r17               // A    were we on kernel stacks already?
+
+       and r9=_TIF_SYSCALL_TRACEAUDIT,r9       // A    mask trace or audit
+       mov r18=ar.bsp                          // M2 (12 cyc)
+(pKStk)        br.cond.spnt .break_fixup               // B    we're already in kernel-mode -- fix up RBS
+       ;;
+.back_from_break_fixup:
+(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A    compute base of memory stack
+       cmp.eq p14,p0=r9,r0                     // A    are syscalls being traced/audited?
+       br.call.sptk.many b7=ia64_syscall_setup // B
+1:
+       mov ar.rsc=0x3                          // M2   set eager mode, pl 0, LE, loadrs=0
+       nop 0
+#ifdef CONFIG_XEN
+       mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2;;
+#else
+       bsw.1                                   // B (6 cyc) regs are saved, switch to bank 1
+#endif
+       ;;
+
+#ifdef CONFIG_XEN
+       movl r16=XSI_PSR_IC
+       mov r3=1
+       ;;
+       st4 [r16]=r3,XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS  // vpsr.ic = 1
+#else
+       ssm psr.ic | PSR_DEFAULT_BITS           // M2   now it's safe to re-enable intr.-collection
+#endif
+       movl r3=ia64_ret_from_syscall           // X
+       ;;
+
+       srlz.i                                  // M0   ensure interruption collection is on
+       mov rp=r3                               // I0   set the real return addr
+(p10)  br.cond.spnt.many ia64_ret_from_syscall // B    return if bad call-frame or r15 is a NaT
+
+#ifdef CONFIG_XEN
+(p15)  ld8 r16=[r16]                           // vpsr.i
+       ;;
+(p15)  st1 [r16]=r0,XSI_PEND_OFS-XSI_PSR_I_ADDR_OFS    // if (p15) vpsr.i = 1
+       mov r2=r0
+       ;;
+(p15)  ld4 r2=[r16]                            // if (pending_interrupts)
+       ;;
+       cmp.ne  p6,p0=r2,r0
+       ;;
+(p6)   ssm     psr.i                           //   do a real ssm psr.i
+#else
+(p15)  ssm psr.i                               // M2   restore psr.i
+#endif
+(p14)  br.call.sptk.many b6=b6                 // B    invoke syscall-handker (ignore return addr)
+       br.cond.spnt.many ia64_trace_syscall    // B    do syscall-tracing thingamagic
+       // NOT REACHED
+///////////////////////////////////////////////////////////////////////
+       // On entry, we optimistically assumed that we're coming from user-space.
+       // For the rare cases where a system-call is done from within the kernel,
+       // we fix things up at this point:
+.break_fixup:
+       add r1=-IA64_PT_REGS_SIZE,sp            // A    allocate space for pt_regs structure
+       mov ar.rnat=r24                         // M2   restore kernel's AR.RNAT
+       ;;
+       mov ar.bspstore=r23                     // M2   restore kernel's AR.BSPSTORE
+       br.cond.sptk .back_from_break_fixup
+END(break_fault)
+
+       .org ia64_ivt+0x3000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+ENTRY(interrupt)
+       DBG_FAULT(12)
+       mov r31=pr              // prepare to save predicates
+       ;;
+       SAVE_MIN_WITH_COVER     // uses r31; defines r2 and r3
+#ifdef CONFIG_XEN
+       movl r3=XSI_PSR_IC
+       mov r14=1
+       ;;
+       st4 [r3]=r14
+#else
+       ssm psr.ic | PSR_DEFAULT_BITS
+#endif
+       ;;
+       adds r3=8,r2            // set up second base pointer for SAVE_REST
+       srlz.i                  // ensure everybody knows psr.ic is back on
+       ;;
+       SAVE_REST
+       ;;
+       alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+#ifdef CONFIG_XEN
+       ;;
+       br.call.sptk.many rp=xen_get_ivr
+       ;;
+       mov out0=r8             // pass cr.ivr as first arg
+#else
+       mov out0=cr.ivr         // pass cr.ivr as first arg
+#endif
+       add out1=16,sp          // pass pointer to pt_regs as second arg
+       ;;
+       srlz.d                  // make sure we see the effect of cr.ivr
+       movl r14=ia64_leave_kernel
+       ;;
+       mov rp=r14
+       br.call.sptk.many b6=ia64_handle_irq
+END(interrupt)
+
+       .org ia64_ivt+0x3400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3400 Entry 13 (size 64 bundles) Reserved
+       DBG_FAULT(13)
+       FAULT(13)
+
+       .org ia64_ivt+0x3800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3800 Entry 14 (size 64 bundles) Reserved
+       DBG_FAULT(14)
+       FAULT(14)
+
+       /*
+        * There is no particular reason for this code to be here, other than that
+        * there happens to be space here that would go unused otherwise.  If this
+        * fault ever gets "unreserved", simply moved the following code to a more
+        * suitable spot...
+        *
+        * ia64_syscall_setup() is a separate subroutine so that it can
+        *      allocate stacked registers so it can safely demine any
+        *      potential NaT values from the input registers.
+        *
+        * On entry:
+        *      - executing on bank 0 or bank 1 register set (doesn't matter)
+        *      -  r1: stack pointer
+        *      -  r2: current task pointer
+        *      -  r3: preserved
+        *      - r11: original contents (saved ar.pfs to be saved)
+        *      - r12: original contents (sp to be saved)
+        *      - r13: original contents (tp to be saved)
+        *      - r15: original contents (syscall # to be saved)
+        *      - r18: saved bsp (after switching to kernel stack)
+        *      - r19: saved b6
+        *      - r20: saved r1 (gp)
+        *      - r21: saved ar.fpsr
+        *      - r22: kernel's register backing store base (krbs_base)
+        *      - r23: saved ar.bspstore
+        *      - r24: saved ar.rnat
+        *      - r25: saved ar.unat
+        *      - r26: saved ar.pfs
+        *      - r27: saved ar.rsc
+        *      - r28: saved cr.iip
+        *      - r29: saved cr.ipsr
+        *      - r31: saved pr
+        *      -  b0: original contents (to be saved)
+        * On exit:
+        *      -  p10: TRUE if syscall is invoked with more than 8 out
+        *              registers or r15's Nat is true
+        *      -  r1: kernel's gp
+        *      -  r3: preserved (same as on entry)
+        *      -  r8: -EINVAL if p10 is true
+        *      - r12: points to kernel stack
+        *      - r13: points to current task
+        *      - r14: preserved (same as on entry)
+        *      - p13: preserved
+        *      - p15: TRUE if interrupts need to be re-enabled
+        *      - ar.fpsr: set to kernel settings
+        *      -  b6: preserved (same as on entry)
+        */
+#ifndef CONFIG_XEN
+GLOBAL_ENTRY(ia64_syscall_setup)
+#if PT(B6) != 0
+# error This code assumes that b6 is the first field in pt_regs.
+#endif
+       st8 [r1]=r19                            // save b6
+       add r16=PT(CR_IPSR),r1                  // initialize first base pointer
+       add r17=PT(R11),r1                      // initialize second base pointer
+       ;;
+       alloc r19=ar.pfs,8,0,0,0                // ensure in0-in7 are writable
+       st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR)    // save cr.ipsr
+       tnat.nz p8,p0=in0
+
+       st8.spill [r17]=r11,PT(CR_IIP)-PT(R11)  // save r11
+       tnat.nz p9,p0=in1
+(pKStk)        mov r18=r0                              // make sure r18 isn't NaT
+       ;;
+
+       st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS)     // save ar.pfs
+       st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP)    // save cr.iip
+       mov r28=b0                              // save b0 (2 cyc)
+       ;;
+
+       st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT)    // save ar.unat
+       dep r19=0,r19,38,26                     // clear all bits but 0..37 [I0]
+(p8)   mov in0=-1
+       ;;
+
+       st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS)    // store ar.pfs.pfm in cr.ifs
+       extr.u r11=r19,7,7      // I0           // get sol of ar.pfs
+       and r8=0x7f,r19         // A            // get sof of ar.pfs
+
+       st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
+       tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
+(p9)   mov in1=-1
+       ;;
+
+(pUStk) sub r18=r18,r22                                // r18=RSE.ndirty*8
+       tnat.nz p10,p0=in2
+       add r11=8,r11
+       ;;
+(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16                // skip over ar_rnat field
+(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17    // skip over ar_bspstore field
+       tnat.nz p11,p0=in3
+       ;;
+(p10)  mov in2=-1
+       tnat.nz p12,p0=in4                              // [I0]
+(p11)  mov in3=-1
+       ;;
+(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT)       // save ar.rnat
+(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE)   // save ar.bspstore
+       shl r18=r18,16                          // compute ar.rsc to be used for "loadrs"
+       ;;
+       st8 [r16]=r31,PT(LOADRS)-PT(PR)         // save predicates
+       st8 [r17]=r28,PT(R1)-PT(B0)             // save b0
+       tnat.nz p13,p0=in5                              // [I0]
+       ;;
+       st8 [r16]=r18,PT(R12)-PT(LOADRS)        // save ar.rsc value for "loadrs"
+       st8.spill [r17]=r20,PT(R13)-PT(R1)      // save original r1
+(p12)  mov in4=-1
+       ;;
+
+.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12)       // save r12
+.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13)           // save r13
+(p13)  mov in5=-1
+       ;;
+       st8 [r16]=r21,PT(R8)-PT(AR_FPSR)        // save ar.fpsr
+       tnat.nz p13,p0=in6
+       cmp.lt p10,p9=r11,r8    // frame size can't be more than local+8
+       ;;
+       mov r8=1
+(p9)   tnat.nz p10,p0=r15
+       adds r12=-16,r1         // switch to kernel memory stack (with 16 bytes of scratch)
+
+       st8.spill [r17]=r15                     // save r15
+       tnat.nz p8,p0=in7
+       nop.i 0
+
+       mov r13=r2                              // establish `current'
+       movl r1=__gp                            // establish kernel global pointer
+       ;;
+       st8 [r16]=r8            // ensure pt_regs.r8 != 0 (see handle_syscall_error)
+(p13)  mov in6=-1
+(p8)   mov in7=-1
+
+       cmp.eq pSys,pNonSys=r0,r0               // set pSys=1, pNonSys=0
+       movl r17=FPSR_DEFAULT
+       ;;
+       mov.m ar.fpsr=r17                       // set ar.fpsr to kernel default value
+(p10)  mov r8=-EINVAL
+       br.ret.sptk.many b7
+END(ia64_syscall_setup)
+#endif
+
+       .org ia64_ivt+0x3c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3c00 Entry 15 (size 64 bundles) Reserved
+       DBG_FAULT(15)
+       FAULT(15)
+
+       /*
+        * Squatting in this space ...
+        *
+        * This special case dispatcher for illegal operation faults allows preserved
+        * registers to be modified through a callback function (asm only) that is handed
+        * back from the fault handler in r8. Up to three arguments can be passed to the
+        * callback function by returning an aggregate with the callback as its first
+        * element, followed by the arguments.
+        */
+ENTRY(dispatch_illegal_op_fault)
+       .prologue
+       .body
+       SAVE_MIN_WITH_COVER
+       ssm psr.ic | PSR_DEFAULT_BITS
+       ;;
+       srlz.i          // guarantee that interruption collection is on
+       ;;
+(p15)  ssm psr.i       // restore psr.i
+       adds r3=8,r2    // set up second base pointer for SAVE_REST
+       ;;
+       alloc r14=ar.pfs,0,0,1,0        // must be first in insn group
+       mov out0=ar.ec
+       ;;
+       SAVE_REST
+       PT_REGS_UNWIND_INFO(0)
+       ;;
+       br.call.sptk.many rp=ia64_illegal_op_fault
+.ret0: ;;
+       alloc r14=ar.pfs,0,0,3,0        // must be first in insn group
+       mov out0=r9
+       mov out1=r10
+       mov out2=r11
+       movl r15=ia64_leave_kernel
+       ;;
+       mov rp=r15
+       mov b6=r8
+       ;;
+       cmp.ne p6,p0=0,r8
+(p6)   br.call.dpnt.many b6=b6         // call returns to ia64_leave_kernel
+       br.sptk.many ia64_leave_kernel
+END(dispatch_illegal_op_fault)
+
+       .org ia64_ivt+0x4000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4000 Entry 16 (size 64 bundles) Reserved
+       DBG_FAULT(16)
+       FAULT(16)
+
+       .org ia64_ivt+0x4400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4400 Entry 17 (size 64 bundles) Reserved
+       DBG_FAULT(17)
+       FAULT(17)
+
+ENTRY(non_syscall)
+       mov ar.rsc=r27                  // restore ar.rsc before SAVE_MIN_WITH_COVER
+       ;;
+       SAVE_MIN_WITH_COVER
+
+       // There is no particular reason for this code to be here, other than that
+       // there happens to be space here that would go unused otherwise.  If this
+       // fault ever gets "unreserved", simply moved the following code to a more
+       // suitable spot...
+
+       alloc r14=ar.pfs,0,0,2,0
+       mov out0=cr.iim
+       add out1=16,sp
+       adds r3=8,r2                    // set up second base pointer for SAVE_REST
+
+       ssm psr.ic | PSR_DEFAULT_BITS
+       ;;
+       srlz.i                          // guarantee that interruption collection is on
+       ;;
+(p15)  ssm psr.i                       // restore psr.i
+       movl r15=ia64_leave_kernel
+       ;;
+       SAVE_REST
+       mov rp=r15
+       ;;
+       br.call.sptk.many b6=ia64_bad_break     // avoid WAW on CFM and ignore return addr
+END(non_syscall)
+
+       .org ia64_ivt+0x4800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4800 Entry 18 (size 64 bundles) Reserved
+       DBG_FAULT(18)
+       FAULT(18)
+
+       /*
+        * There is no particular reason for this code to be here, other than that
+        * there happens to be space here that would go unused otherwise.  If this
+        * fault ever gets "unreserved", simply moved the following code to a more
+        * suitable spot...
+        */
+
+ENTRY(dispatch_unaligned_handler)
+       SAVE_MIN_WITH_COVER
+       ;;
+       alloc r14=ar.pfs,0,0,2,0                // now it's safe (must be first in insn group!)
+       mov out0=cr.ifa
+       adds out1=16,sp
+
+       ssm psr.ic | PSR_DEFAULT_BITS
+       ;;
+       srlz.i                                  // guarantee that interruption collection is on
+       ;;
+(p15)  ssm psr.i                               // restore psr.i
+       adds r3=8,r2                            // set up second base pointer
+       ;;
+       SAVE_REST
+       movl r14=ia64_leave_kernel
+       ;;
+       mov rp=r14
+       br.sptk.many ia64_prepare_handle_unaligned
+END(dispatch_unaligned_handler)
+
+       .org ia64_ivt+0x4c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4c00 Entry 19 (size 64 bundles) Reserved
+       DBG_FAULT(19)
+       FAULT(19)
+
+       /*
+        * There is no particular reason for this code to be here, other than that
+        * there happens to be space here that would go unused otherwise.  If this
+        * fault ever gets "unreserved", simply moved the following code to a more
+        * suitable spot...
+        */
+
+ENTRY(dispatch_to_fault_handler)
+       /*
+        * Input:
+        *      psr.ic: off
+        *      r19:    fault vector number (e.g., 24 for General Exception)
+        *      r31:    contains saved predicates (pr)
+        */
+       SAVE_MIN_WITH_COVER_R19
+       alloc r14=ar.pfs,0,0,5,0
+       mov out0=r15
+#ifdef CONFIG_XEN
+       movl out1=XSI_ISR
+       ;;
+       adds out2=XSI_IFA-XSI_ISR,out1
+       adds out3=XSI_IIM-XSI_ISR,out1
+       adds out4=XSI_ITIR-XSI_ISR,out1
+       ;;
+       ld8 out1=[out1]
+       ld8 out2=[out2]
+       ld8 out3=[out4]
+       ld8 out4=[out4]
+       ;;
+#else
+       mov out1=cr.isr
+       mov out2=cr.ifa
+       mov out3=cr.iim
+       mov out4=cr.itir
+       ;;
+#endif
+       ssm psr.ic | PSR_DEFAULT_BITS
+       ;;
+       srlz.i                                  // guarantee that interruption collection is on
+       ;;
+(p15)  ssm psr.i                               // restore psr.i
+       adds r3=8,r2                            // set up second base pointer for SAVE_REST
+       ;;
+       SAVE_REST
+       movl r14=ia64_leave_kernel
+       ;;
+       mov rp=r14
+       br.call.sptk.many b6=ia64_fault
+END(dispatch_to_fault_handler)
+
+//
+// --- End of long entries, Beginning of short entries
+//
+
+       .org ia64_ivt+0x5000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
+ENTRY(page_not_present)
+       DBG_FAULT(20)
+       mov r16=cr.ifa
+       rsm psr.dt
+       /*
+        * The Linux page fault handler doesn't expect non-present pages to be in
+        * the TLB.  Flush the existing entry now, so we meet that expectation.
+        */
+       mov r17=PAGE_SHIFT<<2
+       ;;
+       ptc.l r16,r17
+       ;;
+       mov r31=pr
+       srlz.d
+       br.sptk.many page_fault
+END(page_not_present)
+
+       .org ia64_ivt+0x5100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
+ENTRY(key_permission)
+       DBG_FAULT(21)
+       mov r16=cr.ifa
+       rsm psr.dt
+       mov r31=pr
+       ;;
+       srlz.d
+       br.sptk.many page_fault
+END(key_permission)
+
+       .org ia64_ivt+0x5200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+ENTRY(iaccess_rights)
+       DBG_FAULT(22)
+       mov r16=cr.ifa
+       rsm psr.dt
+       mov r31=pr
+       ;;
+       srlz.d
+       br.sptk.many page_fault
+END(iaccess_rights)
+
+       .org ia64_ivt+0x5300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+ENTRY(daccess_rights)
+       DBG_FAULT(23)
+#ifdef CONFIG_XEN
+       movl r16=XSI_IFA
+       ;;
+       ld8 r16=[r16]
+       ;;
+       XEN_HYPER_RSM_PSR_DT
+#else
+       mov r16=cr.ifa
+       rsm psr.dt
+#endif
+       mov r31=pr
+       ;;
+       srlz.d
+       br.sptk.many page_fault
+END(daccess_rights)
+
+       .org ia64_ivt+0x5400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+ENTRY(general_exception)
+       DBG_FAULT(24)
+       mov r16=cr.isr
+       mov r31=pr
+       ;;
+       cmp4.eq p6,p0=0,r16
+(p6)   br.sptk.many dispatch_illegal_op_fault
+       ;;
+       mov r19=24              // fault number
+       br.sptk.many dispatch_to_fault_handler
+END(general_exception)
+
+       .org ia64_ivt+0x5500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+ENTRY(disabled_fp_reg)
+       DBG_FAULT(25)
+       rsm psr.dfh             // ensure we can access fph
+       ;;
+       srlz.d
+       mov r31=pr
+       mov r19=25
+       br.sptk.many dispatch_to_fault_handler
+END(disabled_fp_reg)
+
+       .org ia64_ivt+0x5600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+ENTRY(nat_consumption)
+       DBG_FAULT(26)
+
+       mov r16=cr.ipsr
+       mov r17=cr.isr
+       mov r31=pr                              // save PR
+       ;;
+       and r18=0xf,r17                         // r18 = cr.ipsr.code{3:0}
+       tbit.z p6,p0=r17,IA64_ISR_NA_BIT
+       ;;
+       cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
+       dep r16=-1,r16,IA64_PSR_ED_BIT,1
+(p6)   br.cond.spnt 1f         // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
+       ;;
+       mov cr.ipsr=r16         // set cr.ipsr.na
+       mov pr=r31,-1
+       ;;
+       rfi
+
+1:     mov pr=r31,-1
+       ;;
+       FAULT(26)
+END(nat_consumption)
+
+       .org ia64_ivt+0x5700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
+ENTRY(speculation_vector)
+       DBG_FAULT(27)
+       /*
+        * A [f]chk.[as] instruction needs to take the branch to the recovery code but
+        * this part of the architecture is not implemented in hardware on some CPUs, such
+        * as Itanium.  Thus, in general we need to emulate the behavior.  IIM contains
+        * the relative target (not yet sign extended).  So after sign extending it we
+        * simply add it to IIP.  We also need to reset the EI field of the IPSR to zero,
+        * i.e., the slot to restart into.
+        *
+        * cr.imm contains zero_ext(imm21)
+        */
+       mov r18=cr.iim
+       ;;
+       mov r17=cr.iip
+       shl r18=r18,43                  // put sign bit in position (43=64-21)
+       ;;
+
+       mov r16=cr.ipsr
+       shr r18=r18,39                  // sign extend (39=43-4)
+       ;;
+
+       add r17=r17,r18                 // now add the offset
+       ;;
+       mov cr.iip=r17
+       dep r16=0,r16,41,2              // clear EI
+       ;;
+
+       mov cr.ipsr=r16
+       ;;
+
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI;
+#else
+       rfi                             // and go back
+#endif
+END(speculation_vector)
+
+       .org ia64_ivt+0x5800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5800 Entry 28 (size 16 bundles) Reserved
+       DBG_FAULT(28)
+       FAULT(28)
+
+       .org ia64_ivt+0x5900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+ENTRY(debug_vector)
+       DBG_FAULT(29)
+       FAULT(29)
+END(debug_vector)
+
+       .org ia64_ivt+0x5a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+ENTRY(unaligned_access)
+       DBG_FAULT(30)
+       mov r31=pr              // prepare to save predicates
+       ;;
+       br.sptk.many dispatch_unaligned_handler
+END(unaligned_access)
+
+       .org ia64_ivt+0x5b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+ENTRY(unsupported_data_reference)
+       DBG_FAULT(31)
+       FAULT(31)
+END(unsupported_data_reference)
+
+       .org ia64_ivt+0x5c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
+ENTRY(floating_point_fault)
+       DBG_FAULT(32)
+       FAULT(32)
+END(floating_point_fault)
+
+       .org ia64_ivt+0x5d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+ENTRY(floating_point_trap)
+       DBG_FAULT(33)
+       FAULT(33)
+END(floating_point_trap)
+
+       .org ia64_ivt+0x5e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
+ENTRY(lower_privilege_trap)
+       DBG_FAULT(34)
+       FAULT(34)
+END(lower_privilege_trap)
+
+       .org ia64_ivt+0x5f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+ENTRY(taken_branch_trap)
+       DBG_FAULT(35)
+       FAULT(35)
+END(taken_branch_trap)
+
+       .org ia64_ivt+0x6000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+ENTRY(single_step_trap)
+       DBG_FAULT(36)
+       FAULT(36)
+END(single_step_trap)
+
+       .org ia64_ivt+0x6100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6100 Entry 37 (size 16 bundles) Reserved
+       DBG_FAULT(37)
+       FAULT(37)
+
+       .org ia64_ivt+0x6200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6200 Entry 38 (size 16 bundles) Reserved
+       DBG_FAULT(38)
+       FAULT(38)
+
+       .org ia64_ivt+0x6300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6300 Entry 39 (size 16 bundles) Reserved
+       DBG_FAULT(39)
+       FAULT(39)
+
+       .org ia64_ivt+0x6400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6400 Entry 40 (size 16 bundles) Reserved
+       DBG_FAULT(40)
+       FAULT(40)
+
+       .org ia64_ivt+0x6500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6500 Entry 41 (size 16 bundles) Reserved
+       DBG_FAULT(41)
+       FAULT(41)
+
+       .org ia64_ivt+0x6600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6600 Entry 42 (size 16 bundles) Reserved
+       DBG_FAULT(42)
+       FAULT(42)
+
+       .org ia64_ivt+0x6700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6700 Entry 43 (size 16 bundles) Reserved
+       DBG_FAULT(43)
+       FAULT(43)
+
+       .org ia64_ivt+0x6800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6800 Entry 44 (size 16 bundles) Reserved
+       DBG_FAULT(44)
+       FAULT(44)
+
+       .org ia64_ivt+0x6900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+ENTRY(ia32_exception)
+       DBG_FAULT(45)
+       FAULT(45)
+END(ia32_exception)
+
+       .org ia64_ivt+0x6a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept  (30,31,59,70,71)
+ENTRY(ia32_intercept)
+       DBG_FAULT(46)
+#ifdef CONFIG_IA32_SUPPORT
+       mov r31=pr
+       mov r16=cr.isr
+       ;;
+       extr.u r17=r16,16,8     // get ISR.code
+       mov r18=ar.eflag
+       mov r19=cr.iim          // old eflag value
+       ;;
+       cmp.ne p6,p0=2,r17
+(p6)   br.cond.spnt 1f         // not a system flag fault
+       xor r16=r18,r19
+       ;;
+       extr.u r17=r16,18,1     // get the eflags.ac bit
+       ;;
+       cmp.eq p6,p0=0,r17
+(p6)   br.cond.spnt 1f         // eflags.ac bit didn't change
+       ;;
+       mov pr=r31,-1           // restore predicate registers
+#ifdef CONFIG_XEN
+       XEN_HYPER_RFI;
+#else
+       rfi
+#endif
+
+1:
+#endif // CONFIG_IA32_SUPPORT
+       FAULT(46)
+END(ia32_intercept)
+
+       .org ia64_ivt+0x6b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt  (74)
+ENTRY(ia32_interrupt)
+       DBG_FAULT(47)
+#ifdef CONFIG_IA32_SUPPORT
+       mov r31=pr
+       br.sptk.many dispatch_to_ia32_handler
+#else
+       FAULT(47)
+#endif
+END(ia32_interrupt)
+
+       .org ia64_ivt+0x6c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6c00 Entry 48 (size 16 bundles) Reserved
+       DBG_FAULT(48)
+       FAULT(48)
+
+       .org ia64_ivt+0x6d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6d00 Entry 49 (size 16 bundles) Reserved
+       DBG_FAULT(49)
+       FAULT(49)
+
+       .org ia64_ivt+0x6e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6e00 Entry 50 (size 16 bundles) Reserved
+       DBG_FAULT(50)
+       FAULT(50)
+
+       .org ia64_ivt+0x6f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6f00 Entry 51 (size 16 bundles) Reserved
+       DBG_FAULT(51)
+       FAULT(51)
+
+       .org ia64_ivt+0x7000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7000 Entry 52 (size 16 bundles) Reserved
+       DBG_FAULT(52)
+       FAULT(52)
+
+       .org ia64_ivt+0x7100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7100 Entry 53 (size 16 bundles) Reserved
+       DBG_FAULT(53)
+       FAULT(53)
+
+       .org ia64_ivt+0x7200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7200 Entry 54 (size 16 bundles) Reserved
+       DBG_FAULT(54)
+       FAULT(54)
+
+       .org ia64_ivt+0x7300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7300 Entry 55 (size 16 bundles) Reserved
+       DBG_FAULT(55)
+       FAULT(55)
+
+       .org ia64_ivt+0x7400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7400 Entry 56 (size 16 bundles) Reserved
+       DBG_FAULT(56)
+       FAULT(56)
+
+       .org ia64_ivt+0x7500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7500 Entry 57 (size 16 bundles) Reserved
+       DBG_FAULT(57)
+       FAULT(57)
+
+       .org ia64_ivt+0x7600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7600 Entry 58 (size 16 bundles) Reserved
+       DBG_FAULT(58)
+       FAULT(58)
+
+       .org ia64_ivt+0x7700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7700 Entry 59 (size 16 bundles) Reserved
+       DBG_FAULT(59)
+       FAULT(59)
+
+       .org ia64_ivt+0x7800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7800 Entry 60 (size 16 bundles) Reserved
+       DBG_FAULT(60)
+       FAULT(60)
+
+       .org ia64_ivt+0x7900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7900 Entry 61 (size 16 bundles) Reserved
+       DBG_FAULT(61)
+       FAULT(61)
+
+       .org ia64_ivt+0x7a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7a00 Entry 62 (size 16 bundles) Reserved
+       DBG_FAULT(62)
+       FAULT(62)
+
+       .org ia64_ivt+0x7b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7b00 Entry 63 (size 16 bundles) Reserved
+       DBG_FAULT(63)
+       FAULT(63)
+
+       .org ia64_ivt+0x7c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7c00 Entry 64 (size 16 bundles) Reserved
+       DBG_FAULT(64)
+       FAULT(64)
+
+       .org ia64_ivt+0x7d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7d00 Entry 65 (size 16 bundles) Reserved
+       DBG_FAULT(65)
+       FAULT(65)
+
+       .org ia64_ivt+0x7e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7e00 Entry 66 (size 16 bundles) Reserved
+       DBG_FAULT(66)
+       FAULT(66)
+
+#ifdef CONFIG_XEN
+       /*
+        * There is no particular reason for this code to be here, other than that
+        * there happens to be space here that would go unused otherwise.  If this
+        * fault ever gets "unreserved", simply moved the following code to a more
+        * suitable spot...
+        */
+
+GLOBAL_ENTRY(xen_bsw1)
+       /* FIXME: THIS CODE IS NOT NaT SAFE! */
+       movl r30=XSI_BANKNUM;
+       mov r31=1;;
+       st4 [r30]=r31;
+       movl r30=XSI_BANK1_R16;
+       movl r31=XSI_BANK1_R16+8;;
+       ld8 r16=[r30],16; ld8 r17=[r31],16;;
+       ld8 r18=[r30],16; ld8 r19=[r31],16;;
+       ld8 r20=[r30],16; ld8 r21=[r31],16;;
+       ld8 r22=[r30],16; ld8 r23=[r31],16;;
+       ld8 r24=[r30],16; ld8 r25=[r31],16;;
+       ld8 r26=[r30],16; ld8 r27=[r31],16;;
+       ld8 r28=[r30],16; ld8 r29=[r31],16;;
+       ld8 r30=[r30]; ld8 r31=[r31];;
+       br.ret.sptk.many b0
+END(xen_bsw1)
+#endif
+
+       .org ia64_ivt+0x7f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7f00 Entry 67 (size 16 bundles) Reserved
+       DBG_FAULT(67)
+       FAULT(67)
+
+#ifdef CONFIG_IA32_SUPPORT
+
+       /*
+        * There is no particular reason for this code to be here, other than that
+        * there happens to be space here that would go unused otherwise.  If this
+        * fault ever gets "unreserved", simply moved the following code to a more
+        * suitable spot...
+        */
+
+       // IA32 interrupt entry point
+
+ENTRY(dispatch_to_ia32_handler)
+       SAVE_MIN
+       ;;
+       mov r14=cr.isr
+       ssm psr.ic | PSR_DEFAULT_BITS
+       ;;
+       srlz.i                                  // guarantee that interruption collection is on
+       ;;
+(p15)  ssm psr.i
+       adds r3=8,r2            // Base pointer for SAVE_REST
+       ;;
+       SAVE_REST
+       ;;
+       mov r15=0x80
+       shr r14=r14,16          // Get interrupt number
+       ;;
+       cmp.ne p6,p0=r14,r15
+(p6)   br.call.dpnt.many b6=non_ia32_syscall
+
+       adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
+       adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
+       ;;
+       cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+       ld8 r8=[r14]            // get r8
+       ;;
+       st8 [r15]=r8            // save original EAX in r1 (IA32 procs don't use the GP)
+       ;;
+       alloc r15=ar.pfs,0,0,6,0        // must first in an insn group
+       ;;
+       ld4 r8=[r14],8          // r8 == eax (syscall number)
+       mov r15=IA32_NR_syscalls
+       ;;
+       cmp.ltu.unc p6,p7=r8,r15
+       ld4 out1=[r14],8        // r9 == ecx
+       ;;
+       ld4 out2=[r14],8        // r10 == edx
+       ;;
+       ld4 out0=[r14]          // r11 == ebx
+       adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
+       ;;
+       ld4 out5=[r14],PT(R14)-PT(R13)  // r13 == ebp
+       ;;
+       ld4 out3=[r14],PT(R15)-PT(R14)  // r14 == esi
+       adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
+       ;;
+       ld4 out4=[r14]          // r15 == edi
+       movl r16=ia32_syscall_table
+       ;;
+(p6)   shladd r16=r8,3,r16     // force ni_syscall if not valid syscall number
+       ld4 r2=[r2]             // r2 = current_thread_info()->flags
+       ;;
+       ld8 r16=[r16]
+       and r2=_TIF_SYSCALL_TRACEAUDIT,r2       // mask trace or audit
+       ;;
+       mov b6=r16
+       movl r15=ia32_ret_from_syscall
+       cmp.eq p8,p0=r2,r0
+       ;;
+       mov rp=r15
+(p8)   br.call.sptk.many b6=b6
+       br.cond.sptk ia32_trace_syscall
+
+non_ia32_syscall:
+       alloc r15=ar.pfs,0,0,2,0
+       mov out0=r14                            // interrupt #
+       add out1=16,sp                          // pointer to pt_regs
+       ;;                      // avoid WAW on CFM
+       br.call.sptk.many rp=ia32_bad_interrupt
+.ret1: movl r15=ia64_leave_kernel
+       ;;
+       mov rp=r15
+       br.ret.sptk.many rp
+END(dispatch_to_ia32_handler)
+#endif /* CONFIG_IA32_SUPPORT */
+
+#ifdef CONFIG_XEN
+       .section .text,"ax"
+GLOBAL_ENTRY(xen_event_callback)
+       mov r31=pr              // prepare to save predicates
+       ;;
+       SAVE_MIN_WITH_COVER     // uses r31; defines r2 and r3
+       ;;
+       movl r3=XSI_PSR_IC
+       mov r14=1
+       ;;
+       st4 [r3]=r14
+       ;;
+       adds r3=8,r2            // set up second base pointer for SAVE_REST
+       srlz.i                  // ensure everybody knows psr.ic is back on
+       ;;
+       SAVE_REST
+       ;;
+       alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
+       add out0=16,sp          // pass pointer to pt_regs as first arg
+       ;;
+       srlz.d                  // make sure we see the effect of cr.ivr
+       movl r14=ia64_leave_kernel
+       ;;
+       mov rp=r14
+       br.call.sptk.many b6=evtchn_do_upcall
+END(xen_event_callback)
+#endif
diff --git a/arch/ia64/xen/xenminstate.h b/arch/ia64/xen/xenminstate.h
new file mode 100644 (file)
index 0000000..f92fc6e
--- /dev/null
@@ -0,0 +1,368 @@
+
+#include <asm/cache.h>
+
+#ifdef CONFIG_XEN
+#include "../kernel/entry.h"
+#else
+#include "entry.h"
+#endif
+
+/*
+ * For ivt.s we want to access the stack virtually so we don't have to disable translation
+ * on interrupts.
+ *
+ *  On entry:
+ *     r1:     pointer to current task (ar.k6)
+ */
+#define MINSTATE_START_SAVE_MIN_VIRT                                                           \
+(pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
+       ;;                                                                                      \
+(pUStk)        mov.m r24=ar.rnat;                                                                      \
+(pUStk)        addl r22=IA64_RBS_OFFSET,r1;                    /* compute base of RBS */               \
+(pKStk) mov r1=sp;                                     /* get sp  */                           \
+       ;;                                                                                      \
+(pUStk) lfetch.fault.excl.nt1 [r22];                                                           \
+(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;   /* compute base of memory stack */      \
+(pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
+       ;;                                                                                      \
+(pUStk)        mov ar.bspstore=r22;                            /* switch to kernel RBS */              \
+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1;                 /* if in kernel mode, use sp (r12) */   \
+       ;;                                                                                      \
+(pUStk)        mov r18=ar.bsp;                                                                         \
+(pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */             \
+
+#define MINSTATE_END_SAVE_MIN_VIRT                                                             \
+       bsw.1;                  /* switch back to bank 1 (must be last in insn group) */        \
+       ;;
+
+/*
+ * For mca_asm.S we want to access the stack physically since the state is saved before we
+ * go virtual and don't want to destroy the iip or ipsr.
+ */
+#define MINSTATE_START_SAVE_MIN_PHYS                                                           \
+(pKStk) mov r3=IA64_KR(PER_CPU_DATA);;                                                         \
+(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;;                                                   \
+(pKStk) ld8 r3 = [r3];;                                                                                \
+(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;;                                            \
+(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3;                                          \
+(pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
+(pUStk)        addl r22=IA64_RBS_OFFSET,r1;            /* compute base of register backing store */    \
+       ;;                                                                                      \
+(pUStk)        mov r24=ar.rnat;                                                                        \
+(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;   /* compute base of memory stack */      \
+(pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
+(pUStk)        dep r22=-1,r22,61,3;                    /* compute kernel virtual addr of RBS */        \
+       ;;                                                                                      \
+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1;         /* if in kernel mode, use sp (r12) */           \
+(pUStk)        mov ar.bspstore=r22;                    /* switch to kernel RBS */                      \
+       ;;                                                                                      \
+(pUStk)        mov r18=ar.bsp;                                                                         \
+(pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */             \
+
+#define MINSTATE_END_SAVE_MIN_PHYS                                                             \
+       dep r12=-1,r12,61,3;            /* make sp a kernel virtual address */                  \
+       ;;
+
+#ifdef MINSTATE_VIRT
+# define MINSTATE_GET_CURRENT(reg)     mov reg=IA64_KR(CURRENT)
+# define MINSTATE_START_SAVE_MIN       MINSTATE_START_SAVE_MIN_VIRT
+# define MINSTATE_END_SAVE_MIN         MINSTATE_END_SAVE_MIN_VIRT
+#endif
+
+#ifdef MINSTATE_PHYS
+# define MINSTATE_GET_CURRENT(reg)     mov reg=IA64_KR(CURRENT);; tpa reg=reg
+# define MINSTATE_START_SAVE_MIN       MINSTATE_START_SAVE_MIN_PHYS
+# define MINSTATE_END_SAVE_MIN         MINSTATE_END_SAVE_MIN_PHYS
+#endif
+
+/*
+ * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
+ * the minimum state necessary that allows us to turn psr.ic back
+ * on.
+ *
+ * Assumed state upon entry:
+ *     psr.ic: off
+ *     r31:    contains saved predicates (pr)
+ *
+ * Upon exit, the state is as follows:
+ *     psr.ic: off
+ *      r2 = points to &pt_regs.r16
+ *      r8 = contents of ar.ccv
+ *      r9 = contents of ar.csd
+ *     r10 = contents of ar.ssd
+ *     r11 = FPSR_DEFAULT
+ *     r12 = kernel sp (kernel virtual address)
+ *     r13 = points to current task_struct (kernel virtual address)
+ *     p15 = TRUE if psr.i is set in cr.ipsr
+ *     predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
+ *             preserved
+ * CONFIG_XEN note: p6/p7 are not preserved
+ *
+ * Note that psr.ic is NOT turned on by this macro.  This is so that
+ * we can pass interruption state as arguments to a handler.
+ */
+#ifdef CONFIG_XEN
+#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)                                                      \
+       MINSTATE_GET_CURRENT(r16);      /* M (or M;;I) */                                       \
+       mov r27=ar.rsc;                 /* M */                                                 \
+       mov r20=r1;                     /* A */                                                 \
+       mov r25=ar.unat;                /* M */                                                 \
+       /* mov r29=cr.ipsr;             /* M */                                                 \
+       movl r29=XSI_IPSR;;                                                                     \
+       ld8 r29=[r29];;                                                                         \
+       mov r26=ar.pfs;                 /* I */                                                 \
+       /* mov r28=cr.iip;              /* M */                                                 \
+       movl r28=XSI_IIP;;                                                                      \
+       ld8 r28=[r28];;                                                                         \
+       mov r21=ar.fpsr;                /* M */                                                 \
+       COVER;                  /* B;; (or nothing) */                                  \
+       ;;                                                                                      \
+       adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16;                                         \
+       ;;                                                                                      \
+       ld1 r17=[r16];                          /* load current->thread.on_ustack flag */       \
+       st1 [r16]=r0;                           /* clear current->thread.on_ustack flag */      \
+       adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16                                          \
+       /* switch from user to kernel RBS: */                                                   \
+       ;;                                                                                      \
+       invala;                         /* M */                                                 \
+       /* SAVE_IFS; /* see xen special handling below */                                               \
+       cmp.eq pKStk,pUStk=r0,r17;              /* are we in kernel mode already? */            \
+       ;;                                                                                      \
+       MINSTATE_START_SAVE_MIN                                                                 \
+       adds r17=2*L1_CACHE_BYTES,r1;           /* really: biggest cache-line size */           \
+       adds r16=PT(CR_IPSR),r1;                                                                \
+       ;;                                                                                      \
+       lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES;                                             \
+       st8 [r16]=r29;          /* save cr.ipsr */                                              \
+       ;;                                                                                      \
+       lfetch.fault.excl.nt1 [r17];                                                            \
+       tbit.nz p15,p0=r29,IA64_PSR_I_BIT;                                                      \
+       mov r29=b0                                                                              \
+       ;;                                                                                      \
+       adds r16=PT(R8),r1;     /* initialize first base pointer */                             \
+       adds r17=PT(R9),r1;     /* initialize second base pointer */                            \
+(pKStk)        mov r18=r0;             /* make sure r18 isn't NaT */                                   \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r8,16;                                                                \
+.mem.offset 8,0; st8.spill [r17]=r9,16;                                                                \
+        ;;                                                                                     \
+.mem.offset 0,0; st8.spill [r16]=r10,24;                                                       \
+.mem.offset 8,0; st8.spill [r17]=r11,24;                                                       \
+        ;;                                                                                     \
+       /* xen special handling for possibly lazy cover */                                      \
+       movl r8=XSI_INCOMPL_REGFR;                                                              \
+       ;;                                                                                      \
+       ld4 r30=[r8];                                                                           \
+       ;;                                                                                      \
+       /* set XSI_INCOMPL_REGFR 0 */                                                           \
+       st4 [r8]=r0;                                                                            \
+       cmp.eq  p6,p7=r30,r0;                                                                   \
+       ;; /* not sure if this stop bit is necessary */                                         \
+(p6)   adds r8=XSI_PRECOVER_IFS-XSI_INCOMPL_REGFR,r8;                                          \
+(p7)   adds r8=XSI_IFS-XSI_INCOMPL_REGFR,r8;                                                   \
+       ;;                                                                                      \
+       ld8 r30=[r8];                                                                           \
+       ;;                                                                                      \
+       st8 [r16]=r28,16;       /* save cr.iip */                                               \
+       st8 [r17]=r30,16;       /* save cr.ifs */                                               \
+(pUStk)        sub r18=r18,r22;        /* r18=RSE.ndirty*8 */                                          \
+       mov r8=ar.ccv;                                                                          \
+       mov r9=ar.csd;                                                                          \
+       mov r10=ar.ssd;                                                                         \
+       movl r11=FPSR_DEFAULT;   /* L-unit */                                                   \
+       ;;                                                                                      \
+       st8 [r16]=r25,16;       /* save ar.unat */                                              \
+       st8 [r17]=r26,16;       /* save ar.pfs */                                               \
+       shl r18=r18,16;         /* compute ar.rsc to be used for "loadrs" */                    \
+       ;;                                                                                      \
+       st8 [r16]=r27,16;       /* save ar.rsc */                                               \
+(pUStk)        st8 [r17]=r24,16;       /* save ar.rnat */                                              \
+(pKStk)        adds r17=16,r17;        /* skip over ar_rnat field */                                   \
+       ;;                      /* avoid RAW on r16 & r17 */                                    \
+(pUStk)        st8 [r16]=r23,16;       /* save ar.bspstore */                                          \
+       st8 [r17]=r31,16;       /* save predicates */                                           \
+(pKStk)        adds r16=16,r16;        /* skip over ar_bspstore field */                               \
+       ;;                                                                                      \
+       st8 [r16]=r29,16;       /* save b0 */                                                   \
+       st8 [r17]=r18,16;       /* save ar.rsc value for "loadrs" */                            \
+       cmp.eq pNonSys,pSys=r0,r0       /* initialize pSys=0, pNonSys=1 */                      \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r20,16;       /* save original r1 */                          \
+.mem.offset 8,0; st8.spill [r17]=r12,16;                                                       \
+       adds r12=-16,r1;        /* switch to kernel memory stack (with 16 bytes of scratch) */  \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r13,16;                                                       \
+.mem.offset 8,0; st8.spill [r17]=r21,16;       /* save ar.fpsr */                              \
+       mov r13=IA64_KR(CURRENT);       /* establish `current' */                               \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r15,16;                                                       \
+.mem.offset 8,0; st8.spill [r17]=r14,16;                                                       \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r2,16;                                                                \
+.mem.offset 8,0; st8.spill [r17]=r3,16;                                                                \
+       ;;                                                                                      \
+       EXTRA;                                                                                  \
+       mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2;                                        \
+       adds r2=IA64_PT_REGS_R16_OFFSET,r1;                                                     \
+       ;;                                                                                      \
+       movl r1=__gp;           /* establish kernel global pointer */                           \
+       ;;                                                                                      \
+       /* MINSTATE_END_SAVE_MIN */
+#else
+#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)                                                      \
+       MINSTATE_GET_CURRENT(r16);      /* M (or M;;I) */                                       \
+       mov r27=ar.rsc;                 /* M */                                                 \
+       mov r20=r1;                     /* A */                                                 \
+       mov r25=ar.unat;                /* M */                                                 \
+       mov r29=cr.ipsr;                /* M */                                                 \
+       mov r26=ar.pfs;                 /* I */                                                 \
+       mov r28=cr.iip;                 /* M */                                                 \
+       mov r21=ar.fpsr;                /* M */                                                 \
+       COVER;                          /* B;; (or nothing) */                                  \
+       ;;                                                                                      \
+       adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16;                                         \
+       ;;                                                                                      \
+       ld1 r17=[r16];                          /* load current->thread.on_ustack flag */       \
+       st1 [r16]=r0;                           /* clear current->thread.on_ustack flag */      \
+       adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16                                          \
+       /* switch from user to kernel RBS: */                                                   \
+       ;;                                                                                      \
+       invala;                         /* M */                                                 \
+       SAVE_IFS;                                                                               \
+       cmp.eq pKStk,pUStk=r0,r17;              /* are we in kernel mode already? */            \
+       ;;                                                                                      \
+       MINSTATE_START_SAVE_MIN                                                                 \
+       adds r17=2*L1_CACHE_BYTES,r1;           /* really: biggest cache-line size */           \
+       adds r16=PT(CR_IPSR),r1;                                                                \
+       ;;                                                                                      \
+       lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES;                                             \
+       st8 [r16]=r29;          /* save cr.ipsr */                                              \
+       ;;                                                                                      \
+       lfetch.fault.excl.nt1 [r17];                                                            \
+       tbit.nz p15,p0=r29,IA64_PSR_I_BIT;                                                      \
+       mov r29=b0                                                                              \
+       ;;                                                                                      \
+       adds r16=PT(R8),r1;     /* initialize first base pointer */                             \
+       adds r17=PT(R9),r1;     /* initialize second base pointer */                            \
+(pKStk)        mov r18=r0;             /* make sure r18 isn't NaT */                                   \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r8,16;                                                                \
+.mem.offset 8,0; st8.spill [r17]=r9,16;                                                                \
+        ;;                                                                                     \
+.mem.offset 0,0; st8.spill [r16]=r10,24;                                                       \
+.mem.offset 8,0; st8.spill [r17]=r11,24;                                                       \
+        ;;                                                                                     \
+       st8 [r16]=r28,16;       /* save cr.iip */                                               \
+       st8 [r17]=r30,16;       /* save cr.ifs */                                               \
+(pUStk)        sub r18=r18,r22;        /* r18=RSE.ndirty*8 */                                          \
+       mov r8=ar.ccv;                                                                          \
+       mov r9=ar.csd;                                                                          \
+       mov r10=ar.ssd;                                                                         \
+       movl r11=FPSR_DEFAULT;   /* L-unit */                                                   \
+       ;;                                                                                      \
+       st8 [r16]=r25,16;       /* save ar.unat */                                              \
+       st8 [r17]=r26,16;       /* save ar.pfs */                                               \
+       shl r18=r18,16;         /* compute ar.rsc to be used for "loadrs" */                    \
+       ;;                                                                                      \
+       st8 [r16]=r27,16;       /* save ar.rsc */                                               \
+(pUStk)        st8 [r17]=r24,16;       /* save ar.rnat */                                              \
+(pKStk)        adds r17=16,r17;        /* skip over ar_rnat field */                                   \
+       ;;                      /* avoid RAW on r16 & r17 */                                    \
+(pUStk)        st8 [r16]=r23,16;       /* save ar.bspstore */                                          \
+       st8 [r17]=r31,16;       /* save predicates */                                           \
+(pKStk)        adds r16=16,r16;        /* skip over ar_bspstore field */                               \
+       ;;                                                                                      \
+       st8 [r16]=r29,16;       /* save b0 */                                                   \
+       st8 [r17]=r18,16;       /* save ar.rsc value for "loadrs" */                            \
+       cmp.eq pNonSys,pSys=r0,r0       /* initialize pSys=0, pNonSys=1 */                      \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r20,16;       /* save original r1 */                          \
+.mem.offset 8,0; st8.spill [r17]=r12,16;                                                       \
+       adds r12=-16,r1;        /* switch to kernel memory stack (with 16 bytes of scratch) */  \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r13,16;                                                       \
+.mem.offset 8,0; st8.spill [r17]=r21,16;       /* save ar.fpsr */                              \
+       mov r13=IA64_KR(CURRENT);       /* establish `current' */                               \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r15,16;                                                       \
+.mem.offset 8,0; st8.spill [r17]=r14,16;                                                       \
+       ;;                                                                                      \
+.mem.offset 0,0; st8.spill [r16]=r2,16;                                                                \
+.mem.offset 8,0; st8.spill [r17]=r3,16;                                                                \
+       adds r2=IA64_PT_REGS_R16_OFFSET,r1;                                                     \
+       ;;                                                                                      \
+       EXTRA;                                                                                  \
+       movl r1=__gp;           /* establish kernel global pointer */                           \
+       ;;                                                                                      \
+       MINSTATE_END_SAVE_MIN
+#endif
+
+/*
+ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
+ *
+ * Assumed state upon entry:
+ *     psr.ic: on
+ *     r2:     points to &pt_regs.r16
+ *     r3:     points to &pt_regs.r17
+ *     r8:     contents of ar.ccv
+ *     r9:     contents of ar.csd
+ *     r10:    contents of ar.ssd
+ *     r11:    FPSR_DEFAULT
+ *
+ * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
+ */
+#define SAVE_REST                              \
+.mem.offset 0,0; st8.spill [r2]=r16,16;                \
+.mem.offset 8,0; st8.spill [r3]=r17,16;                \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r18,16;                \
+.mem.offset 8,0; st8.spill [r3]=r19,16;                \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r20,16;                \
+.mem.offset 8,0; st8.spill [r3]=r21,16;                \
+       mov r18=b6;                             \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r22,16;                \
+.mem.offset 8,0; st8.spill [r3]=r23,16;                \
+       mov r19=b7;                             \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r24,16;                \
+.mem.offset 8,0; st8.spill [r3]=r25,16;                \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r26,16;                \
+.mem.offset 8,0; st8.spill [r3]=r27,16;                \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r28,16;                \
+.mem.offset 8,0; st8.spill [r3]=r29,16;                \
+       ;;                                      \
+.mem.offset 0,0; st8.spill [r2]=r30,16;                \
+.mem.offset 8,0; st8.spill [r3]=r31,32;                \
+       ;;                                      \
+       mov ar.fpsr=r11;        /* M-unit */    \
+       st8 [r2]=r8,8;          /* ar.ccv */    \
+       adds r24=PT(B6)-PT(F7),r3;              \
+       ;;                                      \
+       stf.spill [r2]=f6,32;                   \
+       stf.spill [r3]=f7,32;                   \
+       ;;                                      \
+       stf.spill [r2]=f8,32;                   \
+       stf.spill [r3]=f9,32;                   \
+       ;;                                      \
+       stf.spill [r2]=f10;                     \
+       stf.spill [r3]=f11;                     \
+       adds r25=PT(B7)-PT(F11),r3;             \
+       ;;                                      \
+       st8 [r24]=r18,16;       /* b6 */        \
+       st8 [r25]=r19,16;       /* b7 */        \
+       ;;                                      \
+       st8 [r24]=r9;           /* ar.csd */    \
+       st8 [r25]=r10;          /* ar.ssd */    \
+       ;;
+
+#define SAVE_MIN_WITH_COVER    DO_SAVE_MIN(cover, mov r30=cr.ifs,)
+#define SAVE_MIN_WITH_COVER_R19        DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19)
+#ifdef CONFIG_XEN
+#define SAVE_MIN               break 0;; /* FIXME: non-cover version only for ia32 support? */
+#else
+#define SAVE_MIN               DO_SAVE_MIN(     , mov r30=r0, )
+#endif
diff --git a/arch/ia64/xen/xenpal.S b/arch/ia64/xen/xenpal.S
new file mode 100644 (file)
index 0000000..5f9681e
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * ia64/xen/xenpal.S
+ *
+ * Alternate PAL  routines for Xen.  Heavily leveraged from
+ *   ia64/kernel/pal.S
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Dan Magenheimer <dan.magenheimer@.hp.com>
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/processor.h>
+
+GLOBAL_ENTRY(xen_pal_call_static)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
+       alloc loc1 = ar.pfs,5,5,0,0
+#ifdef CONFIG_XEN
+       movl r22=running_on_xen;;
+       ld4 r22=[r22];;
+       cmp.eq p7,p0=r22,r0
+(p7)   br.cond.spnt.many __ia64_pal_call_static;;
+#endif
+       movl loc2 = pal_entry_point
+1:     {
+         mov r28 = in0
+         mov r29 = in1
+         mov r8 = ip
+       }
+       ;;
+       ld8 loc2 = [loc2]               // loc2 <- entry point
+       tbit.nz p6,p7 = in4, 0
+       adds r8 = 1f-1b,r8
+       mov loc4=ar.rsc                 // save RSE configuration
+       ;;
+       mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
+       mov loc3 = psr
+       mov loc0 = rp
+       .body
+       mov r30 = in2
+
+#ifdef CONFIG_XEN
+       // this is low priority for paravirtualization, but is called
+       // from the idle loop so confuses privop counting
+       movl r31=XSI_PSR_IC
+       ;;
+(p6)   st4 [r31]=r0
+       ;;
+(p7)   adds r31=XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS,r31
+(p7)   mov r22=1
+       ;;
+(p7)   ld8 r31=[r31]
+       ;;
+(p7)   st1 [r31]=r22
+       ;;
+       mov r31 = in3
+       mov b7 = loc2
+       ;;
+#else
+(p6)   rsm psr.i | psr.ic
+       mov r31 = in3
+       mov b7 = loc2
+
+(p7)   rsm psr.i
+       ;;
+(p6)   srlz.i
+#endif
+       mov rp = r8
+       br.cond.sptk.many b7
+1:     mov psr.l = loc3
+       mov ar.rsc = loc4               // restore RSE configuration
+       mov ar.pfs = loc1
+       mov rp = loc0
+       ;;
+       srlz.d                          // seralize restoration of psr.l
+       br.ret.sptk.many b0
+END(xen_pal_call_static)
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S
new file mode 100644 (file)
index 0000000..a2beb1c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Support routines for Xen
+ *
+ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+#define isBP   p3      // are we the Bootstrap Processor?
+
+       .text
+GLOBAL_ENTRY(early_xen_setup)
+       mov r8=ar.rsc           // Initialized in head.S
+(isBP) movl r9=running_on_xen;;
+       extr.u r8=r8,2,2;;      // Extract pl fields
+       cmp.eq p7,p0=r8,r0      // p7: !running on xen
+       mov r8=1                // booleanize.
+(p7)   br.ret.sptk.many rp;;
+(isBP) st4 [r9]=r8
+       movl r10=xen_ivt;;
+       
+       mov cr.iva=r10
+
+#if XSI_BASE != 0xf100000000000000UL
+       /* Backward compatibility.  */
+(isBP) mov r2=0x600
+(isBP) movl r28=XSI_BASE;;
+(isBP) break 0x1000;;
+#endif
+
+       br.ret.sptk.many rp
+       ;;
+END(early_xen_setup)
+
+#include <xen/interface/xen.h>
+
+/* Stub for suspend.
+   Just force the stacked registers to be written in memory.  */       
+GLOBAL_ENTRY(HYPERVISOR_suspend)
+       alloc r20=ar.pfs,0,0,0,0
+       mov r14=2
+       mov r15=r12
+       ;;
+       /* We don't want to deal with RSE.  */
+       flushrs
+       mov r2=__HYPERVISOR_sched_op
+       st4 [r12]=r14
+       ;;
+       break 0x1000
+       ;; 
+       mov ar.pfs=r20
+       br.ret.sptk.many b0
+END(HYPERVISOR_suspend)
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
new file mode 100644 (file)
index 0000000..fc449f8
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pgalloc.h>
+#include <asm/scatterlist.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                        dma_addr_t *handle, int flag)
+{
+       struct page *page, **map;
+       pgprot_t pgprot;
+       void *addr;
+       int i, order;
+
+       pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
+
+       size = PAGE_ALIGN(size);
+       order = get_order(size);
+
+       page = alloc_pages(flag, order);
+       if (!page)
+               return NULL;
+
+       *handle = page_to_phys(page);
+       map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
+       if (!map) {
+               __free_pages(page, order);
+               return NULL;
+       }
+       split_page(page, order);
+
+       order = 1 << order;
+       size >>= PAGE_SHIFT;
+       map[0] = page;
+       for (i = 1; i < size; i++)
+               map[i] = page + i;
+       for (; i < order; i++)
+               __free_page(page + i);
+       pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+       if (CPU_IS_040_OR_060)
+               pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
+       else
+               pgprot_val(pgprot) |= _PAGE_NOCACHE030;
+       addr = vmap(map, size, flag, pgprot);
+       kfree(map);
+
+       return addr;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+                      void *addr, dma_addr_t handle)
+{
+       pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
+       vfree(addr);
+}
+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)
+{
+       switch (dir) {
+       case DMA_TO_DEVICE:
+               cache_push(handle, size);
+               break;
+       case DMA_FROM_DEVICE:
+               cache_clear(handle, size);
+               break;
+       default:
+               if (printk_ratelimit())
+                       printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+               break;
+       }
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
+                           enum dma_data_direction dir)
+{
+       int i;
+
+       for (i = 0; i < nents; sg++, i++)
+               dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+                         enum dma_data_direction dir)
+{
+       dma_addr_t handle = virt_to_bus(addr);
+
+       dma_sync_single_for_device(dev, handle, size, dir);
+       return handle;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+                       unsigned long offset, size_t size,
+                       enum dma_data_direction dir)
+{
+       dma_addr_t handle = page_to_phys(page) + offset;
+
+       dma_sync_single_for_device(dev, handle, size, dir);
+       return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+              enum dma_data_direction dir)
+{
+       int i;
+
+       for (i = 0; i < nents; sg++, i++) {
+               sg->dma_address = page_to_phys(sg->page) + sg->offset;
+               dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+       }
+       return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c
new file mode 100644 (file)
index 0000000..1bc188c
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+unsigned long __generic_copy_from_user(void *to, const void __user *from,
+                                      unsigned long n)
+{
+       unsigned long tmp, res;
+
+       asm volatile ("\n"
+               "       tst.l   %0\n"
+               "       jeq     2f\n"
+               "1:     moves.l (%1)+,%3\n"
+               "       move.l  %3,(%2)+\n"
+               "       subq.l  #1,%0\n"
+               "       jne     1b\n"
+               "2:     btst    #1,%5\n"
+               "       jeq     4f\n"
+               "3:     moves.w (%1)+,%3\n"
+               "       move.w  %3,(%2)+\n"
+               "4:     btst    #0,%5\n"
+               "       jeq     6f\n"
+               "5:     moves.b (%1)+,%3\n"
+               "       move.b  %3,(%2)+\n"
+               "6:\n"
+               "       .section .fixup,\"ax\"\n"
+               "       .even\n"
+               "10:    move.l  %0,%3\n"
+               "7:     clr.l   (%2)+\n"
+               "       subq.l  #1,%3\n"
+               "       jne     7b\n"
+               "       lsl.l   #2,%0\n"
+               "       btst    #1,%5\n"
+               "       jeq     8f\n"
+               "30:    clr.w   (%2)+\n"
+               "       addq.l  #2,%0\n"
+               "8:     btst    #0,%5\n"
+               "       jeq     6b\n"
+               "50:    clr.b   (%2)+\n"
+               "       addq.l  #1,%0\n"
+               "       jra     6b\n"
+               "       .previous\n"
+               "\n"
+               "       .section __ex_table,\"a\"\n"
+               "       .align  4\n"
+               "       .long   1b,10b\n"
+               "       .long   3b,30b\n"
+               "       .long   5b,50b\n"
+               "       .previous"
+               : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
+               : "0" (n / 4), "d" (n & 3));
+
+       return res;
+}
+EXPORT_SYMBOL(__generic_copy_from_user);
+
+unsigned long __generic_copy_to_user(void __user *to, const void *from,
+                                    unsigned long n)
+{
+       unsigned long tmp, res;
+
+       asm volatile ("\n"
+               "       tst.l   %0\n"
+               "       jeq     4f\n"
+               "1:     move.l  (%1)+,%3\n"
+               "2:     moves.l %3,(%2)+\n"
+               "3:     subq.l  #1,%0\n"
+               "       jne     1b\n"
+               "4:     btst    #1,%5\n"
+               "       jeq     6f\n"
+               "       move.w  (%1)+,%3\n"
+               "5:     moves.w %3,(%2)+\n"
+               "6:     btst    #0,%5\n"
+               "       jeq     8f\n"
+               "       move.b  (%1)+,%3\n"
+               "7:     moves.b  %3,(%2)+\n"
+               "8:\n"
+               "       .section .fixup,\"ax\"\n"
+               "       .even\n"
+               "20:    lsl.l   #2,%0\n"
+               "50:    add.l   %5,%0\n"
+               "       jra     7b\n"
+               "       .previous\n"
+               "\n"
+               "       .section __ex_table,\"a\"\n"
+               "       .align  4\n"
+               "       .long   2b,20b\n"
+               "       .long   3b,20b\n"
+               "       .long   5b,50b\n"
+               "       .long   6b,50b\n"
+               "       .long   7b,50b\n"
+               "       .long   8b,50b\n"
+               "       .previous"
+               : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
+               : "0" (n / 4), "d" (n & 3));
+
+       return res;
+}
+EXPORT_SYMBOL(__generic_copy_to_user);
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+long strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       long res;
+       char c;
+
+       if (count <= 0)
+               return count;
+
+       asm volatile ("\n"
+               "1:     moves.b (%2)+,%4\n"
+               "       move.b  %4,(%1)+\n"
+               "       jeq     2f\n"
+               "       subq.l  #1,%3\n"
+               "       jne     1b\n"
+               "2:     sub.l   %3,%0\n"
+               "3:\n"
+               "       .section .fixup,\"ax\"\n"
+               "       .even\n"
+               "10:    move.l  %5,%0\n"
+               "       jra     3b\n"
+               "       .previous\n"
+               "\n"
+               "       .section __ex_table,\"a\"\n"
+               "       .align  4\n"
+               "       .long   1b,10b\n"
+               "       .previous"
+               : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c)
+               : "i" (-EFAULT), "0" (count));
+
+       return res;
+}
+EXPORT_SYMBOL(strncpy_from_user);
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char __user *src, long n)
+{
+       char c;
+       long res;
+
+       asm volatile ("\n"
+               "1:     subq.l  #1,%1\n"
+               "       jmi     3f\n"
+               "2:     moves.b (%0)+,%2\n"
+               "       tst.b   %2\n"
+               "       jne     1b\n"
+               "       jra     4f\n"
+               "\n"
+               "3:     addq.l  #1,%0\n"
+               "4:     sub.l   %4,%0\n"
+               "5:\n"
+               "       .section .fixup,\"ax\"\n"
+               "       .even\n"
+               "20:    sub.l   %0,%0\n"
+               "       jra     5b\n"
+               "       .previous\n"
+               "\n"
+               "       .section __ex_table,\"a\"\n"
+               "       .align  4\n"
+               "       .long   2b,20b\n"
+               "       .previous\n"
+               : "=&a" (res), "+d" (n), "=&d" (c)
+               : "0" (src), "r" (src));
+
+       return res;
+}
+EXPORT_SYMBOL(strnlen_user);
+
+/*
+ * Zero Userspace
+ */
+
+unsigned long clear_user(void __user *to, unsigned long n)
+{
+       unsigned long res;
+
+       asm volatile ("\n"
+               "       tst.l   %0\n"
+               "       jeq     3f\n"
+               "1:     moves.l %2,(%1)+\n"
+               "2:     subq.l  #1,%0\n"
+               "       jne     1b\n"
+               "3:     btst    #1,%4\n"
+               "       jeq     5f\n"
+               "4:     moves.w %2,(%1)+\n"
+               "5:     btst    #0,%4\n"
+               "       jeq     7f\n"
+               "6:     moves.b %2,(%1)\n"
+               "7:\n"
+               "       .section .fixup,\"ax\"\n"
+               "       .even\n"
+               "10:    lsl.l   #2,%0\n"
+               "40:    add.l   %4,%0\n"
+               "       jra     7b\n"
+               "       .previous\n"
+               "\n"
+               "       .section __ex_table,\"a\"\n"
+               "       .align  4\n"
+               "       .long   1b,10b\n"
+               "       .long   2b,10b\n"
+               "       .long   4b,40b\n"
+               "       .long   5b,40b\n"
+               "       .long   6b,40b\n"
+               "       .long   7b,40b\n"
+               "       .previous"
+               : "=d" (res), "+a" (to)
+               : "r" (0), "0" (n / 4), "d" (n & 3));
+
+    return res;
+}
+EXPORT_SYMBOL(clear_user);
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile
new file mode 100644 (file)
index 0000000..1230180
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
+obj-y := config.o
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
new file mode 100644 (file)
index 0000000..c7d6ad5
--- /dev/null
@@ -0,0 +1,485 @@
+/***************************************************************************/
+
+/*
+ *     linux/arch/m68knommu/platform/532x/config.c
+ *
+ *     Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *     Copyright (C) 2000, Lineo (www.lineo.com)
+ *     Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
+ *     Copyright Freescale Semiconductor, Inc 2006
+ *     Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.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/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+void coldfire_tick(void);
+void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
+
+/***************************************************************************/
+
+/*
+ *     DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void mcf_settimericr(unsigned int timer, unsigned int level)
+{
+       volatile unsigned char *icrp;
+       unsigned int icr;
+       unsigned char irq;
+
+       if (timer <= 2) {
+               switch (timer) {
+               case 2:  irq = 33; icr = MCFSIM_ICR_TIMER2; break;
+               default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
+               }
+               
+               icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+               *icrp = level;
+               mcf_enable_irq0(irq);
+       }
+}
+
+/***************************************************************************/
+
+int mcf_timerirqpending(int timer)
+{
+       unsigned int imr = 0;
+
+       switch (timer) {
+       case 1:  imr = 0x1; break;
+       case 2:  imr = 0x2; break;
+       default: break;
+       }
+       return (mcf_getiprh() & imr);
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+       mcf_setimr(MCFSIM_IMR_MASKALL);
+
+#if defined(CONFIG_BOOTPARAM)
+       strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+       commandp[size-1] = 0;
+#else
+       /* Copy command line from FLASH to local buffer... */
+       memcpy(commandp, (char *) 0x4000, 4);
+       if(strncmp(commandp, "kcl ", 4) == 0){
+               memcpy(commandp, (char *) 0x4004, size);
+               commandp[size-1] = 0;
+       } else {
+               memset(commandp, 0, size);
+       }
+#endif
+
+       mcf_timervector = 64+32;
+       mcf_profilevector = 64+33;
+       mach_sched_init = coldfire_timer_init;
+       mach_tick = coldfire_tick;
+       mach_gettimeoffset = coldfire_timer_offset;
+       mach_trap_init = coldfire_trap_init;
+       mach_reset = coldfire_reset;
+
+#ifdef MCF_BDM_DISABLE
+       /*
+        * Disable the BDM clocking.  This also turns off most of the rest of
+        * the BDM device.  This is good for EMC reasons. This option is not
+        * incompatible with the memory protection option.
+        */
+       wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
+}
+
+/***************************************************************************/
+/* Board initialization */
+
+/********************************************************************/
+/* 
+ * PLL min/max specifications
+ */
+#define MAX_FVCO       500000  /* KHz */
+#define MAX_FSYS       80000   /* KHz */
+#define MIN_FSYS       58333   /* KHz */
+#define FREF           16000   /* KHz */
+
+
+#define MAX_MFD                135     /* Multiplier */
+#define MIN_MFD                88      /* Multiplier */
+#define BUSDIV         6       /* Divider */
+
+/*
+ * Low Power Divider specifications
+ */
+#define MIN_LPD                (1 << 0)    /* Divider (not encoded) */
+#define MAX_LPD                (1 << 15)   /* Divider (not encoded) */
+#define DEFAULT_LPD    (1 << 1)        /* Divider (not encoded) */
+
+#define SYS_CLK_KHZ    80000
+#define SYSTEM_PERIOD  12.5
+/*
+ *  SDRAM Timing Parameters
+ */  
+#define SDRAM_BL       8       /* # of beats in a burst */
+#define SDRAM_TWR      2       /* in clocks */
+#define SDRAM_CASL     2.5     /* CASL in clocks */
+#define SDRAM_TRCD     2       /* in clocks */
+#define SDRAM_TRP      2       /* in clocks */
+#define SDRAM_TRFC     7       /* in clocks */
+#define SDRAM_TREFI    7800    /* in ns */
+
+#define EXT_SRAM_ADDRESS       (0xC0000000)
+#define FLASH_ADDRESS          (0x00000000)
+#define SDRAM_ADDRESS          (0x40000000)
+
+#define NAND_FLASH_ADDRESS     (0xD0000000)
+
+int sys_clk_khz = 0;
+int sys_clk_mhz = 0;
+
+void wtm_init(void);
+void scm_init(void);
+void gpio_init(void);
+void fbcs_init(void);
+void sdramc_init(void);
+int  clock_pll (int fsys, int flags);
+int  clock_limp (int);
+int  clock_exit_limp (void);
+int  get_sys_clock (void);
+
+asmlinkage void __init sysinit(void)
+{
+       sys_clk_khz = clock_pll(0, 0);
+       sys_clk_mhz = sys_clk_khz/1000;
+       
+       wtm_init();
+       scm_init();
+       gpio_init();
+       fbcs_init();
+       sdramc_init();
+}
+
+void wtm_init(void)
+{
+       /* Disable watchdog timer */
+       MCF_WTM_WCR = 0;
+}
+
+#define MCF_SCM_BCR_GBW                (0x00000100)
+#define MCF_SCM_BCR_GBR                (0x00000200)
+
+void scm_init(void)
+{
+       /* All masters are trusted */
+       MCF_SCM_MPR = 0x77777777;
+    
+       /* Allow supervisor/user, read/write, and trusted/untrusted
+          access to all slaves */
+       MCF_SCM_PACRA = 0;
+       MCF_SCM_PACRB = 0;
+       MCF_SCM_PACRC = 0;
+       MCF_SCM_PACRD = 0;
+       MCF_SCM_PACRE = 0;
+       MCF_SCM_PACRF = 0;
+
+       /* Enable bursts */
+       MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
+}
+
+
+void fbcs_init(void)
+{
+       MCF_GPIO_PAR_CS = 0x0000003E;
+
+       /* Latch chip select */
+       MCF_FBCS1_CSAR = 0x10080000;
+
+       MCF_FBCS1_CSCR = 0x002A3780;
+       MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
+
+       /* Initialize latch to drive signals to inactive states */
+       *((u16 *)(0x10080000)) = 0xFFFF;
+
+       /* External SRAM */
+       MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
+       MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
+                       | MCF_FBCS_CSCR_AA
+                       | MCF_FBCS_CSCR_SBM
+                       | MCF_FBCS_CSCR_WS(1));
+       MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
+                       | MCF_FBCS_CSMR_V);
+
+       /* Boot Flash connected to FBCS0 */
+       MCF_FBCS0_CSAR = FLASH_ADDRESS;
+       MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
+                       | MCF_FBCS_CSCR_BEM
+                       | MCF_FBCS_CSCR_AA
+                       | MCF_FBCS_CSCR_SBM
+                       | MCF_FBCS_CSCR_WS(7));
+       MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
+                       | MCF_FBCS_CSMR_V);
+}
+
+void sdramc_init(void)
+{
+       /*
+        * Check to see if the SDRAM has already been initialized
+        * by a run control tool
+        */
+       if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
+               /* SDRAM chip select initialization */
+               
+               /* Initialize SDRAM chip select */
+               MCF_SDRAMC_SDCS0 = (0
+                       | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
+                       | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
+
+       /*
+        * Basic configuration and initialization
+        */
+       MCF_SDRAMC_SDCFG1 = (0
+               | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
+               | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
+               | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
+               | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
+               | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
+               | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
+               | MCF_SDRAMC_SDCFG1_WTLAT(3));
+       MCF_SDRAMC_SDCFG2 = (0
+               | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
+               | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
+               | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
+               | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
+
+            
+       /*
+        * Precharge and enable write to SDMR
+        */
+        MCF_SDRAMC_SDCR = (0
+               | MCF_SDRAMC_SDCR_MODE_EN
+               | MCF_SDRAMC_SDCR_CKE
+               | MCF_SDRAMC_SDCR_DDR
+               | MCF_SDRAMC_SDCR_MUX(1)
+               | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
+               | MCF_SDRAMC_SDCR_PS_16
+               | MCF_SDRAMC_SDCR_IPALL);            
+
+       /*
+        * Write extended mode register
+        */
+       MCF_SDRAMC_SDMR = (0
+               | MCF_SDRAMC_SDMR_BNKAD_LEMR
+               | MCF_SDRAMC_SDMR_AD(0x0)
+               | MCF_SDRAMC_SDMR_CMD);
+
+       /*
+        * Write mode register and reset DLL
+        */
+       MCF_SDRAMC_SDMR = (0
+               | MCF_SDRAMC_SDMR_BNKAD_LMR
+               | MCF_SDRAMC_SDMR_AD(0x163)
+               | MCF_SDRAMC_SDMR_CMD);
+
+       /*
+        * Execute a PALL command
+        */
+       MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
+
+       /*
+        * Perform two REF cycles
+        */
+       MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+       MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+
+       /*
+        * Write mode register and clear reset DLL
+        */
+       MCF_SDRAMC_SDMR = (0
+               | MCF_SDRAMC_SDMR_BNKAD_LMR
+               | MCF_SDRAMC_SDMR_AD(0x063)
+               | MCF_SDRAMC_SDMR_CMD);
+                               
+       /*
+        * Enable auto refresh and lock SDMR
+        */
+       MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
+       MCF_SDRAMC_SDCR |= (0
+               | MCF_SDRAMC_SDCR_REF
+               | MCF_SDRAMC_SDCR_DQS_OE(0xC));
+       }
+}
+
+void gpio_init(void)
+{
+       /* Enable UART0 pins */
+       MCF_GPIO_PAR_UART = ( 0
+               | MCF_GPIO_PAR_UART_PAR_URXD0
+               | MCF_GPIO_PAR_UART_PAR_UTXD0);
+
+       /* Initialize TIN3 as a GPIO output to enable the write
+          half of the latch */
+       MCF_GPIO_PAR_TIMER = 0x00;
+       MCF_GPIO_PDDR_TIMER = 0x08;
+       MCF_GPIO_PCLRR_TIMER = 0x0;
+
+}
+
+int clock_pll(int fsys, int flags)
+{
+       int fref, temp, fout, mfd;
+       u32 i;
+
+       fref = FREF;
+        
+       if (fsys == 0) {
+               /* Return current PLL output */
+               mfd = MCF_PLL_PFDR;
+
+               return (fref * mfd / (BUSDIV * 4));
+       }
+
+       /* Check bounds of requested system clock */
+       if (fsys > MAX_FSYS)
+               fsys = MAX_FSYS;
+       if (fsys < MIN_FSYS)
+               fsys = MIN_FSYS;
+
+       /* Multiplying by 100 when calculating the temp value,
+          and then dividing by 100 to calculate the mfd allows
+          for exact values without needing to include floating
+          point libraries. */
+       temp = 100 * fsys / fref;
+       mfd = 4 * BUSDIV * temp / 100;
+                       
+       /* Determine the output frequency for selected values */
+       fout = (fref * mfd / (BUSDIV * 4));
+
+       /*
+        * Check to see if the SDRAM has already been initialized.
+        * If it has then the SDRAM needs to be put into self refresh
+        * mode before reprogramming the PLL.
+        */
+       if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+               /* Put SDRAM into self refresh mode */
+               MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
+
+       /*
+        * Initialize the PLL to generate the new system clock frequency.
+        * The device must be put into LIMP mode to reprogram the PLL.
+        */
+
+       /* Enter LIMP mode */
+       clock_limp(DEFAULT_LPD);
+                                       
+       /* Reprogram PLL for desired fsys */
+       MCF_PLL_PODR = (0
+               | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
+               | MCF_PLL_PODR_BUSDIV(BUSDIV));
+                                               
+       MCF_PLL_PFDR = mfd;
+               
+       /* Exit LIMP mode */
+       clock_exit_limp();
+       
+       /*
+        * Return the SDRAM to normal operation if it is in use.
+        */
+       if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+               /* Exit self refresh mode */
+               MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
+
+       /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
+       MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
+
+       /* wait for DQS logic to relock */
+       for (i = 0; i < 0x200; i++)
+               ;
+
+       return fout;
+}
+
+int clock_limp(int div)
+{
+       u32 temp;
+
+       /* Check bounds of divider */
+       if (div < MIN_LPD)
+               div = MIN_LPD;
+       if (div > MAX_LPD)
+               div = MAX_LPD;
+    
+       /* Save of the current value of the SSIDIV so we don't
+          overwrite the value*/
+       temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
+      
+       /* Apply the divider to the system clock */
+       MCF_CCM_CDR = ( 0
+               | MCF_CCM_CDR_LPDIV(div)
+               | MCF_CCM_CDR_SSIDIV(temp));
+    
+       MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
+    
+       return (FREF/(3*(1 << div)));
+}
+
+int clock_exit_limp(void)
+{
+       int fout;
+       
+       /* Exit LIMP mode */
+       MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
+
+       /* Wait for PLL to lock */
+       while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
+               ;
+       
+       fout = get_sys_clock();
+
+       return fout;
+}
+
+int get_sys_clock(void)
+{
+       int divider;
+       
+       /* Test to see if device is in LIMP mode */
+       if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
+               divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
+               return (FREF/(2 << divider));
+       }
+       else
+               return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
+}
diff --git a/arch/m68knommu/platform/68328/romvec.S b/arch/m68knommu/platform/68328/romvec.S
new file mode 100644 (file)
index 0000000..3108446
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * linux/arch/m68knommu/platform/68328/romvec.S
+ *
+ * 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 1996 Roman Zippel
+ * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
+ * Copyright 2006 Greg Ungerer <gerg@snapgear.com>
+ */
+
+.global _start
+.global _buserr
+.global trap
+.global system_call
+
+.section .romvec
+
+e_vectors:
+.long CONFIG_RAMBASE+CONFIG_RAMSIZE-4, _start, buserr, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+/* TRAP #0-15 */
+.long system_call, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile
new file mode 100644 (file)
index 0000000..519142c
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for Basler eXcite
+#
+
+obj-$(CONFIG_BASLER_EXCITE)    += excite_irq.o excite_prom.o excite_setup.o \
+                                  excite_device.o excite_procfs.o
+
+obj-$(CONFIG_KGDB)             += excite_dbg_io.o
+obj-m                          += excite_iodev.o
diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c
new file mode 100644 (file)
index 0000000..c04505a
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.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 <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/gdb-stub.h>
+#include <asm/rm9k-ocd.h>
+#include <excite.h>
+
+#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1
+#error Debug port used by serial driver
+#endif
+
+#define UART_CLK               25000000
+#define BASE_BAUD              (UART_CLK / 16)
+#define REGISTER_BASE_0                0x0208UL
+#define REGISTER_BASE_1                0x0238UL
+
+#define REGISTER_BASE_DBG      REGISTER_BASE_1
+
+#define CPRR   0x0004
+#define UACFG  0x0200
+#define UAINTS 0x0204
+#define UARBR  (REGISTER_BASE_DBG + 0x0000)
+#define UATHR  (REGISTER_BASE_DBG + 0x0004)
+#define UADLL  (REGISTER_BASE_DBG + 0x0008)
+#define UAIER  (REGISTER_BASE_DBG + 0x000c)
+#define UADLH  (REGISTER_BASE_DBG + 0x0010)
+#define UAIIR  (REGISTER_BASE_DBG + 0x0014)
+#define UAFCR  (REGISTER_BASE_DBG + 0x0018)
+#define UALCR  (REGISTER_BASE_DBG + 0x001c)
+#define UAMCR  (REGISTER_BASE_DBG + 0x0020)
+#define UALSR  (REGISTER_BASE_DBG + 0x0024)
+#define UAMSR  (REGISTER_BASE_DBG + 0x0028)
+#define UASCR  (REGISTER_BASE_DBG + 0x002c)
+
+#define        PARITY_NONE     0
+#define        PARITY_ODD      0x08
+#define        PARITY_EVEN     0x18
+#define        PARITY_MARK     0x28
+#define        PARITY_SPACE    0x38
+
+#define        DATA_5BIT       0x0
+#define        DATA_6BIT       0x1
+#define        DATA_7BIT       0x2
+#define        DATA_8BIT       0x3
+
+#define        STOP_1BIT       0x0
+#define        STOP_2BIT       0x4
+
+#define BAUD_DBG       57600
+#define        PARITY_DBG      PARITY_NONE
+#define        DATA_DBG        DATA_8BIT
+#define        STOP_DBG        STOP_1BIT
+
+/* Initialize the serial port for KGDB debugging */
+void __init excite_kgdb_init(void)
+{
+       const u32 divisor = BASE_BAUD / BAUD_DBG;
+
+       /* Take the UART out of reset */
+       titan_writel(0x00ff1cff, CPRR);
+       titan_writel(0x00000000, UACFG);
+       titan_writel(0x00000002, UACFG);
+
+       titan_writel(0x0, UALCR);
+       titan_writel(0x0, UAIER);
+
+       /* Disable FIFOs */
+       titan_writel(0x00, UAFCR);
+
+       titan_writel(0x80, UALCR);
+       titan_writel(divisor & 0xff, UADLL);
+       titan_writel((divisor & 0xff00) >> 8, UADLH);
+       titan_writel(0x0, UALCR);
+
+       titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR);
+
+       /* Enable receiver interrupt */
+       titan_readl(UARBR);
+       titan_writel(0x1, UAIER);
+}
+
+int getDebugChar(void)
+{
+       while (!(titan_readl(UALSR) & 0x1));
+       return titan_readl(UARBR);
+}
+
+int putDebugChar(int data)
+{
+       while (!(titan_readl(UALSR) & 0x20));
+       titan_writel(data, UATHR);
+       return 1;
+}
+
+/* KGDB interrupt handler */
+asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs)
+{
+       if (unlikely(
+               ((titan_readl(UAIIR) & 0x7) == 4)
+               && ((titan_readl(UARBR) & 0xff) == 0x3)))
+                       set_async_breakpoint(&regs->cp0_epc);
+}
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
new file mode 100644 (file)
index 0000000..bbb4ea4
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/types.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+#include <rm9k_eth.h>
+#include <rm9k_wdt.h>
+#include <rm9k_xicap.h>
+#include <excite_nandflash.h>
+
+#include "excite_iodev.h"
+
+#define RM9K_GE_UNIT   0
+#define XICAP_UNIT     0
+#define NAND_UNIT      0
+
+#define DLL_TIMEOUT    3               /* seconds */
+
+
+#define RINIT(__start__, __end__, __name__, __parent__) {      \
+       .name   = __name__ "_0",                                \
+       .start  = (__start__),                                  \
+       .end    = (__end__),                                    \
+       .flags  = 0,                                            \
+       .parent = (__parent__)                                  \
+}
+
+#define RINIT_IRQ(__irq__, __name__) { \
+       .name   = __name__ "_0",        \
+       .start  = (__irq__),            \
+       .end    = (__irq__),            \
+       .flags  = IORESOURCE_IRQ,       \
+       .parent = NULL                  \
+}
+
+
+
+enum {
+       slice_xicap,
+       slice_eth
+};
+
+
+
+static struct resource
+       excite_ctr_resource = {
+               .name           = "GPI counters",
+               .start          = 0,
+               .end            = 5,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_gpislice_resource = {
+               .name           = "GPI slices",
+               .start          = 0,
+               .end            = 1,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_mdio_channel_resource = {
+               .name           = "MDIO channels",
+               .start          = 0,
+               .end            = 1,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_fifomem_resource = {
+               .name           = "FIFO memory",
+               .start          = 0,
+               .end            = 767,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_scram_resource = {
+               .name           = "Scratch RAM",
+               .start          = EXCITE_PHYS_SCRAM,
+               .end            = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_fpga_resource = {
+               .name           = "System FPGA",
+               .start          = EXCITE_PHYS_FPGA,
+               .end            = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_nand_resource = {
+               .name           = "NAND flash control",
+               .start          = EXCITE_PHYS_NAND,
+               .end            = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_titan_resource = {
+               .name           = "TITAN registers",
+               .start          = EXCITE_PHYS_TITAN,
+               .end            = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       };
+
+
+
+static void adjust_resources(struct resource *res, unsigned int n)
+{
+       struct resource *p;
+       const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM
+                                  | IORESOURCE_IRQ | IORESOURCE_DMA;
+
+       for (p = res; p < res + n; p++) {
+               const struct resource * const parent = p->parent;
+               if (parent) {
+                       p->start += parent->start;
+                       p->end   += parent->start;
+                       p->flags =  parent->flags & mask;
+               }
+       }
+}
+
+
+
+#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE)
+static struct resource xicap_rsrc[] = {
+       RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource),
+       RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource),
+       RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource),
+       RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource),
+       RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource),
+       RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource),
+       RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
+       RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource),
+       RINIT_IRQ(TITAN_IRQ,  XICAP_RESOURCE_IRQ)
+};
+
+static struct platform_device xicap_pdev = {
+       .name           = XICAP_NAME,
+       .id             = XICAP_UNIT,
+       .num_resources  = ARRAY_SIZE(xicap_rsrc),
+       .resource       = xicap_rsrc
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init xicap_devinit(void)
+{
+       unsigned long tend;
+       u32 reg;
+       int retval;
+
+       adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc));
+
+       /* Power up the slice and configure it. */
+       reg = titan_readl(CPTC1R);
+       reg &= ~(0x11100 << slice_xicap);
+       titan_writel(reg, CPTC1R);
+
+       /* Enable slice & DLL. */
+       reg= titan_readl(CPRR);
+       reg &= ~(0x00030003 << (slice_xicap * 2));
+       titan_writel(reg, CPRR);
+
+       /* Wait for DLLs to lock */
+       tend = jiffies + DLL_TIMEOUT * HZ;
+       while (time_before(jiffies, tend)) {
+               if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))))
+                       break;
+               yield();
+       }
+
+       if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) {
+               printk(KERN_ERR "%s: DLL not locked after %u seconds\n",
+                      xicap_pdev.name, DLL_TIMEOUT);
+               retval = -ETIME;
+       } else {
+               /* Register platform device */
+               retval = platform_device_register(&xicap_pdev);
+       }
+
+       return retval;
+}
+
+device_initcall(xicap_devinit);
+#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */
+
+
+
+#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE)
+static struct resource wdt_rsrc[] = {
+       RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource),
+       RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource),
+       RINIT_IRQ(TITAN_IRQ,  WDT_RESOURCE_IRQ)
+};
+
+static struct platform_device wdt_pdev = {
+       .name           = WDT_NAME,
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(wdt_rsrc),
+       .resource       = wdt_rsrc
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init wdt_devinit(void)
+{
+       adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc));
+       return platform_device_register(&wdt_pdev);
+}
+
+device_initcall(wdt_devinit);
+#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */
+
+
+
+static struct resource excite_nandflash_rsrc[] = {
+       RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS,  &excite_nand_resource)
+};
+
+static struct platform_device excite_nandflash_pdev = {
+       .name           = "excite_nand",
+       .id             = NAND_UNIT,
+       .num_resources  = ARRAY_SIZE(excite_nandflash_rsrc),
+       .resource       = excite_nandflash_rsrc
+};
+
+/*
+ * Create a platform device for the access to the nand-flash
+ * port
+ */
+static int __init excite_nandflash_devinit(void)
+{
+       adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc));
+
+        /* nothing to be done here */
+
+        /* Register platform device */
+       return platform_device_register(&excite_nandflash_pdev);
+}
+
+device_initcall(excite_nandflash_devinit);
+
+
+
+static struct resource iodev_rsrc[] = {
+       RINIT_IRQ(FPGA1_IRQ,  IODEV_RESOURCE_IRQ)
+};
+
+static struct platform_device io_pdev = {
+       .name           = IODEV_NAME,
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(iodev_rsrc),
+       .resource       = iodev_rsrc
+};
+
+/*
+ * Create a platform device for the external I/O ports.
+ */
+static int __init io_devinit(void)
+{
+       adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc));
+       return platform_device_register(&io_pdev);
+}
+
+device_initcall(io_devinit);
+
+
+
+
+#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE)
+static struct resource rm9k_ge_rsrc[] = {
+       RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource),
+       RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource),
+       RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource),
+       RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource),
+       RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource),
+       RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource),
+       RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource),
+       RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource),
+       RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource),
+       RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource),
+       RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource),
+       RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
+       RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource),
+       RINIT_IRQ(TITAN_IRQ,  RM9K_GE_RESOURCE_IRQ_MAIN),
+       RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY)
+};
+
+static struct platform_device rm9k_ge_pdev = {
+       .name           = RM9K_GE_NAME,
+       .id             = RM9K_GE_UNIT,
+       .num_resources  = ARRAY_SIZE(rm9k_ge_rsrc),
+       .resource       = rm9k_ge_rsrc
+};
+
+
+
+/*
+ * Create a platform device for the Ethernet port.
+ */
+static int __init rm9k_ge_devinit(void)
+{
+       u32 reg;
+
+       adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc));
+
+       /* Power up the slice and configure it. */
+       reg = titan_readl(CPTC1R);
+       reg &= ~(0x11000 << slice_eth);
+       reg |= 0x100 << slice_eth;
+       titan_writel(reg, CPTC1R);
+
+       /* Take the MAC out of reset, reset the DLLs. */
+       reg = titan_readl(CPRR);
+       reg &= ~(0x00030000 << (slice_eth * 2));
+       reg |= 0x3 << (slice_eth * 2);
+       titan_writel(reg, CPRR);
+
+       return platform_device_register(&rm9k_ge_pdev);
+}
+
+device_initcall(rm9k_ge_devinit);
+#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */
+
+
+
+static int __init excite_setup_devs(void)
+{
+       int res;
+       u32 reg;
+
+       /* Enable xdma and fifo interrupts */
+       reg = titan_readl(0x0050);
+       titan_writel(reg | 0x18000000, 0x0050);
+
+       res = request_resource(&iomem_resource, &excite_titan_resource);
+       if (res)
+               return res;
+       res = request_resource(&iomem_resource, &excite_scram_resource);
+       if (res)
+               return res;
+       res = request_resource(&iomem_resource, &excite_fpga_resource);
+       if (res)
+               return res;
+       res = request_resource(&iomem_resource, &excite_nand_resource);
+       if (res)
+               return res;
+       excite_fpga_resource.flags = excite_fpga_resource.parent->flags &
+                                  ( IORESOURCE_IO | IORESOURCE_MEM
+                                  | IORESOURCE_IRQ | IORESOURCE_DMA);
+       excite_nand_resource.flags = excite_nand_resource.parent->flags &
+                                  ( IORESOURCE_IO | IORESOURCE_MEM
+                                  | IORESOURCE_IRQ | IORESOURCE_DMA);
+
+       return 0;
+}
+
+arch_initcall(excite_setup_devs);
+
diff --git a/arch/mips/basler/excite/excite_flashtest.c b/arch/mips/basler/excite/excite_flashtest.c
new file mode 100644 (file)
index 0000000..f0024a8
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+*  Copyright (C) 2005 by Basler Vision Technologies AG
+*  Author: Thies Moeller <thies.moeller@baslerweb.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/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#include <excite.h>
+
+#include <asm/io.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <asm/rm9k-ocd.h> // for ocd_write
+#include <linux/workqueue.h> // for queue
+
+#include "excite_nandflash.h"
+#include "nandflash.h"
+
+#define PFX "excite flashtest: "
+typedef void __iomem *io_reg_t;
+
+#define io_readb(__a__)                __raw_readb((__a__))
+#define io_writeb(__v__, __a__)        __raw_writeb((__v__), (__a__))
+
+
+
+static inline const struct resource *excite_nandflash_get_resource(
+       struct platform_device *d, unsigned long flags, const char *basename)
+{
+       const char fmt[] = "%s_%u";
+       char buf[80];
+
+       if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf))
+               return NULL;
+
+       return platform_get_resource_byname(d, flags, buf);
+}
+
+static inline io_reg_t
+excite_nandflash_map_regs(struct platform_device *d, const char *basename)
+{
+       void *result = NULL;
+       const struct resource *const r =
+           excite_nandflash_get_resource(d, IORESOURCE_MEM, basename);
+       if (r)
+          result = ioremap_nocache(r->start, r->end + 1 - r->start);
+       return result;
+}
+
+/* controller and mtd information */
+
+struct excite_nandflash_drvdata {
+       struct mtd_info board_mtd;
+       struct nand_chip board_chip;
+       io_reg_t regs;
+};
+
+
+/* command and control functions */
+static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+       struct nand_chip *this = mtd->priv;
+       io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs;
+
+       switch (cmd) {
+       /* Select the command latch */
+       case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD;
+               break;
+       /* Deselect the command latch */
+       case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA;
+               break;
+       /* Select the address latch */
+       case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR;
+               break;
+       /* Deselect the address latch */
+       case NAND_CTL_CLRALE: this->IO_ADDR_W = regs  + EXCITE_NANDFLASH_DATA;
+               break;
+       /* Select the chip  -- not used */
+       case NAND_CTL_SETNCE:
+               break;
+       /* Deselect the chip -- not used */
+       case NAND_CTL_CLRNCE:
+               break;
+       }
+
+       this->IO_ADDR_R = this->IO_ADDR_W;
+}
+
+/* excite_nandflash_devready()
+ *
+ * returns 0 if the nand is busy, 1 if it is ready
+ */
+static int excite_nandflash_devready(struct mtd_info *mtd)
+{
+       struct excite_nandflash_drvdata *drvdata =
+           container_of(mtd, struct excite_nandflash_drvdata, board_mtd);
+
+       return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+}
+
+/* device management functions */
+
+/* excite_nandflash_remove
+ *
+ * called by device layer to remove the driver
+ * the binding to the mtd and all allocated
+ * resources are released
+ */
+static int excite_nandflash_remove(struct device *dev)
+{
+       struct excite_nandflash_drvdata *this = dev_get_drvdata(dev);
+
+       pr_info(PFX "remove");
+
+       dev_set_drvdata(dev, NULL);
+
+       if (this == NULL) {
+               pr_debug(PFX "call remove without private data!!");
+               return 0;
+       }
+
+
+       /* free the common resources */
+       if (this->regs != NULL) {
+               iounmap(this->regs);
+               this->regs = NULL;
+       }
+
+       kfree(this);
+
+       return 0;
+}
+
+static int elapsed;
+
+void my_workqueue_handler(void *arg)
+{
+       elapsed = 1;
+}
+
+DECLARE_WORK(sigElapsed, my_workqueue_handler, 0);
+
+
+/* excite_nandflash_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code checks to see if
+ * it can allocate all necessary resources then calls the
+ * nand layer to look for devices
+*/
+static int excite_nandflash_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+
+       struct excite_nandflash_drvdata *drvdata;           /* private driver data     */
+       struct nand_chip              *board_chip;  /* private flash chip data */
+       struct mtd_info               *board_mtd;   /* mtd info for this board */
+
+       int err      = 0;
+       int count    = 0;
+       struct timeval tv,endtv;
+       unsigned int dt;
+
+       pr_info(PFX "probe dev: (%p)\n", dev);
+
+       pr_info(PFX "adjust LB timing\n");
+       ocd_writel(0x00000330, LDP2);
+
+       drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL);
+       if (unlikely(!drvdata)) {
+               printk(KERN_ERR PFX "no memory for drvdata\n");
+               err = -ENOMEM;
+               goto mem_error;
+       }
+
+       /* Initialize structures */
+       memset(drvdata, 0, sizeof(*drvdata));
+
+       /* bind private data into driver */
+       dev_set_drvdata(dev, drvdata);
+
+       /* allocate and map the resource */
+       drvdata->regs =
+           excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
+
+       if (unlikely(!drvdata->regs)) {
+               printk(KERN_ERR PFX "cannot reserve register region\n");
+               err = -ENXIO;
+               goto io_error;
+       }
+
+       /* initialise our chip */
+       board_chip = &drvdata->board_chip;
+
+       board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA;
+       board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA;
+
+       board_chip->hwcontrol = excite_nandflash_hwcontrol;
+       board_chip->dev_ready = excite_nandflash_devready;
+
+       board_chip->chip_delay = 25;
+       #if 0
+       /* TODO: speedup the initial scan */
+       board_chip->options = NAND_USE_FLASH_BBT;
+       #endif
+       board_chip->eccmode = NAND_ECC_SOFT;
+
+       /* link chip to mtd */
+       board_mtd = &drvdata->board_mtd;
+       board_mtd->priv = board_chip;
+
+
+       pr_info(PFX "FlashTest\n");
+       elapsed = 0;
+/*     schedule_delayed_work(&sigElapsed, 1*HZ);
+       while (!elapsed) {
+               io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+               count++;
+       }
+       pr_info(PFX "reads in 1 sec --> %d\n",count);
+*/
+       do_gettimeofday(&tv);
+       for (count = 0 ; count < 1000000; count ++) {
+               io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+       }
+       do_gettimeofday(&endtv);
+       dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec  - tv.tv_usec;
+       pr_info(PFX "%8d us timeval\n",dt);
+       pr_info(PFX "EndFlashTest\n");
+
+/*      return with error to unload everything
+*/
+io_error:
+       iounmap(drvdata->regs);
+
+mem_error:
+       kfree(drvdata);
+
+       if (err == 0)
+               err = -EINVAL;
+       return err;
+}
+
+static struct device_driver excite_nandflash_driver = {
+       .name = "excite_nand",
+       .bus = &platform_bus_type,
+       .probe = excite_nandflash_probe,
+       .remove = excite_nandflash_remove,
+};
+
+static int __init excite_nandflash_init(void)
+{
+       pr_info(PFX "register Driver (Rev: $Revision:$)\n");
+       return driver_register(&excite_nandflash_driver);
+}
+
+static void __exit excite_nandflash_exit(void)
+{
+       driver_unregister(&excite_nandflash_driver);
+       pr_info(PFX "Driver unregistered");
+}
+
+module_init(excite_nandflash_init);
+module_exit(excite_nandflash_exit);
+
+MODULE_AUTHOR("Thies Moeller <thies.moeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h
new file mode 100644 (file)
index 0000000..38fcda7
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef EXCITE_FPGA_H_INCLUDED
+#define EXCITE_FPGA_H_INCLUDED
+
+
+/**
+ * Adress alignment of the individual FPGA bytes.
+ * The address arrangement of the individual bytes of the FPGA is two
+ * byte aligned at the embedded MK2 platform.
+ */
+#ifdef EXCITE_CCI_FPGA_MK2
+typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
+#else
+typedef unsigned char excite_cci_fpga_align_t;
+#endif
+
+
+/**
+ * Size of Dual Ported RAM.
+ */
+#define EXCITE_DPR_SIZE 263
+
+
+/**
+ * Size of Reserved Status Fields in Dual Ported RAM.
+ */
+#define EXCITE_DPR_STATUS_SIZE 7
+
+
+
+/**
+ * FPGA.
+ * Hardware register layout of the FPGA interface. The FPGA must accessed
+ * byte wise solely.
+ * @see EXCITE_CCI_DPR_MK2
+ */
+typedef struct excite_fpga {
+
+       /**
+        * Dual Ported RAM.
+        */
+       excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
+
+       /**
+        * Status.
+        */
+       excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
+
+#ifdef EXCITE_CCI_FPGA_MK2
+       /**
+        * RM9000 Interrupt.
+        * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
+        */
+       excite_cci_fpga_align_t rm9k_int;
+#else
+       /**
+        * MK2 Interrupt.
+        * Write access initiates interrupt at the ARM processor of the MK2.
+        */
+       excite_cci_fpga_align_t mk2_int;
+
+       excite_cci_fpga_align_t gap[0x1000-0x10f];
+
+       /**
+        * IRQ Source/Acknowledge.
+        */
+       excite_cci_fpga_align_t rm9k_irq_src;
+
+       /**
+        * IRQ Mask.
+        * Set bits enable the related interrupt.
+        */
+       excite_cci_fpga_align_t rm9k_irq_mask;
+#endif
+
+
+} excite_fpga;
+
+
+
+#endif /* ndef EXCITE_FPGA_H_INCLUDED */
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
new file mode 100644 (file)
index 0000000..10bbb8c
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  Copyright (C) 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+
+#include "excite_iodev.h"
+
+
+
+static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
+static int __init iodev_probe(struct device *);
+static int __exit iodev_remove(struct device *);
+static int iodev_open(struct inode *, struct file *);
+static int iodev_release(struct inode *, struct file *);
+static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
+static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
+static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *);
+
+
+
+static const char iodev_name[] = "iodev";
+static unsigned int iodev_irq;
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+
+
+static struct file_operations fops =
+{
+       .owner          = THIS_MODULE,
+       .open           = iodev_open,
+       .release        = iodev_release,
+       .read           = iodev_read,
+       .poll           = iodev_poll
+};
+
+static struct miscdevice miscdev =
+{
+       .minor          = MISC_DYNAMIC_MINOR,
+       .name           = iodev_name,
+       .fops           = &fops
+};
+
+static struct device_driver iodev_driver =
+{
+       .name           = (char *) iodev_name,
+       .bus            = &platform_bus_type,
+       .owner          = THIS_MODULE,
+       .probe          = iodev_probe,
+       .remove         = __exit_p(iodev_remove)
+};
+
+
+
+static const struct resource *
+iodev_get_resource(struct platform_device *pdv, const char *name,
+                    unsigned int type)
+{
+       char buf[80];
+       if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
+               return NULL;
+       return platform_get_resource_byname(pdv, type, buf);
+}
+
+
+
+/* No hotplugging on the platform bus - use __init */
+static int __init iodev_probe(struct device *dev)
+{
+       struct platform_device * const pdv = to_platform_device(dev);
+       const struct resource * const ri =
+               iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
+
+       if (unlikely(!ri))
+               return -ENXIO;
+
+       iodev_irq = ri->start;
+       return misc_register(&miscdev);
+}
+
+
+
+static int __exit iodev_remove(struct device *dev)
+{
+       return misc_deregister(&miscdev);
+}
+
+
+
+static int iodev_open(struct inode *i, struct file *f)
+{
+       return request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED,
+                          iodev_name, &miscdev);
+}
+
+
+
+static int iodev_release(struct inode *i, struct file *f)
+{
+       free_irq(iodev_irq, &miscdev);
+       return 0;
+}
+
+
+
+
+static ssize_t
+iodev_read(struct file *f, char __user *d, size_t s, loff_t *o)
+{
+       ssize_t ret;
+       DEFINE_WAIT(w);
+
+       prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE);
+       if (!signal_pending(current))
+               schedule();
+       ret = signal_pending(current) ? -ERESTARTSYS : 0;
+       finish_wait(&wq, &w);
+       return ret;
+}
+
+
+static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p)
+{
+       poll_wait(f, &wq, p);
+       return POLLOUT | POLLWRNORM;
+}
+
+
+
+
+static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
+{
+       wake_up(&wq);
+       return IRQ_HANDLED;
+}
+
+
+
+static int __init iodev_init_module(void)
+{
+       return driver_register(&iodev_driver);
+}
+
+
+
+static void __exit iodev_cleanup_module(void)
+{
+       driver_unregister(&iodev_driver);
+}
+
+module_init(iodev_init_module);
+module_exit(iodev_cleanup_module);
+
+
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler");
+MODULE_VERSION("0.0");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h
new file mode 100644 (file)
index 0000000..cbfbb5d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __EXCITE_IODEV_H__
+#define __EXCITE_IODEV_H__
+
+/* Device name */
+#define IODEV_NAME             "iodev"
+
+/* Resource names */
+#define IODEV_RESOURCE_IRQ     "excite_iodev_irq"
+
+#endif /* __EXCITE_IODEV_H__ */
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
new file mode 100644 (file)
index 0000000..511ad87
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  Copyright (C) by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslereb.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/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+extern asmlinkage void excite_handle_int(void);
+
+/*
+ * Initialize the interrupt handler
+ */
+void __init arch_init_irq(void)
+{
+       mips_cpu_irq_init(0);
+       rm7k_cpu_irq_init(8);
+       rm9k_cpu_irq_init(12);
+
+#ifdef CONFIG_KGDB
+       excite_kgdb_init();
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       const u32
+               interrupts = read_c0_cause() >> 8,
+               mask = ((read_c0_status() >> 8) & 0x000000ff) |
+                      (read_c0_intcontrol() & 0x0000ff00),
+               pending = interrupts & mask;
+       u32 msgintflags, msgintmask, msgint;
+
+       /* process timer interrupt */
+       if (pending & (1 << TIMER_IRQ)) {
+               do_IRQ(TIMER_IRQ, regs);
+               return;
+       }
+
+       /* Process PCI interrupts */
+#if USB_IRQ < 10
+       msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20));
+       if ((pending & (1 << USB_IRQ)) && msgint) {
+#else
+       if (pending & (1 << USB_IRQ)) {
+#endif
+               do_IRQ(USB_IRQ, regs);
+               return;
+       }
+
+       /* Process TITAN interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
+       if ((pending & (1 << TITAN_IRQ)) && msgint) {
+               ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
+#if defined(CONFIG_KGDB)
+               excite_kgdb_inthdl(regs);
+#endif
+               do_IRQ(TITAN_IRQ, regs);
+               return;
+       }
+
+       /* Process FPGA line #0 interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20));
+       if ((pending & (1 << FPGA0_IRQ)) && msgint) {
+               do_IRQ(FPGA0_IRQ, regs);
+               return;
+       }
+
+       /* Process FPGA line #1 interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20));
+       if ((pending & (1 << FPGA1_IRQ)) && msgint) {
+               do_IRQ(FPGA1_IRQ, regs);
+               return;
+       }
+
+       /* Process PHY interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20));
+       if ((pending & (1 << PHY_IRQ)) && msgint) {
+               do_IRQ(PHY_IRQ, regs);
+               return;
+       }
+
+       /* Process spurious interrupts */
+       spurious_interrupt(regs);
+}
diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c
new file mode 100644 (file)
index 0000000..9ee67a9
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  Procfs support for Basler eXcite
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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/proc_fs.h>
+#include <linux/stat.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size)
+{
+       const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id);
+       const int w = len - offs;
+       *addr = buf + offs;
+       return w < size ? w : size;
+}
+
+static int
+excite_bootrom_read(char *page, char **start, off_t off, int count,
+                 int *eof, void *data)
+{
+       void __iomem * src;
+
+       if (off >= EXCITE_SIZE_BOOTROM) {
+               *eof = 1;
+               return 0;
+       }
+
+       if ((off + count) > EXCITE_SIZE_BOOTROM)
+               count = EXCITE_SIZE_BOOTROM - off;
+
+       src = ioremap(EXCITE_PHYS_BOOTROM + off, count);
+       if (src) {
+               memcpy_fromio(page, src, count);
+               iounmap(src);
+               *start = page;
+       } else {
+               count = -ENOMEM;
+       }
+
+       return count;
+}
+
+void excite_procfs_init(void)
+{
+       /* Create & populate /proc/excite */
+       struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root);
+       if (pdir) {
+               struct proc_dir_entry * e;
+
+               e = create_proc_info_entry("unit_id", S_IRUGO, pdir,
+                                          excite_get_unit_id);
+               if (e) e->size = 6;
+
+               e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
+                                          excite_bootrom_read, NULL);
+               if (e) e->size = EXCITE_SIZE_BOOTROM;
+       }
+}
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c
new file mode 100644 (file)
index 0000000..6ecd512
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com)
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
+ *  Manish Lachwani.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/string.h>
+
+#include <excite.h>
+
+/* This struct is used by Redboot to pass arguments to the kernel */
+typedef struct
+{
+       char *name;
+       char *val;
+} t_env_var;
+
+struct parmblock {
+       t_env_var memsize;
+       t_env_var modetty0;
+       t_env_var ethaddr;
+       t_env_var env_end;
+       char *argv[2];
+       char text[0];
+};
+
+static unsigned int prom_argc;
+static const char ** prom_argv;
+static const t_env_var * prom_env;
+
+static void prom_halt(void) __attribute__((noreturn));
+static void prom_exit(void) __attribute__((noreturn));
+
+
+
+const char *get_system_type(void)
+{
+       return "Basler eXcite";
+}
+
+/*
+ * Halt the system
+ */
+static void prom_halt(void)
+{
+       printk(KERN_NOTICE "\n** System halted.\n");
+       while (1)
+               asm volatile (
+                       "\t.set\tmips3\n"
+                       "\twait\n"
+                       "\t.set\tmips0\n"
+               );
+}
+
+/*
+ * Reset the CPU and re-enter Redboot
+ */
+static void prom_exit(void)
+{
+       unsigned int i;
+       volatile unsigned char * const flg =
+               (volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR);
+
+       /* Clear the watchdog reset flag, set the reboot flag */
+       *flg &= ~0x01;
+       *flg |= 0x80;
+
+       for (i = 0; i < 10; i++) {
+               *(volatile unsigned char *)  (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02;
+               iob();
+               mdelay(1000);
+       }
+
+       printk(KERN_NOTICE "Reset failed\n");
+       prom_halt();
+}
+
+static const char __init *prom_getenv(char *name)
+{
+       const t_env_var * p;
+       for (p = prom_env; p->name != NULL; p++)
+               if(strcmp(name, p->name) == 0)
+                       break;
+       return p->val;
+}
+
+/*
+ * Init routine which accepts the variables from Redboot
+ */
+void __init prom_init(void)
+{
+       const struct parmblock * const pb = (struct parmblock *) fw_arg2;
+
+       prom_argc = fw_arg0;
+       prom_argv = (const char **) fw_arg1;
+       prom_env = &pb->memsize;
+
+       /* Callbacks for halt, restart */
+       _machine_restart = (void (*)(char *)) prom_exit;
+       _machine_halt = prom_halt;
+
+#ifdef CONFIG_32BIT
+       /* copy command line */
+       strcpy(arcs_cmdline, prom_argv[1]);
+       memsize = simple_strtol(prom_getenv("memsize"), NULL, 16);
+       strcpy(modetty, prom_getenv("modetty0"));
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#      error 64 bit support not implemented
+#endif /* CONFIG_64BIT */
+
+       mips_machgroup = MACH_GROUP_TITAN;
+       mips_machtype = MACH_TITAN_EXCITE;
+}
+
+/* This is called from free_initmem(), so we need to provide it */
+void __init prom_free_prom_memory(void)
+{
+       /* Nothing to do */
+}
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
new file mode 100644 (file)
index 0000000..a1ce458
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
+ *  Manish Lachwani.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable-32.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+#define TITAN_UART_CLK 25000000
+
+#if 1
+/* normal serial port assignment */
+#define REGBASE_SER0   0x0208
+#define REGBASE_SER1   0x0238
+#define MASK_SER0      0x1
+#define MASK_SER1      0x2
+#else
+/* serial ports swapped */
+#define REGBASE_SER0   0x0238
+#define REGBASE_SER1   0x0208
+#define MASK_SER0      0x2
+#define MASK_SER1      0x1
+#endif
+
+unsigned long memsize;
+char modetty[30];
+unsigned int titan_irq = TITAN_IRQ;
+static void __iomem * ctl_regs;
+u32 unit_id;
+
+volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD);
+volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN);
+
+/* Protect access to shared GPI registers */
+spinlock_t titan_lock = SPIN_LOCK_UNLOCKED;
+int titan_irqflags;
+
+
+static void excite_timer_init(void)
+{
+       const u32 modebit5 = ocd_readl(0x00e4);
+       unsigned int
+               mult = ((modebit5 >> 11) & 0x1f) + 2,
+               div = ((modebit5 >> 16) & 0x1f) + 2;
+
+       if (div == 33) div = 1;
+       mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2;
+}
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+       /* The eXcite platform uses the alternate timer interrupt */
+       set_c0_intcontrol(0x80);
+       setup_irq(TIMER_IRQ, irq);
+}
+
+static int __init excite_init_console(void)
+{
+#if defined(CONFIG_SERIAL_8250)
+       static __initdata char serr[] =
+               KERN_ERR "Serial port #%u setup failed\n";
+       struct uart_port up;
+
+       /* Take the DUART out of reset */
+       titan_writel(0x00ff1cff, CPRR);
+
+#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1)
+       /* Enable both ports */
+       titan_writel(MASK_SER0 | MASK_SER1, UACFG);
+#else
+       /* Enable port #0 only */
+       titan_writel(MASK_SER0, UACFG);
+#endif /* defined(CONFIG_KGDB) */
+
+       /*
+        * Set up serial port #0. Do not use autodetection; the result is
+        * not what we want.
+        */
+       memset(&up, 0, sizeof(up));
+       up.membase      = (char *) titan_addr(REGBASE_SER0);
+       up.irq          = TITAN_IRQ;
+       up.uartclk      = TITAN_UART_CLK;
+       up.regshift     = 0;
+       up.iotype       = UPIO_MEM32;
+       up.type         = PORT_RM9000;
+       up.flags        = UPF_SHARE_IRQ;
+       up.line         = 0;
+       if (early_serial_setup(&up))
+               printk(serr, up.line);
+
+#if CONFIG_SERIAL_8250_NR_UARTS > 1
+       /* And now for port #1. */
+       up.membase      = (char *) titan_addr(REGBASE_SER1);
+       up.line         = 1;
+       if (early_serial_setup(&up))
+               printk(serr, up.line);
+#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */
+#else
+       /* Leave the DUART in reset */
+       titan_writel(0x00ff3cff, CPRR);
+#endif  /* defined(CONFIG_SERIAL_8250) */
+
+       return 0;
+}
+
+static int __init excite_platform_init(void)
+{
+       unsigned int i;
+       unsigned char buf[3];
+       u8 reg;
+       void __iomem * dpr;
+
+       /* BIU buffer allocations */
+       ocd_writel(8, CPURSLMT);        /* CPU */
+       titan_writel(4, CPGRWL);        /* GPI / Ethernet */
+
+       /* Map control registers located in FPGA */
+       ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16);
+       if (!ctl_regs)
+               panic("eXcite: failed to map platform control registers\n");
+       memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf));
+       unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16);
+
+       /* Clear the reboot flag */
+       dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1);
+       reg = __raw_readb(dpr);
+       __raw_writeb(reg & 0x7f, dpr);
+       iounmap(dpr);
+
+       /* Interrupt controller setup */
+       for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) {
+               ocd_writel(0x00000000, i + 0x04);
+               ocd_writel(0xffffffff, i + 0x0c);
+       }
+       ocd_writel(0x2, NMICONFIG);
+
+       ocd_writel(0x1 << (TITAN_MSGINT % 0x20),
+                  INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20)));
+       ocd_writel((0x1 << (FPGA0_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20)));
+       ocd_writel((0x1 << (FPGA1_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20)));
+       ocd_writel((0x1 << (PHY_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20)));
+#if USB_IRQ < 10
+       ocd_writel((0x1 << (USB_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20)));
+#endif
+       /* Enable the packet FIFO, XDMA and XDMA arbiter */
+       titan_writel(0x00ff18ff, CPRR);
+
+       /*
+        * Set up the PADMUX. Power down all ethernet slices,
+        * they will be powered up and configured at device startup.
+        */
+       titan_writel(0x00878206, CPTC1R);
+       titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */
+
+       /* Reset and enable the FIFO block */
+       titan_writel(0x00000001, SDRXFCIE);
+       titan_writel(0x00000001, SDTXFCIE);
+       titan_writel(0x00000100, SDRXFCIE);
+       titan_writel(0x00000000, SDTXFCIE);
+
+       /*
+        * Initialize the common interrupt shared by all components of
+        * the GPI/Ethernet subsystem.
+        */
+       titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0);
+       titan_writel(TITAN_MSGINT, CPCFG1);
+
+       /*
+        * XDMA configuration.
+        * In order for the XDMA to be sharable among multiple drivers,
+        * the setup must be done here in the platform. The reason is that
+        * this setup can only be done while the XDMA is in reset. If this
+        * were done in a driver, it would interrupt all other drivers
+        * using the XDMA.
+        */
+       titan_writel(0x80021dff, GXCFG);        /* XDMA reset */
+       titan_writel(0x00000000, CPXCISRA);
+       titan_writel(0x00000000, CPXCISRB);     /* clear pending interrupts */
+#if defined (CONFIG_HIGHMEM)
+#      error change for HIGHMEM support!
+#else
+       titan_writel(0x00000000, GXDMADRPFX);   /* buffer address prefix */
+#endif
+       titan_writel(0, GXDMA_DESCADR);
+
+       for (i = 0x5040; i <= 0x5300; i += 0x0040)
+               titan_writel(0x80080000, i);    /* reset channel */
+
+       titan_writel((0x1 << 29)                        /* no sparse tx descr. */
+                    | (0x1 << 28)                      /* no sparse rx descr. */
+                    | (0x1 << 23) | (0x1 << 24)        /* descriptor coherency */
+                    | (0x1 << 21) | (0x1 << 22)        /* data coherency */
+                    | (0x1 << 17)
+                    | 0x1dff,
+                    GXCFG);
+
+#if defined(CONFIG_SMP)
+#      error No SMP support
+#else
+       /* All interrupts go to core #0 only. */
+       titan_writel(0x1f007fff, CPDST0A);
+       titan_writel(0x00000000, CPDST0B);
+       titan_writel(0x0000ff3f, CPDST1A);
+       titan_writel(0x00000000, CPDST1B);
+       titan_writel(0x00ffffff, CPXDSTA);
+       titan_writel(0x00000000, CPXDSTB);
+#endif
+
+       /* Enable DUART interrupts, disable everything else. */
+       titan_writel(0x04000000, CPGIG0ER);
+       titan_writel(0x000000c0, CPGIG1ER);
+
+       excite_procfs_init();
+       return 0;
+}
+
+void __init plat_mem_setup(void)
+{
+       volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000;
+
+       /* Announce RAM to system */
+       add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
+
+       /* Set up timer initialization hooks */
+       board_time_init = excite_timer_init;
+
+       /* Set up the peripheral address map */
+       *(boot_ocd_base + (LKB9 / sizeof (u32))) = 0;
+       *(boot_ocd_base + (LKB10 / sizeof (u32))) = 0;
+       *(boot_ocd_base + (LKB11 / sizeof (u32))) = 0;
+       *(boot_ocd_base + (LKB12 / sizeof (u32))) = 0;
+       wmb();
+       *(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4;
+       wmb();
+
+       ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5);
+       ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5);
+       ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13);
+       ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13);
+
+       /* Local bus slot #0 */
+       ocd_writel(0x00040510, LDP0);
+       ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9);
+       ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9);
+
+       /* Local bus slot #2 */
+       ocd_writel(0x00000330, LDP2);
+       ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11);
+       ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11);
+
+       /* Local bus slot #3 */
+       ocd_writel(0x00123413, LDP3);
+       ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12);
+       ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12);
+}
+
+
+
+console_initcall(excite_init_console);
+arch_initcall(excite_platform_init);
+
+EXPORT_SYMBOL(titan_lock);
+EXPORT_SYMBOL(titan_irqflags);
+EXPORT_SYMBOL(titan_irq);
+EXPORT_SYMBOL(ocd_base);
+EXPORT_SYMBOL(titan_base);
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
new file mode 100644 (file)
index 0000000..375b2ac
--- /dev/null
@@ -0,0 +1,1241 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc1
+# Thu Jul  6 10:04:05 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+CONFIG_MARKEINS=y
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_EMMA2RH=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+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_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=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
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x1e000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_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_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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=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 is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_RTC=m
+CONFIG_GEN_RTC=m
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_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_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+CONFIG_I2C_DEBUG_CORE=y
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_DEBUG_BUS=y
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A 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_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+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_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=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+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 is not set
+# CONFIG_CIFS is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT=""
+CONFIG_NLS_CODEPAGE_437=m
+# 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=m
+CONFIG_NLS_ISO8859_1=m
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
new file mode 100644 (file)
index 0000000..045ebd0
--- /dev/null
@@ -0,0 +1,1245 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc1
+# Thu Jul  6 10:04:09 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+CONFIG_BASLER_EXCITE=y
+# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_COHERENT=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_IRQ_CPU_RM9K=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_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 is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_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_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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC 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=y
+# CONFIG_SERIAL_NONSTANDARD 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 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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=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
+# CONFIG_HW_RANDOM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT 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
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_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_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_SMIVGX is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY 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=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_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_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION 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
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# 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=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
new file mode 100644 (file)
index 0000000..3e4b16b
--- /dev/null
@@ -0,0 +1,864 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc1
+# Thu Jul  6 10:04:21 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+CONFIG_WR_PPMC=y
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_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=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+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 is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+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_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+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_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200n8"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_PLIST=y
diff --git a/arch/mips/emma2rh/common/Makefile b/arch/mips/emma2rh/common/Makefile
new file mode 100644 (file)
index 0000000..859121b
--- /dev/null
@@ -0,0 +1,13 @@
+#
+#  arch/mips/emma2rh/common/Makefile
+#       Makefile for the common code of NEC EMMA2RH based board.
+#
+#  Copyright (C) NEC Electronics Corporation 2005-2006
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+
+obj-$(CONFIG_MARKEINS) += irq.o irq_emma2rh.o prom.o
diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c
new file mode 100644 (file)
index 0000000..3af5769
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *  arch/mips/emma2rh/common/irq.c
+ *      This file is common irq dispatcher.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+
+#include <asm/i8259.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/*
+ * the first level int-handler will jump here if it is a emma2rh irq
+ */
+asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs)
+{
+       u32 intStatus;
+       u32 bitmask;
+       u32 i;
+
+       intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0)
+           & emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
+
+#ifdef EMMA2RH_SW_CASCADE
+       if (intStatus &
+           (1 << ((EMMA2RH_SW_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+               u32 swIntStatus;
+               swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
+                   & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+               for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+                       if (swIntStatus & bitmask) {
+                               do_IRQ(EMMA2RH_SW_IRQ_BASE + i, regs);
+                               return;
+                       }
+               }
+       }
+#endif
+
+       for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+               if (intStatus & bitmask) {
+                       do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+                       return;
+               }
+       }
+
+       intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1)
+           & emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
+
+#ifdef EMMA2RH_GPIO_CASCADE
+       if (intStatus &
+           (1 << ((EMMA2RH_GPIO_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+               u32 gpioIntStatus;
+               gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
+                   & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+               for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+                       if (gpioIntStatus & bitmask) {
+                               do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i, regs);
+                               return;
+                       }
+               }
+       }
+#endif
+
+       for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
+               if (intStatus & bitmask) {
+                       do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+                       return;
+               }
+       }
+
+       intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2)
+           & emma2rh_in32(EMMA2RH_BHIF_INT_EN_2);
+
+       for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
+               if (intStatus & bitmask) {
+                       do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+                       return;
+               }
+       }
+}
diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c
new file mode 100644 (file)
index 0000000..7c93086
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  arch/mips/emma2rh/common/irq_emma2rh.c
+ *      This file defines the irq handler for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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
+ */
+
+/*
+ * EMMA2RH defines 64 IRQs.
+ *
+ * This file exports one function:
+ *     emma2rh_irq_init(u32 irq_base);
+ */
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/* number of total irqs supported by EMMA2RH */
+#define        NUM_EMMA2RH_IRQ         96
+
+static int emma2rh_irq_base = -1;
+
+void ll_emma2rh_irq_enable(int);
+void ll_emma2rh_irq_disable(int);
+
+static void emma2rh_irq_enable(unsigned int irq)
+{
+       ll_emma2rh_irq_enable(irq - emma2rh_irq_base);
+}
+
+static void emma2rh_irq_disable(unsigned int irq)
+{
+       ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
+}
+
+static unsigned int emma2rh_irq_startup(unsigned int irq)
+{
+       emma2rh_irq_enable(irq);
+       return 0;
+}
+
+#define        emma2rh_irq_shutdown    emma2rh_irq_disable
+
+static void emma2rh_irq_ack(unsigned int irq)
+{
+       /* disable interrupt - some handler will re-enable the irq
+        * and if the interrupt is leveled, we will have infinite loop
+        */
+       ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
+}
+
+static void emma2rh_irq_end(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               ll_emma2rh_irq_enable(irq - emma2rh_irq_base);
+}
+
+struct irq_chip emma2rh_irq_controller = {
+       .typename = "emma2rh_irq",
+       .startup = emma2rh_irq_startup,
+       .shutdown = emma2rh_irq_shutdown,
+       .enable = emma2rh_irq_enable,
+       .disable = emma2rh_irq_disable,
+       .ack = emma2rh_irq_ack,
+       .end = emma2rh_irq_end,
+       .set_affinity = NULL    /* no affinity stuff for UP */
+};
+
+void emma2rh_irq_init(u32 irq_base)
+{
+       u32 i;
+
+       for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 1;
+               irq_desc[i].handler = &emma2rh_irq_controller;
+       }
+
+       emma2rh_irq_base = irq_base;
+}
+
+void ll_emma2rh_irq_enable(int emma2rh_irq)
+{
+       u32 reg_value;
+       u32 reg_bitmask;
+       u32 reg_index;
+
+       reg_index = EMMA2RH_BHIF_INT_EN_0
+           + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0)
+           * (emma2rh_irq / 32);
+       reg_value = emma2rh_in32(reg_index);
+       reg_bitmask = 0x1 << (emma2rh_irq % 32);
+       db_assert((reg_value & reg_bitmask) == 0);
+       emma2rh_out32(reg_index, reg_value | reg_bitmask);
+}
+
+void ll_emma2rh_irq_disable(int emma2rh_irq)
+{
+       u32 reg_value;
+       u32 reg_bitmask;
+       u32 reg_index;
+
+       reg_index = EMMA2RH_BHIF_INT_EN_0
+           + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0)
+           * (emma2rh_irq / 32);
+       reg_value = emma2rh_in32(reg_index);
+       reg_bitmask = 0x1 << (emma2rh_irq % 32);
+       db_assert((reg_value & reg_bitmask) != 0);
+       emma2rh_out32(reg_index, reg_value & ~reg_bitmask);
+}
diff --git a/arch/mips/emma2rh/common/prom.c b/arch/mips/emma2rh/common/prom.c
new file mode 100644 (file)
index 0000000..7433bd8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  arch/mips/emma2rh/common/prom.c
+ *      This file is prom file.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/common/prom.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/emma2rh/emma2rh.h>
+#include <asm/debug.h>
+
+const char *get_system_type(void)
+{
+       switch (mips_machtype) {
+       case MACH_NEC_MARKEINS:
+               return "NEC EMMA2RH Mark-eins";
+       default:
+               return "Unknown NEC board";
+       }
+}
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+       int argc = fw_arg0;
+       char **arg = (char **)fw_arg1;
+       int i;
+
+       /* if user passes kernel args, ignore the default one */
+       if (argc > 1)
+               arcs_cmdline[0] = '\0';
+
+       /* arg[0] is "g", the rest is boot parameters */
+       for (i = 1; i < argc; i++) {
+               if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+                   >= sizeof(arcs_cmdline))
+                       break;
+               strcat(arcs_cmdline, arg[i]);
+               strcat(arcs_cmdline, " ");
+       }
+
+       mips_machgroup = MACH_GROUP_NEC_EMMA2RH;
+
+#if defined(CONFIG_MARKEINS)
+       mips_machtype = MACH_NEC_MARKEINS;
+       add_memory_region(0, EMMA2RH_RAM_SIZE, BOOT_MEM_RAM);
+#endif
+
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/emma2rh/markeins/Makefile b/arch/mips/emma2rh/markeins/Makefile
new file mode 100644 (file)
index 0000000..14fc268
--- /dev/null
@@ -0,0 +1,13 @@
+#
+#  arch/mips/emma2rh/markeins/Makefile
+#       Makefile for the common code of NEC EMMA2RH based board.
+#
+#  Copyright (C) NEC Electronics Corporation 2005-2006
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+
+obj-$(CONFIG_MARKEINS) += irq.o irq_markeins.o setup.o led.o platform.o
diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c
new file mode 100644 (file)
index 0000000..2a736be
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  arch/mips/emma2rh/markeins/irq.c
+ *      This file defines the irq handler for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/delay.h>
+
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/*
+ * IRQ mapping
+ *
+ *  0-7: 8 CPU interrupts
+ *     0 -     software interrupt 0
+ *     1 -     software interrupt 1
+ *     2 -     most Vrc5477 interrupts are routed to this pin
+ *     3 -     (optional) some other interrupts routed to this pin for debugg
+ *     4 -     not used
+ *     5 -     not used
+ *     6 -     not used
+ *     7 -     cpu timer (used by default)
+ *
+ */
+
+extern void emma2rh_sw_irq_init(u32 base);
+extern void emma2rh_gpio_irq_init(u32 base);
+extern void emma2rh_irq_init(u32 base);
+extern asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs);
+
+static struct irqaction irq_cascade = {
+          .handler = no_action,
+          .flags = 0,
+          .mask = CPU_MASK_NONE,
+          .name = "cascade",
+          .dev_id = NULL,
+          .next = NULL,
+};
+
+void __init arch_init_irq(void)
+{
+       u32 reg;
+
+       db_run(printk("markeins_irq_setup invoked.\n"));
+
+       /* by default, interrupts are disabled. */
+       emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0);
+       emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0);
+
+       clear_c0_status(0xff00);
+       set_c0_status(0x0400);
+
+#define GPIO_PCI (0xf<<15)
+       /* setup GPIO interrupt for PCI interface */
+       /* direction input */
+       reg = emma2rh_in32(EMMA2RH_GPIO_DIR);
+       emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI);
+       /* disable interrupt */
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+       emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI);
+       /* level triggerd */
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE);
+       emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI);
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A);
+       emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI));
+       /* interrupt clear */
+       emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI);
+
+       /* init all controllers */
+       emma2rh_irq_init(EMMA2RH_IRQ_BASE);
+       emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE);
+       emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE);
+       mips_cpu_irq_init(CPU_IRQ_BASE);
+
+       /* setup cascade interrupts */
+       setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
+       setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade);
+       setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade);
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+        unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(CPU_IRQ_BASE + 7, regs);
+       else if (pending & STATUSF_IP2)
+               emma2rh_irq_dispatch(regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(CPU_IRQ_BASE + 1, regs);
+       else if (pending & STATUSF_IP0)
+               do_IRQ(CPU_IRQ_BASE + 0, regs);
+       else
+               spurious_interrupt(regs);
+}
+
+
diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c
new file mode 100644 (file)
index 0000000..f23ae9f
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  arch/mips/emma2rh/markeins/irq_markeins.c
+ *      This file defines the irq handler for Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+#include <asm/emma2rh/emma2rh.h>
+
+static int emma2rh_sw_irq_base = -1;
+static int emma2rh_gpio_irq_base = -1;
+
+void ll_emma2rh_sw_irq_enable(int reg);
+void ll_emma2rh_sw_irq_disable(int reg);
+void ll_emma2rh_gpio_irq_enable(int reg);
+void ll_emma2rh_gpio_irq_disable(int reg);
+
+static void emma2rh_sw_irq_enable(unsigned int irq)
+{
+       ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
+}
+
+static void emma2rh_sw_irq_disable(unsigned int irq)
+{
+       ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
+}
+
+static unsigned int emma2rh_sw_irq_startup(unsigned int irq)
+{
+       emma2rh_sw_irq_enable(irq);
+       return 0;
+}
+
+#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable
+
+static void emma2rh_sw_irq_ack(unsigned int irq)
+{
+       ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
+}
+
+static void emma2rh_sw_irq_end(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
+}
+
+struct irq_chip emma2rh_sw_irq_controller = {
+       .typename = "emma2rh_sw_irq",
+       .startup = emma2rh_sw_irq_startup,
+       .shutdown = emma2rh_sw_irq_shutdown,
+       .enable = emma2rh_sw_irq_enable,
+       .disable = emma2rh_sw_irq_disable,
+       .ack = emma2rh_sw_irq_ack,
+       .end = emma2rh_sw_irq_end,
+       .set_affinity = NULL,
+};
+
+void emma2rh_sw_irq_init(u32 irq_base)
+{
+       u32 i;
+
+       for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 2;
+               irq_desc[i].handler = &emma2rh_sw_irq_controller;
+       }
+
+       emma2rh_sw_irq_base = irq_base;
+}
+
+void ll_emma2rh_sw_irq_enable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < NUM_EMMA2RH_IRQ_SW);
+
+       reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+       reg |= 1 << irq;
+       emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
+}
+
+void ll_emma2rh_sw_irq_disable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < 32);
+
+       reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+       reg &= ~(1 << irq);
+       emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
+}
+
+static void emma2rh_gpio_irq_enable(unsigned int irq)
+{
+       ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
+}
+
+static void emma2rh_gpio_irq_disable(unsigned int irq)
+{
+       ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base);
+}
+
+static unsigned int emma2rh_gpio_irq_startup(unsigned int irq)
+{
+       emma2rh_gpio_irq_enable(irq);
+       return 0;
+}
+
+#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable
+
+static void emma2rh_gpio_irq_ack(unsigned int irq)
+{
+       irq -= emma2rh_gpio_irq_base;
+       emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
+       ll_emma2rh_gpio_irq_disable(irq);
+}
+
+static void emma2rh_gpio_irq_end(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
+}
+
+struct irq_chip emma2rh_gpio_irq_controller = {
+       .typename = "emma2rh_gpio_irq",
+       .startup = emma2rh_gpio_irq_startup,
+       .shutdown = emma2rh_gpio_irq_shutdown,
+       .enable = emma2rh_gpio_irq_enable,
+       .disable = emma2rh_gpio_irq_disable,
+       .ack = emma2rh_gpio_irq_ack,
+       .end = emma2rh_gpio_irq_end,
+       .set_affinity = NULL,
+};
+
+void emma2rh_gpio_irq_init(u32 irq_base)
+{
+       u32 i;
+
+       for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 2;
+               irq_desc[i].handler = &emma2rh_gpio_irq_controller;
+       }
+
+       emma2rh_gpio_irq_base = irq_base;
+}
+
+void ll_emma2rh_gpio_irq_enable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
+
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+       reg |= 1 << irq;
+       emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
+}
+
+void ll_emma2rh_gpio_irq_disable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
+
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+       reg &= ~(1 << irq);
+       emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
+}
diff --git a/arch/mips/emma2rh/markeins/led.c b/arch/mips/emma2rh/markeins/led.c
new file mode 100644 (file)
index 0000000..b65254c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  arch/mips/emma2rh/markeins/led.c
+ *      This file defines the led display for Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/emma2rh/emma2rh.h>
+
+const unsigned long clear = 0x20202020;
+
+#define LED_BASE 0xb1400038
+
+void markeins_led_clear(void)
+{
+       emma2rh_out32(LED_BASE, clear);
+       emma2rh_out32(LED_BASE + 4, clear);
+}
+
+void markeins_led(const char *str)
+{
+       int i;
+       int len = strlen(str);
+
+       markeins_led_clear();
+       if (len > 8)
+               len = 8;
+
+       if (emma2rh_in32(0xb0000800) & (0x1 << 18))
+               for (i = 0; i < len; i++)
+                       emma2rh_out8(LED_BASE + i, str[i]);
+       else
+               for (i = 0; i < len; i++)
+                       emma2rh_out8(LED_BASE + (i & 4) + (3 - (i & 3)),
+                                    str[i]);
+}
+
+void markeins_led_hex(u32 val)
+{
+       char str[10];
+
+       sprintf(str, "%08x", val);
+       markeins_led(str);
+}
diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c
new file mode 100644 (file)
index 0000000..15cc61d
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ *  arch/mips/emma2rh/markeins/platofrm.c
+ *      This file sets up platform devices for EMMA2RH Mark-eins.
+ *
+ *  Copyright(C) MontaVista Software Inc, 2006
+ *
+ *  Author: dmitry pervushin <dpervushin@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+
+#define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */
+
+static struct resource i2c_emma_resources_0[] = {
+       { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ },
+       { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 },
+};
+
+struct resource i2c_emma_resources_1[] = {
+       { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ },
+       { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 },
+};
+
+struct resource i2c_emma_resources_2[] = {
+       { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ },
+       { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 },
+};
+
+struct platform_device i2c_emma_devices[] = {
+       [0] = {
+               .name = I2C_EMMA2RH,
+               .id = 0,
+               .resource = i2c_emma_resources_0,
+               .num_resources = ARRAY_SIZE(i2c_emma_resources_0),
+       },
+       [1] = {
+               .name = I2C_EMMA2RH,
+               .id = 1,
+               .resource = i2c_emma_resources_1,
+               .num_resources = ARRAY_SIZE(i2c_emma_resources_1),
+       },
+       [2] = {
+               .name = I2C_EMMA2RH,
+               .id = 2,
+               .resource = i2c_emma_resources_2,
+               .num_resources = ARRAY_SIZE(i2c_emma_resources_2),
+       },
+};
+
+#define EMMA2RH_SERIAL_CLOCK 18544000
+#define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
+
+static struct  plat_serial8250_port platform_serial_ports[] = {
+       [0] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR0,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [1] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR1,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [2] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR2,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [3] = {
+        .flags = 0,
+       },
+};
+
+static struct  platform_device serial_emma = {
+       .name = "serial8250",
+       .dev = {
+               .platform_data = &platform_serial_ports,
+       },
+};
+
+static struct platform_device *devices[] = {
+       &i2c_emma_devices[0],
+       &i2c_emma_devices[1],
+       &i2c_emma_devices[2],
+       &serial_emma,
+};
+
+static struct mtd_partition markeins_parts[] = {
+       [0] = {
+               .name = "RootFS",
+               .offset = 0x00000000,
+               .size = 0x00c00000,
+       },
+       [1] = {
+               .name = "boot code area",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00100000,
+       },
+       [2] = {
+               .name = "kernel image",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00300000,
+       },
+       [3] = {
+               .name = "RootFS2",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00c00000,
+       },
+       [4] = {
+               .name = "boot code area2",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00100000,
+       },
+       [5] = {
+               .name = "kernel image2",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static int __init platform_devices_setup(void)
+{
+       physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts));
+       return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+arch_initcall(platform_devices_setup);
+
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
new file mode 100644 (file)
index 0000000..b29a447
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ *  arch/mips/emma2rh/markeins/setup.c
+ *      This file is setup for EMMA2RH Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c.
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/param.h>       /* for HZ */
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define        USE_CPU_COUNTER_TIMER   /* whether we use cpu counter */
+
+extern void markeins_led(const char *);
+
+static int bus_frequency = 0;
+
+static void markeins_machine_restart(char *command)
+{
+       static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
+
+       printk("cannot EMMA2RH Mark-eins restart.\n");
+       markeins_led("restart.");
+       back_to_prom();
+}
+
+static void markeins_machine_halt(void)
+{
+       printk("EMMA2RH Mark-eins halted.\n");
+       markeins_led("halted.");
+       while (1) ;
+}
+
+static void markeins_machine_power_off(void)
+{
+       printk("EMMA2RH Mark-eins halted. Please turn off the power.\n");
+       markeins_led("poweroff.");
+       while (1) ;
+}
+
+static unsigned long clock[4] = { 166500000, 187312500, 199800000, 210600000 };
+
+static unsigned int __init detect_bus_frequency(unsigned long rtc_base)
+{
+       u32 reg;
+
+       /* detect from boot strap */
+       reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0);
+       reg = (reg >> 4) & 0x3;
+       return clock[reg];
+}
+
+static void __init emma2rh_time_init(void)
+{
+       u32 reg;
+       if (bus_frequency == 0)
+               bus_frequency = detect_bus_frequency(0);
+
+       reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0);
+       if ((reg & 0x3) == 0)
+               reg = (reg >> 6) & 0x3;
+       else {
+               reg = emma2rh_in32(EMMA2RH_BHIF_MAIN_CTRL);
+               reg = (reg >> 4) & 0x3;
+       }
+       mips_hpt_frequency = (bus_frequency * (4 + reg)) / 4 / 2;
+}
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+       /* we are using the cpu counter for timer interrupts */
+       setup_irq(CPU_IRQ_BASE + 7, irq);
+}
+
+static void markeins_board_init(void);
+extern void markeins_irq_setup(void);
+
+static void inline __init markeins_sio_setup(void)
+{
+#ifdef CONFIG_KGDB_8250
+       struct uart_port emma_port;
+
+       memset(&emma_port, 0, sizeof(emma_port));
+
+       emma_port.flags =
+           UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+       emma_port.iotype = UPIO_MEM;
+       emma_port.regshift = 4; /* I/O addresses are every 8 bytes */
+       emma_port.uartclk = 18544000;   /* Clock rate of the chip */
+
+       emma_port.line = 0;
+       emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3);
+       emma_port.membase = (u8*)emma_port.mapbase;
+       early_serial_setup(&emma_port);
+
+       emma_port.line = 1;
+       emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3);
+       emma_port.membase = (u8*)emma_port.mapbase;
+       early_serial_setup(&emma_port);
+
+       emma_port.irq = EMMA2RH_IRQ_PFUR1;
+       kgdb8250_add_port(1, &emma_port);
+#endif
+}
+
+void __init plat_mem_setup(void)
+{
+       /* initialize board - we don't trust the loader */
+       markeins_board_init();
+
+       set_io_port_base(KSEG1ADDR(EMMA2RH_PCI_IO_BASE));
+
+       board_time_init = emma2rh_time_init;
+
+       _machine_restart = markeins_machine_restart;
+       _machine_halt = markeins_machine_halt;
+       pm_power_off = markeins_machine_power_off;
+
+       /* setup resource limits */
+       ioport_resource.start = EMMA2RH_PCI_IO_BASE;
+       ioport_resource.end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1;
+       iomem_resource.start = EMMA2RH_IO_BASE;
+       iomem_resource.end = EMMA2RH_ROM_BASE - 1;
+
+       /* Reboot on panic */
+       panic_timeout = 180;
+
+       markeins_sio_setup();
+}
+
+static void __init markeins_board_init(void)
+{
+       u32 val;
+
+       val = emma2rh_in32(EMMA2RH_PBRD_INT_EN);        /* open serial interrupts. */
+       emma2rh_out32(EMMA2RH_PBRD_INT_EN, val | 0xaa);
+       val = emma2rh_in32(EMMA2RH_PBRD_CLKSEL);        /* set serial clocks. */
+       emma2rh_out32(EMMA2RH_PBRD_CLKSEL, val | 0x5);  /* 18MHz */
+       emma2rh_out32(EMMA2RH_PCI_CONTROL, 0);
+
+       markeins_led("MVL E2RH");
+}
diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile
new file mode 100644 (file)
index 0000000..7cf5220
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# 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 2006 Wind River System, Inc.
+# Author: Rongkai.Zhan <rongkai.zhan@windriver.com>
+#
+# Makefile for the Wind River MIPS 4KC PPMC Eval Board
+#
+
+obj-y += irq.o reset.o setup.o time.o pci.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c
new file mode 100644 (file)
index 0000000..8d75a43
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * irq.c: GT64120 Interrupt Controller
+ *
+ * Copyright (C) 2006, Wind River System Inc.
+ * Author: Rongkai.Zhan, <rongkai.zhan@windriver.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/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/irq_cpu.h>
+#include <asm/gt64120.h>
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(WRPPMC_MIPS_TIMER_IRQ, regs);    /* CPU Compare/Count internal timer */
+       else if (pending & STATUSF_IP6)
+               do_IRQ(WRPPMC_UART16550_IRQ, regs);     /* UART 16550 port */
+       else if (pending & STATUSF_IP3)
+               do_IRQ(WRPPMC_PCI_INTA_IRQ, regs);      /* PCI INT_A */
+       else
+               spurious_interrupt(regs);
+}
+
+/**
+ * Initialize GT64120 Interrupt Controller
+ */
+void gt64120_init_pic(void)
+{
+       /* clear CPU Interrupt Cause Registers */
+       GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21));
+       GT_WRITE(GT_HINTRCAUSE_OFS, 0x00);
+
+       /* Disable all interrupts from GT64120 bridge chip */
+       GT_WRITE(GT_INTRMASK_OFS, 0x00);
+       GT_WRITE(GT_HINTRMASK_OFS, 0x00);
+       GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00);
+       GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00);
+}
+
+void __init arch_init_irq(void)
+{
+       /* IRQ 0 - 7 are for MIPS common irq_cpu controller */
+       mips_cpu_irq_init(0);
+
+       gt64120_init_pic();
+}
diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c
new file mode 100644 (file)
index 0000000..2fbe934
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * pci.c: GT64120 PCI support.
+ *
+ * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan <rongkai.zhan@windriver.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/gt64120.h>
+
+extern struct pci_ops gt64120_pci_ops;
+
+static struct resource pci0_io_resource = {
+       .name  = "pci_0 io",
+       .start = GT_PCI_IO_BASE,
+       .end   = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1,
+       .flags = IORESOURCE_IO,
+};
+
+static struct resource pci0_mem_resource = {
+       .name  = "pci_0 memory",
+       .start = GT_PCI_MEM_BASE,
+       .end   = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1,
+       .flags = IORESOURCE_MEM,
+};
+
+static struct pci_controller hose_0 = {
+       .pci_ops        = &gt64120_pci_ops,
+       .io_resource    = &pci0_io_resource,
+       .mem_resource   = &pci0_mem_resource,
+};
+
+static int __init gt64120_pci_init(void)
+{
+       u32 tmp;
+
+       tmp = GT_READ(GT_PCI0_CMD_OFS);         /* Huh??? -- Ralf  */
+       tmp = GT_READ(GT_PCI0_BARE_OFS);
+
+       /* reset the whole PCI I/O space range */
+       ioport_resource.start = GT_PCI_IO_BASE;
+       ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+
+       register_pci_controller(&hose_0);
+       return 0;
+}
+
+arch_initcall(gt64120_pci_init);
diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c
new file mode 100644 (file)
index 0000000..b97039c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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) 1997 Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+void wrppmc_machine_restart(char *command)
+{
+       /*
+        * Ouch, we're still alive ... This time we take the silver bullet ...
+        * ... and find that we leave the hardware in a state in which the
+        * kernel in the flush locks up somewhen during of after the PCI
+        * detection stuff.
+        */
+       local_irq_disable();
+       set_c0_status(ST0_BEV | ST0_ERL);
+       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+       flush_cache_all();
+       write_c0_wired(0);
+       __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void wrppmc_machine_halt(void)
+{
+       local_irq_disable();
+
+       printk(KERN_NOTICE "You can safely turn off the power\n");
+       while (1) {
+               __asm__(
+                       ".set\tmips3\n\t"
+                       "wait\n\t"
+                       ".set\tmips0"
+               );
+       }
+}
+
+void wrppmc_machine_power_off(void)
+{
+       wrppmc_machine_halt();
+}
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
new file mode 100644 (file)
index 0000000..429afc4
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * setup.c: Setup pointers to hardware dependent routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan <rongkai.zhan@windriver.com>
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/gt64120.h>
+
+unsigned long gt64120_base = KSEG1ADDR(0x14000000);
+
+#ifdef WRPPMC_EARLY_DEBUG
+
+static volatile unsigned char * wrppmc_led = \
+       (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE);
+
+/*
+ * PPMC LED control register:
+ * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON)
+ * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON)
+ * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON)
+ */
+void wrppmc_led_on(int mask)
+{
+       unsigned char value = *wrppmc_led;
+
+       value &= (0xF8 | mask);
+       *wrppmc_led = value;
+}
+
+/* If mask = 0, turn off all LEDs */
+void wrppmc_led_off(int mask)
+{
+       unsigned char value = *wrppmc_led;
+
+       value |= (0x7 & mask);
+       *wrppmc_led = value;
+}
+
+/*
+ * We assume that bootloader has initialized UART16550 correctly
+ */
+void __init wrppmc_early_putc(char ch)
+{
+       static volatile unsigned char *wrppmc_uart = \
+               (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE);
+       unsigned char value;
+
+       /* Wait until Transmit-Holding-Register is empty */
+       while (1) {
+               value = *(wrppmc_uart + 5);
+               if (value & 0x20)
+                       break;
+       }
+
+       *wrppmc_uart = ch;
+}
+
+void __init wrppmc_early_printk(const char *fmt, ...)
+{
+       static char pbuf[256] = {'\0', };
+       char *ch = pbuf;
+       va_list args;
+       unsigned int i;
+
+       memset(pbuf, 0, 256);
+       va_start(args, fmt);
+       i = vsprintf(pbuf, fmt, args);
+       va_end(args);
+
+       /* Print the string */
+       while (*ch != '\0') {
+               wrppmc_early_putc(*ch);
+               /* if print '\n', also print '\r' */
+               if (*ch++ == '\n')
+                       wrppmc_early_putc('\r');
+       }
+}
+#endif /* WRPPMC_EARLY_DEBUG */
+
+unsigned long __init prom_free_prom_memory(void)
+{
+       return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250
+static void wrppmc_setup_serial(void)
+{
+       struct uart_port up;
+
+       memset(&up, 0x00, sizeof(struct uart_port));
+
+       /*
+        * A note about mapbase/membase
+        * -) mapbase is the physical address of the IO port.
+        * -) membase is an 'ioremapped' cookie.
+        */
+       up.line = 0;
+       up.type = PORT_16550;
+       up.iotype = UPIO_MEM;
+       up.mapbase = WRPPMC_UART16550_BASE;
+       up.membase = ioremap(up.mapbase, 8);
+       up.irq = WRPPMC_UART16550_IRQ;
+       up.uartclk = WRPPMC_UART16550_CLOCK;
+       up.flags = UPF_SKIP_TEST/* | UPF_BOOT_AUTOCONF */;
+       up.regshift = 0;
+
+       early_serial_setup(&up);
+}
+#endif
+
+void __init plat_mem_setup(void)
+{
+       extern void wrppmc_time_init(void);
+       extern void wrppmc_machine_restart(char *command);
+       extern void wrppmc_machine_halt(void);
+       extern void wrppmc_machine_power_off(void);
+
+       _machine_restart = wrppmc_machine_restart;
+       _machine_halt    = wrppmc_machine_halt;
+       pm_power_off     = wrppmc_machine_power_off;
+
+       /* Use MIPS Count/Compare Timer */
+       board_time_init   = wrppmc_time_init;
+
+       /* This makes the operations of 'in/out[bwl]' to the
+        * physical address ( < KSEG0) can work via KSEG1
+        */
+       set_io_port_base(KSEG1);
+
+#ifdef CONFIG_SERIAL_8250
+       wrppmc_setup_serial();
+#endif
+}
+
+const char *get_system_type(void)
+{
+       return "Wind River PPMC (GT64120)";
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+void __init prom_init(void)
+{
+       mips_machgroup = MACH_GROUP_GALILEO;
+       mips_machtype = MACH_EV64120A;
+
+       add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
+       add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
+
+       wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n",
+                       WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE));
+}
diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c
new file mode 100644 (file)
index 0000000..5b44085
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * time.c: MIPS CPU Count/Compare timer hookup
+ *
+ * Author: Mark.Zhan, <rongkai.zhan@windriver.com>
+ *
+ * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006, Wind River System Inc.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/param.h>       /* for HZ */
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/gt64120.h>
+
+#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+       /* Install ISR for timer interrupt */
+       setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq);
+}
+
+/*
+ * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
+ *
+ * NOTE: We disable all GT64120 timers, and use MIPS processor internal
+ * timer as the source of kernel clock tick.
+ */
+void __init wrppmc_time_init(void)
+{
+       /* Disable GT64120 timers */
+       GT_WRITE(GT_TC_CONTROL_OFS, 0x00);
+       GT_WRITE(GT_TC0_OFS, 0x00);
+       GT_WRITE(GT_TC1_OFS, 0x00);
+       GT_WRITE(GT_TC2_OFS, 0x00);
+       GT_WRITE(GT_TC3_OFS, 0x00);
+
+       /* Use MIPS compare/count internal timer */
+       mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ;
+}
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
new file mode 100644 (file)
index 0000000..528e731
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ * bios-less APM driver for MIPS Linux
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+
+#include <asm/apm.h> /* apm_power_info */
+#include <asm/system.h>
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV  134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ *     apm=on/off                      enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS         16
+
+struct apm_queue {
+       unsigned int            event_head;
+       unsigned int            event_tail;
+       apm_event_t             events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+       struct list_head        list;
+
+       unsigned int            suser: 1;
+       unsigned int            writer: 1;
+       unsigned int            reader: 1;
+
+       int                     suspend_result;
+       unsigned int            suspend_state;
+#define SUSPEND_NONE   0               /* no suspend pending */
+#define SUSPEND_PENDING        1               /* suspend pending read */
+#define SUSPEND_READ   2               /* suspend read, pending ack */
+#define SUSPEND_ACKED  3               /* suspend acked */
+#define SUSPEND_DONE   4               /* suspend completed */
+
+       struct apm_queue        queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int apm_disabled;
+static int mips_apm_active;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DECLARE_COMPLETION(kapmd_exit);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+
+static const char driver_version[] = "1.13";   /* no spaces */
+
+
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+       return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+       q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+       q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+       if (q->event_head == q->event_tail) {
+               static int notified;
+
+               if (notified++ == 0)
+                   printk(KERN_ERR "apm: an event queue overflowed\n");
+               q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       }
+       q->events[q->event_head] = event;
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+       if (as->suser && as->writer) {
+               switch (event) {
+               case APM_SYS_SUSPEND:
+               case APM_USER_SUSPEND:
+                       /*
+                        * If this user already has a suspend pending,
+                        * don't queue another one.
+                        */
+                       if (as->suspend_state != SUSPEND_NONE)
+                               return;
+
+                       as->suspend_state = SUSPEND_PENDING;
+                       suspends_pending++;
+                       break;
+               }
+       }
+       queue_add_event(&as->queue, event);
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+       struct apm_user *as;
+
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               if (as != sender && as->reader)
+                       queue_event_one_user(as, event);
+       }
+       up_read(&user_list_lock);
+       wake_up_interruptible(&apm_waitqueue);
+}
+
+static void apm_suspend(void)
+{
+       struct apm_user *as;
+       int err = pm_suspend(PM_SUSPEND_MEM);
+
+       /*
+        * Anyone on the APM queues will think we're still suspended.
+        * Send a message so everyone knows we're now awake again.
+        */
+       queue_event(APM_NORMAL_RESUME, NULL);
+
+       /*
+        * Finally, wake up anyone who is sleeping on the suspend.
+        */
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               as->suspend_result = err;
+               as->suspend_state = SUSPEND_DONE;
+       }
+       up_read(&user_list_lock);
+
+       wake_up(&apm_suspend_waitqueue);
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
+{
+       struct apm_user *as = fp->private_data;
+       apm_event_t event;
+       int i = count, ret = 0;
+
+       if (count < sizeof(apm_event_t))
+               return -EINVAL;
+
+       if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+               return -EAGAIN;
+
+       wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+       while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+               event = queue_get_event(&as->queue);
+
+               ret = -EFAULT;
+               if (copy_to_user(buf, &event, sizeof(event)))
+                       break;
+
+               if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+                       as->suspend_state = SUSPEND_READ;
+
+               buf += sizeof(event);
+               i -= sizeof(event);
+       }
+
+       if (i < count)
+               ret = count - i;
+
+       return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+       struct apm_user *as = fp->private_data;
+
+       poll_wait(fp, &apm_waitqueue, wait);
+       return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct apm_user *as = filp->private_data;
+       unsigned long flags;
+       int err = -EINVAL;
+
+       if (!as->suser || !as->writer)
+               return -EPERM;
+
+       switch (cmd) {
+       case APM_IOC_SUSPEND:
+               as->suspend_result = -EINTR;
+
+               if (as->suspend_state == SUSPEND_READ) {
+                       /*
+                        * If we read a suspend command from /dev/apm_bios,
+                        * then the corresponding APM_IOC_SUSPEND ioctl is
+                        * interpreted as an acknowledge.
+                        */
+                       as->suspend_state = SUSPEND_ACKED;
+                       suspends_pending--;
+               } else {
+                       /*
+                        * Otherwise it is a request to suspend the system.
+                        * Queue an event for all readers, and expect an
+                        * acknowledge from all writers who haven't already
+                        * acknowledged.
+                        */
+                       queue_event(APM_USER_SUSPEND, as);
+               }
+
+               /*
+                * If there are no further acknowledges required, suspend
+                * the system.
+                */
+               if (suspends_pending == 0)
+                       apm_suspend();
+
+               /*
+                * Wait for the suspend/resume to complete.  If there are
+                * pending acknowledges, we wait here for them.
+                *
+                * Note that we need to ensure that the PM subsystem does
+                * not kick us out of the wait when it suspends the threads.
+                */
+               flags = current->flags;
+               current->flags |= PF_NOFREEZE;
+
+               /*
+                * Note: do not allow a thread which is acking the suspend
+                * to escape until the resume is complete.
+                */
+               if (as->suspend_state == SUSPEND_ACKED)
+                       wait_event(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+               else
+                       wait_event_interruptible(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+
+               current->flags = flags;
+               err = as->suspend_result;
+               as->suspend_state = SUSPEND_NONE;
+               break;
+       }
+
+       return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as = filp->private_data;
+       filp->private_data = NULL;
+
+       down_write(&user_list_lock);
+       list_del(&as->list);
+       up_write(&user_list_lock);
+
+       /*
+        * We are now unhooked from the chain.  As far as new
+        * events are concerned, we no longer exist.  However, we
+        * need to balance suspends_pending, which means the
+        * possibility of sleeping.
+        */
+       if (as->suspend_state != SUSPEND_NONE) {
+               suspends_pending -= 1;
+               if (suspends_pending == 0)
+                       apm_suspend();
+       }
+
+       kfree(as);
+       return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as;
+
+       as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+       if (as) {
+               /*
+                * XXX - this is a tiny bit broken, when we consider BSD
+                * process accounting. If the device is opened by root, we
+                * instantly flag that we used superuser privs. Who knows,
+                * we might close the device immediately without doing a
+                * privileged operation -- cevans
+                */
+               as->suser = capable(CAP_SYS_ADMIN);
+               as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+               as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+               down_write(&user_list_lock);
+               list_add(&as->list, &apm_user_list);
+               up_write(&user_list_lock);
+
+               filp->private_data = as;
+       }
+
+       return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+       .owner          = THIS_MODULE,
+       .read           = apm_read,
+       .poll           = apm_poll,
+       .ioctl          = apm_ioctl,
+       .open           = apm_open,
+       .release        = apm_release,
+};
+
+static struct miscdevice apm_device = {
+       .minor          = APM_MINOR_DEV,
+       .name           = "apm_bios",
+       .fops           = &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *     bit 0: APM_16_BIT_SUPPORT
+ *     bit 1: APM_32_BIT_SUPPORT
+ *     bit 2: APM_IDLE_SLOWS_CLOCK
+ *     bit 3: APM_BIOS_DISABLED
+ *     bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *     0x00: Off-line
+ *     0x01: On-line
+ *     0x02: On backup power (BIOS >= 1.1 only)
+ *     0xff: Unknown
+ *   4) Battery status
+ *     0x00: High
+ *     0x01: Low
+ *     0x02: Critical
+ *     0x03: Charging
+ *     0x04: Selected battery not present (BIOS >= 1.2 only)
+ *     0xff: Unknown
+ *   5) Battery flag
+ *     bit 0: High
+ *     bit 1: Low
+ *     bit 2: Critical
+ *     bit 3: Charging
+ *     bit 7: No system battery
+ *     0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *     0-100: valid
+ *     -1: Unknown
+ *   7) Remaining battery life (time units):
+ *     Number of remaining minutes or seconds
+ *     -1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+       struct apm_power_info info;
+       char *units;
+       int ret;
+
+       info.ac_line_status = 0xff;
+       info.battery_status = 0xff;
+       info.battery_flag   = 0xff;
+       info.battery_life   = -1;
+       info.time           = -1;
+       info.units          = -1;
+
+       if (apm_get_power_status)
+               apm_get_power_status(&info);
+
+       switch (info.units) {
+       default:        units = "?";    break;
+       case 0:         units = "min";  break;
+       case 1:         units = "sec";  break;
+       }
+
+       ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+                    driver_version, APM_32_BIT_SUPPORT,
+                    info.ac_line_status, info.battery_status,
+                    info.battery_flag, info.battery_life,
+                    info.time, units);
+
+       return ret;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+       daemonize("kapmd");
+       current->flags |= PF_NOFREEZE;
+
+       do {
+               apm_event_t event;
+
+               wait_event_interruptible(kapmd_wait,
+                               !queue_empty(&kapmd_queue) || !mips_apm_active);
+
+               if (!mips_apm_active)
+                       break;
+
+               spin_lock_irq(&kapmd_queue_lock);
+               event = 0;
+               if (!queue_empty(&kapmd_queue))
+                       event = queue_get_event(&kapmd_queue);
+               spin_unlock_irq(&kapmd_queue_lock);
+
+               switch (event) {
+               case 0:
+                       break;
+
+               case APM_LOW_BATTERY:
+               case APM_POWER_STATUS_CHANGE:
+                       queue_event(event, NULL);
+                       break;
+
+               case APM_USER_SUSPEND:
+               case APM_SYS_SUSPEND:
+                       queue_event(event, NULL);
+                       if (suspends_pending == 0)
+                               apm_suspend();
+                       break;
+
+               case APM_CRITICAL_SUSPEND:
+                       apm_suspend();
+                       break;
+               }
+       } while (1);
+
+       complete_and_exit(&kapmd_exit, 0);
+}
+
+static int __init apm_init(void)
+{
+       int ret;
+
+       if (apm_disabled) {
+               printk(KERN_NOTICE "apm: disabled on user request.\n");
+               return -ENODEV;
+       }
+
+       mips_apm_active = 1;
+
+       ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+       if (ret < 0) {
+               mips_apm_active = 0;
+               return ret;
+       }
+
+#ifdef CONFIG_PROC_FS
+       create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+       ret = misc_register(&apm_device);
+       if (ret != 0) {
+               remove_proc_entry("apm", NULL);
+
+               mips_apm_active = 0;
+               wake_up(&kapmd_wait);
+               wait_for_completion(&kapmd_exit);
+       }
+
+       return ret;
+}
+
+static void __exit apm_exit(void)
+{
+       misc_deregister(&apm_device);
+       remove_proc_entry("apm", NULL);
+
+       mips_apm_active = 0;
+       wake_up(&kapmd_wait);
+       wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+       while ((str != NULL) && (*str != '\0')) {
+               if (strncmp(str, "off", 3) == 0)
+                       apm_disabled = 1;
+               if (strncmp(str, "on", 2) == 0)
+                       apm_disabled = 0;
+               str = strchr(str, ',');
+               if (str != NULL)
+                       str += strspn(str, ", \t");
+       }
+       return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&kapmd_queue_lock, flags);
+       queue_add_event(&kapmd_queue, event);
+       spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+       wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
new file mode 100644 (file)
index 0000000..beb80f3
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (unsigned int) uu.s.low << -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+               w.s.low = (unsigned int) uu.s.low << b;
+               w.s.high = ((unsigned int) uu.s.high << b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
new file mode 100644 (file)
index 0000000..c884a91
--- /dev/null
@@ -0,0 +1,31 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high =
+                   uu.s.high >> 31;
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h
new file mode 100644 (file)
index 0000000..3f19d1c
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+       int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+       int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union
+{
+       struct DWstruct s;
+       long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
new file mode 100644 (file)
index 0000000..dcf8d68
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (unsigned int) uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = (unsigned int) uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
new file mode 100644 (file)
index 0000000..42b5096
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2006 Chris Dearman (chris@mips.com),
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/bcache.h>
+#include <asm/cacheops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/r4kcache.h>
+
+/*
+ * MIPS32/MIPS64 L2 cache handling
+ */
+
+/*
+ * Writeback and invalidate the secondary cache before DMA.
+ */
+static void mips_sc_wback_inv(unsigned long addr, unsigned long size)
+{
+       blast_scache_range(addr, addr + size);
+}
+
+/*
+ * Invalidate the secondary cache before DMA.
+ */
+static void mips_sc_inv(unsigned long addr, unsigned long size)
+{
+       blast_inv_scache_range(addr, addr + size);
+}
+
+static void mips_sc_enable(void)
+{
+       /* L2 cache is permanently enabled */
+}
+
+static void mips_sc_disable(void)
+{
+       /* L2 cache is permanently enabled */
+}
+
+static struct bcache_ops mips_sc_ops = {
+       .bc_enable = mips_sc_enable,
+       .bc_disable = mips_sc_disable,
+       .bc_wback_inv = mips_sc_wback_inv,
+       .bc_inv = mips_sc_inv
+};
+
+static inline int __init mips_sc_probe(void)
+{
+       struct cpuinfo_mips *c = &current_cpu_data;
+       unsigned int config1, config2;
+       unsigned int tmp;
+
+       /* Mark as not present until probe completed */
+       c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
+
+       /* Ignore anything but MIPSxx processors */
+       if (c->isa_level != MIPS_CPU_ISA_M32R1 &&
+           c->isa_level != MIPS_CPU_ISA_M32R2 &&
+           c->isa_level != MIPS_CPU_ISA_M64R1 &&
+           c->isa_level != MIPS_CPU_ISA_M64R2)
+               return 0;
+
+       /* Does this MIPS32/MIPS64 CPU have a config2 register? */
+       config1 = read_c0_config1();
+       if (!(config1 & MIPS_CONF_M))
+               return 0;
+
+       config2 = read_c0_config2();
+       tmp = (config2 >> 4) & 0x0f;
+       if (0 < tmp && tmp <= 7)
+               c->scache.linesz = 2 << tmp;
+       else
+               return 0;
+
+       tmp = (config2 >> 8) & 0x0f;
+       if (0 <= tmp && tmp <= 7)
+               c->scache.sets = 64 << tmp;
+       else
+               return 0;
+
+       tmp = (config2 >> 0) & 0x0f;
+       if (0 <= tmp && tmp <= 7)
+               c->scache.ways = tmp + 1;
+       else
+               return 0;
+
+       c->scache.waysize = c->scache.sets * c->scache.linesz;
+       c->scache.waybit = __ffs(c->scache.waysize);
+
+       c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+       return 1;
+}
+
+int __init mips_sc_init(void)
+{
+       int found = mips_sc_probe ();
+       if (found) {
+               mips_sc_enable();
+               bcops = &mips_sc_ops;
+       }
+       return found;
+}
+
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
new file mode 100644 (file)
index 0000000..7abcfd1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ *  arch/mips/pci/fixup-emma2rh.c
+ *      This file defines the PCI configration.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define EMMA2RH_PCI_HOST_SLOT 0x09
+#define EMMA2RH_USB_SLOT 0x03
+#define PCI_DEVICE_ID_NEC_EMMA2RH      0x014b /* EMMA2RH PCI Host */
+
+/*
+ * we fix up irqs based on the slot number.
+ * The first entry is at AD:11.
+ * Fortunately this works because, although we have two pci buses,
+ * they all have different slot numbers (except for rockhopper slot 20
+ * which is handled below).
+ *
+ */
+
+#define        MAX_SLOT_NUM 10
+static unsigned char irq_map[][5] __initdata = {
+       [3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC,
+              MARKEINS_PCI_IRQ_INTD, 0,},
+       [4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,},
+       [5] = {0, 0, 0, 0, 0,},
+       [6] = {0, MARKEINS_PCI_IRQ_INTC, MARKEINS_PCI_IRQ_INTD,
+              MARKEINS_PCI_IRQ_INTA, MARKEINS_PCI_IRQ_INTB,},
+};
+
+static void __devinit nec_usb_controller_fixup(struct pci_dev *dev)
+{
+       if (PCI_SLOT(dev->devfn) == EMMA2RH_USB_SLOT)
+               /* on board USB controller configuration */
+               pci_write_config_dword(dev, 0xe4, 1 << 5);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+                       nec_usb_controller_fixup);
+
+/*
+ * Prevent the PCI layer from seeing the resources allocated to this device
+ * if it is the host bridge by marking it as such.  These resources are of
+ * no consequence to the PCI layer (they are handled elsewhere).
+ */
+static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev)
+{
+       int i;
+
+       if (PCI_SLOT(dev->devfn) == EMMA2RH_PCI_HOST_SLOT) {
+               dev->class &= 0xff;
+               dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
+               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                       dev->resource[i].start = 0;
+                       dev->resource[i].end = 0;
+                       dev->resource[i].flags = 0;
+               }
+       }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
+                        emma2rh_pci_host_fixup);
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return irq_map[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
new file mode 100644 (file)
index 0000000..1da696d
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <excite.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (pin == 0)
+               return -1;
+
+       return USB_IRQ;         /* USB controller is the only PCI device */
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
new file mode 100644 (file)
index 0000000..3357c13
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * fixup-wrppmc.c: PPMC board specific PCI fixup
+ *
+ * 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) 2006, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com)
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/gt64120.h>
+
+/* PCI interrupt pins */
+#define PCI_INTA               1
+#define PCI_INTB               2
+#define PCI_INTC               3
+#define PCI_INTD               4
+
+#define PCI_SLOT_MAXNR 32 /* Each PCI bus has 32 physical slots */
+
+static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = {
+       /* 0    INTA   INTB   INTC   INTD */
+       [0] = {0, 0, 0, 0, 0},          /* Slot 0: GT64120 PCI bridge */
+       [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return pci_irq_tab[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c
new file mode 100644 (file)
index 0000000..1fa0992
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * 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) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/pci.h>
+#include <asm/paccess.h>
+#include <asm/pci/bridge.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn0/hub.h>
+
+/*
+ * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
+ * not really documented, so right now I can't write code which uses it.
+ * Therefore we use type 0 accesses for now even though they won't work
+ * correcly for PCI-to-PCI bridges.
+ *
+ * The function is complicated by the ultimate brokeness of the IOC3 chip
+ * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
+ * accesses and does only decode parts of it's address space.
+ */
+
+static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 * value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       volatile void *addr;
+       u32 cf, shift, mask;
+       int res;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+       if (size == 1)
+               res = get_dbe(*value, (u8 *) addr);
+       else if (size == 2)
+               res = get_dbe(*value, (u16 *) addr);
+       else
+               res = get_dbe(*value, (u32 *) addr);
+
+       return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+               *value = 0;
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       *value = (cf >> shift) & mask;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 * value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int busno = bus->number;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       volatile void *addr;
+       u32 cf, shift, mask;
+       int res;
+
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+       if (size == 1)
+               res = get_dbe(*value, (u8 *) addr);
+       else if (size == 2)
+               res = get_dbe(*value, (u16 *) addr);
+       else
+               res = get_dbe(*value, (u32 *) addr);
+
+       return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+               *value = 0;
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       *value = (cf >> shift) & mask;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
+                          int where, int size, u32 * value)
+{
+       if (bus->number > 0)
+               return pci_conf1_read_config(bus, devfn, where, size, value);
+
+       return pci_conf0_read_config(bus, devfn, where, size, value);
+}
+
+static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
+                                 int where, int size, u32 value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       volatile void *addr;
+       u32 cf, shift, mask, smask;
+       int res;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+       if (size == 1) {
+               res = put_dbe(value, (u8 *) addr);
+       } else if (size == 2) {
+               res = put_dbe(value, (u16 *) addr);
+       } else {
+               res = put_dbe(value, (u32 *) addr);
+       }
+
+       if (res)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to touch the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+               return PCIBIOS_SUCCESSFUL;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       smask = mask << shift;
+
+       cf = (cf & ~smask) | ((value & mask) << shift);
+       if (put_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
+                                 int where, int size, u32 value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       int busno = bus->number;
+       volatile void *addr;
+       u32 cf, shift, mask, smask;
+       int res;
+
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+       if (size == 1) {
+               res = put_dbe(value, (u8 *) addr);
+       } else if (size == 2) {
+               res = put_dbe(value, (u16 *) addr);
+       } else {
+               res = put_dbe(value, (u32 *) addr);
+       }
+
+       if (res)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to touch the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+               return PCIBIOS_SUCCESSFUL;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       smask = mask << shift;
+
+       cf = (cf & ~smask) | ((value & mask) << shift);
+       if (put_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 value)
+{
+       if (bus->number > 0)
+               return pci_conf1_write_config(bus, devfn, where, size, value);
+
+       return pci_conf0_write_config(bus, devfn, where, size, value);
+}
+
+struct pci_ops bridge_pci_ops = {
+       .read   = pci_read_config,
+       .write  = pci_write_config,
+};
diff --git a/arch/mips/pci/ops-emma2rh.c b/arch/mips/pci/ops-emma2rh.c
new file mode 100644 (file)
index 0000000..38f1816
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  arch/mips/pci/ops-emma2rh.c
+ *      This file defines the PCI operation for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/pci/ops-vr41xx.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define RTABORT (0x1<<9)
+#define RMABORT (0x1<<10)
+#define EMMA2RH_PCI_SLOT_NUM 9 /* 0000:09.0 is final PCI device */
+
+/*
+ * access config space
+ */
+
+static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num)
+{
+       /* check if the bus is top-level */
+       if (bus->parent != NULL) {
+               *bus_num = bus->number;
+               db_assert(bus_num != 0);
+       } else
+               *bus_num = 0;
+
+       if (*bus_num == 0) {
+               /* Type 0 */
+               if (PCI_SLOT(devfn) >= 10)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       } else {
+               /* Type 1 */
+               if ((*bus_num >= 64) || (PCI_SLOT(devfn) >= 16))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+       return 0;
+}
+
+static inline int set_pci_configuration_address(unsigned char bus_num,
+                                               unsigned int devfn, int where)
+{
+       u32 config_win0;
+
+       emma2rh_out32(EMMA2RH_PCI_INT, ~RMABORT);
+       if (bus_num == 0)
+               /*
+                * Type 0 configuration
+                */
+               config_win0 = (1 << (22 + PCI_SLOT(devfn))) | (5 << 9);
+       else
+               /*
+                * Type 1 configuration
+                */
+               config_win0 = (bus_num << 26) | (PCI_SLOT(devfn) << 22) |
+                   (1 << 15) | (5 << 9);
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, config_win0);
+
+       return 0;
+}
+
+static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
+                          int size, uint32_t * val)
+{
+       u32 bus_num;
+       u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE);
+       u32 backup_win0;
+       u32 data;
+
+       *val = 0xffffffffU;
+
+       if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR);
+
+       if (set_pci_configuration_address(bus_num, devfn, where) < 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       data =
+           *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+                             (where & 0xfffffffc));
+
+       switch (size) {
+       case 1:
+               *val = (data >> ((where & 3) << 3)) & 0xffU;
+               break;
+       case 2:
+               *val = (data >> ((where & 2) << 3)) & 0xffffU;
+               break;
+       case 4:
+               *val = data;
+               break;
+       default:
+               emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+
+       if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
+                           int size, u32 val)
+{
+       u32 bus_num;
+       u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE);
+       u32 backup_win0;
+       u32 data;
+       int shift;
+
+       if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR);
+
+       if (set_pci_configuration_address(bus_num, devfn, where) < 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /* read modify write */
+       data =
+           *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+                             (where & 0xfffffffc));
+
+       switch (size) {
+       case 1:
+               shift = (where & 3) << 3;
+               data &= ~(0xffU << shift);
+               data |= ((val & 0xffU) << shift);
+               break;
+       case 2:
+               shift = (where & 2) << 3;
+               data &= ~(0xffffU << shift);
+               data |= ((val & 0xffffU) << shift);
+               break;
+       case 4:
+               data = val;
+               break;
+       default:
+               emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+       *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+                         (where & 0xfffffffc)) = data;
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+       if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops emma2rh_pci_ops = {
+       .read = pci_config_read,
+       .write = pci_config_write,
+};
diff --git a/arch/mips/pci/pci-emma2rh.c b/arch/mips/pci/pci-emma2rh.c
new file mode 100644 (file)
index 0000000..d99591a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  arch/mips/pci/pci-emma2rh.c
+ *      This file defines the PCI configration.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
+ *
+ *     Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+static struct resource pci_io_resource = {
+       .name = "pci IO space",
+       .start = EMMA2RH_PCI_IO_BASE,
+       .end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1,
+       .flags = IORESOURCE_IO,
+};
+
+static struct resource pci_mem_resource = {
+       .name = "pci memory space",
+       .start = EMMA2RH_PCI_MEM_BASE,
+       .end = EMMA2RH_PCI_MEM_BASE + EMMA2RH_PCI_MEM_SIZE - 1,
+       .flags = IORESOURCE_MEM,
+};
+
+extern struct pci_ops emma2rh_pci_ops;
+
+static struct pci_controller emma2rh_pci_controller = {
+       .pci_ops = &emma2rh_pci_ops,
+       .mem_resource = &pci_mem_resource,
+       .io_resource = &pci_io_resource,
+       .mem_offset = -0x04000000,
+       .io_offset = 0,
+};
+
+static void __init emma2rh_pci_init(void)
+{
+       /* setup PCI interface */
+       emma2rh_out32(EMMA2RH_PCI_ARBIT_CTR, 0x70f);
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x80000a18);
+       emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_COMMAND,
+                     PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_CAP_LIST |
+                     PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+       emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_0, 0x10000000);
+       emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_1, 0x00000000);
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x12000000 | 0x218);
+       emma2rh_out32(EMMA2RH_PCI_IWIN1_CTR, 0x18000000 | 0x600);
+       emma2rh_out32(EMMA2RH_PCI_INIT_ESWP, 0x00000200);
+
+       emma2rh_out32(EMMA2RH_PCI_TWIN_CTR, 0x00009200);
+       emma2rh_out32(EMMA2RH_PCI_TWIN_BADR, 0x00000000);
+       emma2rh_out32(EMMA2RH_PCI_TWIN0_DADR, 0x00000000);
+       emma2rh_out32(EMMA2RH_PCI_TWIN1_DADR, 0x00000000);
+}
+
+static int __init emma2rh_pci_setup(void)
+{
+       emma2rh_pci_init();
+       register_pci_controller(&emma2rh_pci_controller);
+       return 0;
+}
+
+arch_initcall(emma2rh_pci_setup);
diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c
new file mode 100644 (file)
index 0000000..3c86c77
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <asm/rm9k-ocd.h>
+#include <excite.h>
+
+
+extern struct pci_ops titan_pci_ops;
+
+
+static struct resource
+       mem_resource =  {
+               .name   = "PCI memory",
+               .start  = EXCITE_PHYS_PCI_MEM,
+               .end    = EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1,
+               .flags  = IORESOURCE_MEM
+       },
+       io_resource = {
+               .name   = "PCI I/O",
+               .start  = EXCITE_PHYS_PCI_IO,
+               .end    = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1,
+               .flags  = IORESOURCE_IO
+       };
+
+
+static struct pci_controller bx_controller = {
+       .pci_ops        = &titan_pci_ops,
+       .mem_resource   = &mem_resource,
+       .mem_offset     = 0x00000000UL,
+       .io_resource    = &io_resource,
+       .io_offset      = 0x00000000UL
+};
+
+
+static char
+       iopage_failed[] __initdata   = "Cannot allocate PCI I/O page",
+       modebits_no_pci[] __initdata = "PCI is not configured in mode bits";
+
+#define RM9000x2_OCD_HTSC      0x0604
+#define RM9000x2_OCD_HTBHL     0x060c
+#define RM9000x2_OCD_PCIHRST   0x078c
+
+#define RM9K_OCD_MODEBIT1      0x00d4 /* (MODEBIT1) Mode Bit 1 */
+#define RM9K_OCD_CPHDCR                0x00f4 /* CPU-PCI/HT Data Control. */
+
+#define PCISC_FB2B             0x00000200
+#define PCISC_MWICG            0x00000010
+#define PCISC_EMC              0x00000004
+#define PCISC_ERMA             0x00000002
+
+
+
+static int __init basler_excite_pci_setup(void)
+{
+       const unsigned int fullbars = memsize / (256 << 20);
+       unsigned int i;
+
+       /* Check modebits to see if PCI is really enabled. */
+       if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1))
+               panic(modebits_no_pci);
+
+       if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO,
+                                      "Memory-mapped PCI I/O page"))
+               panic(iopage_failed);
+
+       /* Enable PCI 0 as master for config cycles */
+       ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC);
+
+
+       /* Set up latency timer */
+       ocd_writel(0x8008, RM9000x2_OCD_HTBHL);
+
+       /*  Setup host IO and Memory space */
+       ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7);
+       ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7);
+       ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8);
+       ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8);
+
+       /* Set up PCI BARs to map all installed memory */
+       for (i = 0; i < 6; i++) {
+               const unsigned int bar = 0x610 + i * 4;
+
+               if (i < fullbars) {
+                       ocd_writel(0x10000000 * i, bar);
+                       ocd_writel(0x01000000 * i, bar + 0x140);
+                       ocd_writel(0x0ffff029, bar + 0x100);
+                       continue;
+               }
+
+               if (i == fullbars) {
+                       int o;
+                       u32 mask;
+
+                       const unsigned long rem = memsize - i * 0x10000000;
+                       if (!rem) {
+                               ocd_writel(0x00000000, bar + 0x100);
+                               continue;
+                       }
+
+                       o = ffs(rem) - 1;
+                       if (rem & ~(0x1 << o))
+                               o++;
+                       mask = ((0x1 << o) & 0x0ffff000) - 0x1000;
+                       ocd_writel(0x10000000 * i, bar);
+                       ocd_writel(0x01000000 * i, bar + 0x140);
+                       ocd_writel(0x00000029 | mask, bar + 0x100);
+                       continue;
+               }
+
+               ocd_writel(0x00000000, bar + 0x100);
+       }
+
+       /* Finally, enable the PCI interupt */
+#if USB_IRQ > 7
+       set_c0_intcontrol(1 << USB_IRQ);
+#else
+       set_c0_status(1 << (USB_IRQ + 8));
+#endif
+
+       ioport_resource.start = EXCITE_PHYS_PCI_IO;
+       ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1;
+       set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO));
+       register_pci_controller(&bx_controller);
+       return 0;
+}
+
+
+arch_initcall(basler_excite_pci_setup);
diff --git a/arch/mips/qemu/q-reset.c b/arch/mips/qemu/q-reset.c
new file mode 100644 (file)
index 0000000..dbbe44a
--- /dev/null
@@ -0,0 +1,33 @@
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/cacheflush.h>
+#include <asm/qemu.h>
+
+static void qemu_machine_restart(char *command)
+{
+       volatile unsigned int *reg = (unsigned int *)QEMU_RESTART_REG;
+
+       set_c0_status(ST0_BEV | ST0_ERL);
+       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+       flush_cache_all();
+       write_c0_wired(0);
+       *reg = 42;
+       while (1)
+               cpu_wait();
+}
+
+static void qemu_machine_halt(void)
+{
+       volatile unsigned int *reg = (unsigned int *)QEMU_HALT_REG;
+
+       *reg = 42;
+       while (1)
+               cpu_wait();
+}
+
+void qemu_reboot_setup(void)
+{
+       _machine_restart = qemu_machine_restart;
+       _machine_halt = qemu_machine_halt;
+}
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
new file mode 100644 (file)
index 0000000..d1d0f1f
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Big Endian PROM code for SNI RM machines
+ *
+ * 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) 2005-2006 Florian Lohoff (flo@rfc822.org)
+ * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/addrspace.h>
+#include <asm/sni.h>
+#include <asm/mipsprom.h>
+#include <asm/bootinfo.h>
+
+/* special SNI prom calls */
+/*
+ * This does not exist in all proms - SINIX compares
+ * the prom env variable "version" against "2.0008"
+ * or greater. If lesser it tries to probe interesting
+ * registers
+ */
+#define PROM_GET_MEMCONF       58
+
+#define PROM_VEC               (u64 *)CKSEG1ADDR(0x1fc00000)
+#define PROM_ENTRY(x)          (PROM_VEC + (x))
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG_PRINTF(x...)     prom_printf(x)
+#else
+#define DBG_PRINTF(x...)
+#endif
+
+static int *(*__prom_putchar)(int)        = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
+static char *(*__prom_getenv)(char *)     = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
+static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
+
+char *prom_getenv (char *s)
+{
+       return __prom_getenv(s);
+}
+
+void prom_printf(char *fmt, ...)
+{
+       va_list args;
+       char ppbuf[1024];
+       char *bptr;
+
+       va_start(args, fmt);
+       vsprintf(ppbuf, fmt, args);
+
+       bptr = ppbuf;
+
+       while (*bptr != 0) {
+               if (*bptr == '\n')
+                       __prom_putchar('\r');
+
+               __prom_putchar(*bptr++);
+       }
+       va_end(args);
+}
+
+unsigned long prom_free_prom_memory(void)
+{
+       return 0;
+}
+
+/*
+ * /proc/cpuinfo system type
+ *
+ */
+static const char *systype = "Unknown";
+const char *get_system_type(void)
+{
+       return systype;
+}
+
+#define SNI_IDPROM_BASE                0xbff00000
+#define SNI_IDPROM_MEMSIZE             (SNI_IDPROM_BASE+0x28)  /* Memsize in 16MB quantities */
+#define SNI_IDPROM_BRDTYPE             (SNI_IDPROM_BASE+0x29)  /* Board Type */
+#define SNI_IDPROM_CPUTYPE             (SNI_IDPROM_BASE+0x30)  /* CPU Type */
+
+#define SNI_IDPROM_SIZE        0x1000
+
+#ifdef DEBUG
+static void sni_idprom_dump(void)
+{
+       int     i;
+
+       prom_printf("SNI IDProm dump (first 128byte):\n");
+       for(i=0;i<128;i++) {
+               if (i%16 == 0)
+                       prom_printf("%04x ", i);
+
+               prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE+i));
+
+               if (i%16 == 15)
+                       prom_printf("\n");
+       }
+}
+#endif
+
+static void sni_mem_init(void )
+{
+       int i, memsize;
+       struct membank {
+               u32             size;
+               u32             base;
+               u32             size2;
+               u32             pad1;
+               u32             pad2;
+       } memconf[8];
+
+       /* MemSIZE from prom in 16MByte chunks */
+       memsize=*((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
+
+       DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize);
+
+       /* get memory bank layout from prom */
+       __prom_get_memconf(&memconf);
+
+       DBG_PRINTF("prom_get_mem_conf memory configuration:\n");
+       for(i=0;i<8 && memconf[i].size;i++) {
+               prom_printf("Bank%d: %08x @ %08x\n", i,
+                       memconf[i].size, memconf[i].base);
+               add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
+       }
+}
+
+void __init prom_init(void)
+{
+       int argc = fw_arg0;
+       char **argv = (void *)fw_arg1;
+       unsigned int sni_brd_type = *(unsigned char *) SNI_IDPROM_BRDTYPE;
+       int i;
+
+       DBG_PRINTF("Found SNI brdtype %02x\n", sni_brd_type);
+
+#ifdef DEBUG
+       sni_idprom_dump();
+#endif
+       sni_mem_init();
+
+       /* copy prom cmdline parameters to kernel cmdline */
+       for (i = 1; i < argc; i++) {
+               strcat(arcs_cmdline, argv[i]);
+               if (i < (argc - 1))
+                       strcat(arcs_cmdline, " ");
+       }
+}
+
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
new file mode 100644 (file)
index 0000000..d7b985e
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * MPC7448HPC2 (Taiga) board Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * 2006 Roy Zang <Roy Zang at 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.
+ */
+
+
+/ {
+       model = "mpc7448hpc2";
+       compatible = "mpc74xx";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       linux,phandle = <100>;
+
+       cpus {
+               #cpus = <1>;
+               #address-cells = <1>;
+               #size-cells =<0>;
+               linux,phandle = <200>;
+                               
+               PowerPC,7448@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K bytes
+                       i-cache-size = <8000>;          // L1, 32K bytes
+                       timebase-frequency = <0>;       // 33 MHz, from uboot
+                       clock-frequency = <0>;          // From U-Boot
+                       bus-frequency = <0>;            // From U-Boot
+                       32-bit;
+                       linux,phandle = <201>;
+                       linux,boot-cpu;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               linux,phandle = <300>;
+               reg = <00000000 20000000        // DDR2   512M at 0
+                      >;
+       };
+
+       tsi108@c0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "tsi-bridge";
+               ranges = <00000000 c0000000 00010000>;
+               reg = <c0000000 00010000>;
+               bus-frequency = <0>;
+
+               i2c@7000 {
+                       interrupt-parent = <7400>;
+                       interrupts = <E 0>;
+                       reg = <7000 400>;
+                       device_type = "i2c";
+                       compatible  = "tsi-i2c";
+               };
+
+               mdio@6000 {
+                       device_type = "mdio";
+                       compatible = "tsi-ethernet";
+
+                       ethernet-phy@6000 {
+                               linux,phandle = <6000>;
+                               interrupt-parent = <7400>;
+                               interrupts = <2 1>;
+                               reg = <6000 50>;
+                               phy-id = <8>;
+                               device_type = "ethernet-phy";
+                       };
+
+                       ethernet-phy@6400 {
+                               linux,phandle = <6400>;
+                               interrupt-parent = <7400>;
+                               interrupts = <2 1>;
+                               reg = <6000 50>;
+                               phy-id = <9>;
+                               device_type = "ethernet-phy";
+                       };
+
+               };
+
+               ethernet@6200 {
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSI-ETH";
+                       compatible = "tsi-ethernet";
+                       reg = <6000 200>;
+                       address = [ 00 06 D2 00 00 01 ];
+                       interrupts = <10 2>;
+                       interrupt-parent = <7400>;
+                       phy-handle = <6000>;
+               };
+
+               ethernet@6600 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSI-ETH";
+                       compatible = "tsi-ethernet";
+                       reg = <6400 200>;
+                       address = [ 00 06 D2 00 00 02 ];
+                       interrupts = <11 2>;
+                       interrupt-parent = <7400>;
+                       phy-handle = <6400>;
+               };
+
+               serial@7808 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <7808 200>;
+                       clock-frequency = <3f6b5a00>;
+                       interrupts = <c 0>;
+                       interrupt-parent = <7400>;
+               };
+
+               serial@7c08 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <7c08 200>;
+                       clock-frequency = <3f6b5a00>;
+                       interrupts = <d 0>;
+                       interrupt-parent = <7400>;
+               };
+
+               pic@7400 {
+                       linux,phandle = <7400>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <7400 400>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                               big-endian;
+               };
+               pci@1000 {
+                       compatible = "tsi10x";
+                       device_type = "pci";
+                       linux,phandle = <1000>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <1000 1000>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 e0000000 e0000000 0 1A000000       
+                                 01000000 0 00000000 fa000000 0 00010000>;
+                       clock-frequency = <7f28154>;
+                       interrupt-parent = <7400>;
+                       interrupts = <17 2>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x11 */
+                               0800 0 0 1 7400 24 0
+                               0800 0 0 2 7400 25 0
+                               0800 0 0 3 7400 26 0
+                               0800 0 0 4 7400 27 0
+
+                               /* IDSEL 0x12 */
+                               1000 0 0 1 7400 25 0
+                               1000 0 0 2 7400 26 0
+                               1000 0 0 3 7400 27 0
+                               1000 0 0 4 7400 24 0
+
+                               /* IDSEL 0x13 */
+                               1800 0 0 1 7400 26 0
+                               1800 0 0 2 7400 27 0
+                               1800 0 0 3 7400 24 0
+                               1800 0 0 4 7400 25 0
+
+                               /* IDSEL 0x14 */
+                               2000 0 0 1 7400 27 0
+                               2000 0 0 2 7400 24 0
+                               2000 0 0 3 7400 25 0
+                               2000 0 0 4 7400 26 0
+                               >;
+               };
+       };
+
+};
diff --git a/arch/powerpc/boot/dts/mpc8349emds.dts b/arch/powerpc/boot/dts/mpc8349emds.dts
new file mode 100644 (file)
index 0000000..12f5dbf
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * MPC8349E MDS Device Tree Source
+ *
+ * Copyright 2005, 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/ {
+       model = "MPC8349EMDS";
+       compatible = "MPC834xMDS";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #cpus = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8349@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       // from bootloader
+                       bus-frequency = <0>;            // from bootloader
+                       clock-frequency = <0>;          // from bootloader
+                       32-bit;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <00000000 10000000>;      // 256MB at 0
+       };
+
+       soc8349@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 e0000000 00100000>;
+               reg = <e0000000 00000200>;
+               bus-frequency = <0>;
+
+               wdt@200 {
+                       device_type = "watchdog";
+                       compatible = "mpc83xx_wdt";
+                       reg = <200 100>;
+               };
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <e 8>;
+                       interrupt-parent = <700>;
+                       dfsrr;
+               };
+
+               i2c@3100 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3100 100>;
+                       interrupts = <f 8>;
+                       interrupt-parent = <700>;
+                       dfsrr;
+               };
+
+               spi@7000 {
+                       device_type = "spi";
+                       compatible = "mpc83xx_spi";
+                       reg = <7000 1000>;
+                       interrupts = <10 8>;
+                       interrupt-parent = <700>;
+                       mode = <0>;
+               };
+
+               /* phy type (ULPI or SERIAL) are only types supportted for MPH */
+               /* port = 0 or 1 */
+               usb@22000 {
+                       device_type = "usb";
+                       compatible = "fsl-usb2-mph";
+                       reg = <22000 1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupt-parent = <700>;
+                       interrupts = <27 2>;
+                       phy_type = "ulpi";
+                       port1;
+               };
+               /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
+               usb@23000 {
+                       device_type = "usb";
+                       compatible = "fsl-usb2-dr";
+                       reg = <23000 1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupt-parent = <700>;
+                       interrupts = <26 2>;
+                       phy_type = "ulpi";
+               };
+
+               mdio@24520 {
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <700>;
+                               interrupts = <11 2>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <700>;
+                               interrupts = <12 2>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <20 8 21 8 22 8>;
+                       interrupt-parent = <700>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       address = [ 00 00 00 00 00 00 ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <23 8 24 8 25 8>;
+                       interrupt-parent = <700>;
+                       phy-handle = <2452001>;
+               };
+
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;
+                       clock-frequency = <0>;
+                       interrupts = <9 8>;
+                       interrupt-parent = <700>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;
+                       clock-frequency = <0>;
+                       interrupts = <a 8>;
+                       interrupt-parent = <700>;
+               };
+
+               pci@8500 {
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                                       /* IDSEL 0x11 */
+                                        8800 0 0 1 700 14 8
+                                        8800 0 0 2 700 15 8
+                                        8800 0 0 3 700 16 8
+                                        8800 0 0 4 700 17 8
+
+                                       /* IDSEL 0x12 */
+                                        9000 0 0 1 700 16 8
+                                        9000 0 0 2 700 17 8
+                                        9000 0 0 3 700 14 8
+                                        9000 0 0 4 700 15 8
+
+                                       /* IDSEL 0x13 */
+                                        9800 0 0 1 700 17 8
+                                        9800 0 0 2 700 14 8
+                                        9800 0 0 3 700 15 8
+                                        9800 0 0 4 700 16 8
+
+                                       /* IDSEL 0x15 */
+                                        a800 0 0 1 700 14 8
+                                        a800 0 0 2 700 15 8
+                                        a800 0 0 3 700 16 8
+                                        a800 0 0 4 700 17 8
+
+                                       /* IDSEL 0x16 */
+                                        b000 0 0 1 700 17 8
+                                        b000 0 0 2 700 14 8
+                                        b000 0 0 3 700 15 8
+                                        b000 0 0 4 700 16 8
+
+                                       /* IDSEL 0x17 */
+                                        b800 0 0 1 700 16 8
+                                        b800 0 0 2 700 17 8
+                                        b800 0 0 3 700 14 8
+                                        b800 0 0 4 700 15 8
+
+                                       /* IDSEL 0x18 */
+                                        b000 0 0 1 700 15 8
+                                        b000 0 0 2 700 16 8
+                                        b000 0 0 3 700 17 8
+                                        b000 0 0 4 700 14 8>;
+                       interrupt-parent = <700>;
+                       interrupts = <42 8>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 a0000000 a0000000 0 10000000
+                                 42000000 0 80000000 80000000 0 10000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8500 100>;
+                       compatible = "83xx";
+                       device_type = "pci";
+               };
+
+               pci@8600 {
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                                       /* IDSEL 0x11 */
+                                        8800 0 0 1 700 14 8
+                                        8800 0 0 2 700 15 8
+                                        8800 0 0 3 700 16 8
+                                        8800 0 0 4 700 17 8
+
+                                       /* IDSEL 0x12 */
+                                        9000 0 0 1 700 16 8
+                                        9000 0 0 2 700 17 8
+                                        9000 0 0 3 700 14 8
+                                        9000 0 0 4 700 15 8
+
+                                       /* IDSEL 0x13 */
+                                        9800 0 0 1 700 17 8
+                                        9800 0 0 2 700 14 8
+                                        9800 0 0 3 700 15 8
+                                        9800 0 0 4 700 16 8
+
+                                       /* IDSEL 0x15 */
+                                        a800 0 0 1 700 14 8
+                                        a800 0 0 2 700 15 8
+                                        a800 0 0 3 700 16 8
+                                        a800 0 0 4 700 17 8
+
+                                       /* IDSEL 0x16 */
+                                        b000 0 0 1 700 17 8
+                                        b000 0 0 2 700 14 8
+                                        b000 0 0 3 700 15 8
+                                        b000 0 0 4 700 16 8
+
+                                       /* IDSEL 0x17 */
+                                        b800 0 0 1 700 16 8
+                                        b800 0 0 2 700 17 8
+                                        b800 0 0 3 700 14 8
+                                        b800 0 0 4 700 15 8
+
+                                       /* IDSEL 0x18 */
+                                        b000 0 0 1 700 15 8
+                                        b000 0 0 2 700 16 8
+                                        b000 0 0 3 700 17 8
+                                        b000 0 0 4 700 14 8>;
+                       interrupt-parent = <700>;
+                       interrupts = <42 8>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 b0000000 b0000000 0 10000000
+                                 42000000 0 90000000 90000000 0 10000000
+                                 01000000 0 00000000 e2100000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8600 100>;
+                       compatible = "83xx";
+                       device_type = "pci";
+               };
+
+               /* May need to remove if on a part without crypto engine */
+               crypto@30000 {
+                       device_type = "crypto";
+                       model = "SEC2";
+                       compatible = "talitos";
+                       reg = <30000 10000>;
+                       interrupts = <b 8>;
+                       interrupt-parent = <700>;
+                       num-channels = <4>;
+                       channel-fifo-len = <18>;
+                       exec-units-mask = <0000007e>;
+                       /* desc mask is for rev2.0,
+                        * we need runtime fixup for >2.0 */
+                       descriptor-types-mask = <01010ebf>;
+               };
+
+               /* IPIC
+                * interrupts cell = <intr #, sense>
+                * sense values match linux IORESOURCE_IRQ_* defines:
+                * sense == 8: Level, low assertion
+                * sense == 2: Edge, high-to-low change
+                */
+               pic@700 {
+                       linux,phandle = <700>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <700 100>;
+                       built-in;
+                       device_type = "ipic";
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
new file mode 100644 (file)
index 0000000..5f41c1f
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * MPC8540 ADS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+/ {
+       model = "MPC8540ADS";
+       compatible = "MPC85xxADS";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       linux,phandle = <100>;
+
+       cpus {
+               #cpus = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               linux,phandle = <200>;
+
+               PowerPC,8540@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       //  33 MHz, from uboot
+                       bus-frequency = <0>;    // 166 MHz
+                       clock-frequency = <0>;  // 825 MHz, from uboot
+                       32-bit;
+                       linux,phandle = <201>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               linux,phandle = <300>;
+               reg = <00000000 08000000>;      // 128M at 0x0
+       };
+
+       soc8540@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 e0000000 00100000>;
+               reg = <e0000000 00100000>;      // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <1b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 1>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 1>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@3 {
+                               linux,phandle = <2452003>;
+                               interrupt-parent = <40000>;
+                               interrupts = <37 1>;
+                               reg = <3>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       address = [ 00 E0 0C 00 73 00 ];
+                       local-mac-address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <d 2 e 2 12 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       address = [ 00 E0 0C 00 73 01 ];
+                       local-mac-address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <13 2 14 2 18 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+
+               ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "FEC";
+                       compatible = "gianfar";
+                       reg = <26000 1000>;
+                       address = [ 00 E0 0C 00 73 02 ];
+                       local-mac-address = [ 00 E0 0C 00 73 02 ];
+                       interrupts = <19 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452003>;
+               };
+
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+               pci@8000 {
+                       linux,phandle = <8000>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x02 */
+                               1000 0 0 1 40000 31 1
+                               1000 0 0 2 40000 32 1
+                               1000 0 0 3 40000 33 1
+                               1000 0 0 4 40000 34 1
+
+                               /* IDSEL 0x03 */
+                               1800 0 0 1 40000 34 1
+                               1800 0 0 2 40000 31 1
+                               1800 0 0 3 40000 32 1
+                               1800 0 0 4 40000 33 1
+
+                               /* IDSEL 0x04 */
+                               2000 0 0 1 40000 33 1
+                               2000 0 0 2 40000 34 1
+                               2000 0 0 3 40000 31 1
+                               2000 0 0 4 40000 32 1
+
+                               /* IDSEL 0x05 */
+                               2800 0 0 1 40000 32 1
+                               2800 0 0 2 40000 33 1
+                               2800 0 0 3 40000 34 1
+                               2800 0 0 4 40000 31 1
+
+                               /* IDSEL 0x0c */
+                               6000 0 0 1 40000 31 1
+                               6000 0 0 2 40000 32 1
+                               6000 0 0 3 40000 33 1
+                               6000 0 0 4 40000 34 1
+
+                               /* IDSEL 0x0d */
+                               6800 0 0 1 40000 34 1
+                               6800 0 0 2 40000 31 1
+                               6800 0 0 3 40000 32 1
+                               6800 0 0 4 40000 33 1
+
+                               /* IDSEL 0x0e */
+                               7000 0 0 1 40000 33 1
+                               7000 0 0 2 40000 34 1
+                               7000 0 0 3 40000 31 1
+                               7000 0 0 4 40000 32 1
+
+                               /* IDSEL 0x0f */
+                               7800 0 0 1 40000 32 1
+                               7800 0 0 2 40000 33 1
+                               7800 0 0 3 40000 34 1
+                               7800 0 0 4 40000 31 1
+
+                               /* IDSEL 0x12 */
+                               9000 0 0 1 40000 31 1
+                               9000 0 0 2 40000 32 1
+                               9000 0 0 3 40000 33 1
+                               9000 0 0 4 40000 34 1
+
+                               /* IDSEL 0x13 */
+                               9800 0 0 1 40000 34 1
+                               9800 0 0 2 40000 31 1
+                               9800 0 0 3 40000 32 1
+                               9800 0 0 4 40000 33 1
+
+                               /* IDSEL 0x14 */
+                               a000 0 0 1 40000 33 1
+                               a000 0 0 2 40000 34 1
+                               a000 0 0 3 40000 31 1
+                               a000 0 0 4 40000 32 1
+
+                               /* IDSEL 0x15 */
+                               a800 0 0 1 40000 32 1
+                               a800 0 0 2 40000 33 1
+                               a800 0 0 3 40000 34 1
+                               a800 0 0 4 40000 31 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <08 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 80000000 80000000 0 20000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+               };
+
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                       big-endian;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
new file mode 100644 (file)
index 0000000..7be0bc6
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * MPC8541 CDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+/ {
+       model = "MPC8541CDS";
+       compatible = "MPC85xxCDS";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       linux,phandle = <100>;
+
+       cpus {
+               #cpus = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               linux,phandle = <200>;
+
+               PowerPC,8541@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       //  33 MHz, from uboot
+                       bus-frequency = <0>;    // 166 MHz
+                       clock-frequency = <0>;  // 825 MHz, from uboot
+                       32-bit;
+                       linux,phandle = <201>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               linux,phandle = <300>;
+               reg = <00000000 08000000>;      // 128M at 0x0
+       };
+
+       soc8541@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 e0000000 00100000>;
+               reg = <e0000000 00100000>;      // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <1b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <d 2 e 2 12 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <13 2 14 2 18 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               pci@8000 {
+                       linux,phandle = <8000>;
+                       interrupt-map-mask = <1f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x10 */
+                               08000 0 0 1 40000 30 1
+                               08000 0 0 2 40000 31 1
+                               08000 0 0 3 40000 32 1
+                               08000 0 0 4 40000 33 1
+
+                               /* IDSEL 0x11 */
+                               08800 0 0 1 40000 30 1
+                               08800 0 0 2 40000 31 1
+                               08800 0 0 3 40000 32 1
+                               08800 0 0 4 40000 33 1
+
+                               /* IDSEL 0x12 (Slot 1) */
+                               09000 0 0 1 40000 30 1
+                               09000 0 0 2 40000 31 1
+                               09000 0 0 3 40000 32 1
+                               09000 0 0 4 40000 33 1
+
+                               /* IDSEL 0x13 (Slot 2) */
+                               09800 0 0 1 40000 31 1
+                               09800 0 0 2 40000 32 1
+                               09800 0 0 3 40000 33 1
+                               09800 0 0 4 40000 30 1
+
+                               /* IDSEL 0x14 (Slot 3) */
+                               0a000 0 0 1 40000 32 1
+                               0a000 0 0 2 40000 33 1
+                               0a000 0 0 3 40000 30 1
+                               0a000 0 0 4 40000 31 1
+
+                               /* IDSEL 0x15 (Slot 4) */
+                               0a800 0 0 1 40000 33 1
+                               0a800 0 0 2 40000 30 1
+                               0a800 0 0 3 40000 31 1
+                               0a800 0 0 4 40000 32 1
+
+                               /* Bus 1 (Tundra Bridge) */
+                               /* IDSEL 0x12 (ISA bridge) */
+                               19000 0 0 1 40000 30 1
+                               19000 0 0 2 40000 31 1
+                               19000 0 0 3 40000 32 1
+                               19000 0 0 4 40000 33 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <08 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 80000000 80000000 0 20000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+
+                       i8259@19000 {
+                               clock-frequency = <0>;
+                               interrupt-controller;
+                               device_type = "interrupt-controller";
+                               reg = <19000 0 0 0 1>;
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               built-in;
+                               compatible = "chrp,iic";
+                               big-endian;
+                               interrupts = <1>;
+                               interrupt-parent = <8000>;
+                       };
+               };
+
+               pci@9000 {
+                       linux,phandle = <9000>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x15 */
+                               a800 0 0 1 40000 3b 1
+                               a800 0 0 2 40000 3b 1
+                               a800 0 0 3 40000 3b 1
+                               a800 0 0 4 40000 3b 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <09 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 a0000000 a0000000 0 20000000
+                                 01000000 0 00000000 e3000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <9000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+               };
+
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                        big-endian;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
new file mode 100644 (file)
index 0000000..893d795
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * MPC8555 CDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+/ {
+       model = "MPC8548CDS";
+       compatible = "MPC85xxCDS";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       linux,phandle = <100>;
+
+       cpus {
+               #cpus = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               linux,phandle = <200>;
+
+               PowerPC,8548@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       //  33 MHz, from uboot
+                       bus-frequency = <0>;    // 166 MHz
+                       clock-frequency = <0>;  // 825 MHz, from uboot
+                       32-bit;
+                       linux,phandle = <201>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               linux,phandle = <300>;
+               reg = <00000000 08000000>;      // 128M at 0x0
+       };
+
+       soc8548@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 e0000000 00100000>;
+               reg = <e0000000 00100000>;      // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <1b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+
+                       ethernet-phy@2 {
+                               linux,phandle = <2452002>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <2>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@3 {
+                               linux,phandle = <2452003>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <3>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <d 2 e 2 12 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <13 2 14 2 18 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+
+               ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <26000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 02 ];
+                       interrupts = <f 2 10 2 11 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+
+/* eTSEC 4 is currently broken
+               ethernet@27000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <27000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 03 ];
+                       interrupts = <15 2 16 2 17 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+ */
+
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               pci@8000 {
+                       linux,phandle = <8000>;
+                       interrupt-map-mask = <1f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x10 */
+                               08000 0 0 1 40000 30 1
+                               08000 0 0 2 40000 31 1
+                               08000 0 0 3 40000 32 1
+                               08000 0 0 4 40000 33 1
+
+                               /* IDSEL 0x11 */
+                               08800 0 0 1 40000 30 1
+                               08800 0 0 2 40000 31 1
+                               08800 0 0 3 40000 32 1
+                               08800 0 0 4 40000 33 1
+
+                               /* IDSEL 0x12 (Slot 1) */
+                               09000 0 0 1 40000 30 1
+                               09000 0 0 2 40000 31 1
+                               09000 0 0 3 40000 32 1
+                               09000 0 0 4 40000 33 1
+
+                               /* IDSEL 0x13 (Slot 2) */
+                               09800 0 0 1 40000 31 1
+                               09800 0 0 2 40000 32 1
+                               09800 0 0 3 40000 33 1
+                               09800 0 0 4 40000 30 1
+
+                               /* IDSEL 0x14 (Slot 3) */
+                               0a000 0 0 1 40000 32 1
+                               0a000 0 0 2 40000 33 1
+                               0a000 0 0 3 40000 30 1
+                               0a000 0 0 4 40000 31 1
+
+                               /* IDSEL 0x15 (Slot 4) */
+                               0a800 0 0 1 40000 33 1
+                               0a800 0 0 2 40000 30 1
+                               0a800 0 0 3 40000 31 1
+                               0a800 0 0 4 40000 32 1
+
+                               /* Bus 1 (Tundra Bridge) */
+                               /* IDSEL 0x12 (ISA bridge) */
+                               19000 0 0 1 40000 30 1
+                               19000 0 0 2 40000 31 1
+                               19000 0 0 3 40000 32 1
+                               19000 0 0 4 40000 33 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <08 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 80000000 80000000 0 20000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+
+                       i8259@19000 {
+                               clock-frequency = <0>;
+                               interrupt-controller;
+                               device_type = "interrupt-controller";
+                               reg = <19000 0 0 0 1>;
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               built-in;
+                               compatible = "chrp,iic";
+                               big-endian;
+                               interrupts = <1>;
+                               interrupt-parent = <8000>;
+                       };
+               };
+
+               pci@9000 {
+                       linux,phandle = <9000>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x15 */
+                               a800 0 0 1 40000 3b 1
+                               a800 0 0 2 40000 3b 1
+                               a800 0 0 3 40000 3b 1
+                               a800 0 0 4 40000 3b 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <09 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 a0000000 a0000000 0 20000000
+                                 01000000 0 00000000 e3000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <9000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+               };
+
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                        big-endian;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
new file mode 100644 (file)
index 0000000..118f5a8
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * MPC8555 CDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+/ {
+       model = "MPC8555CDS";
+       compatible = "MPC85xxCDS";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       linux,phandle = <100>;
+
+       cpus {
+               #cpus = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               linux,phandle = <200>;
+
+               PowerPC,8555@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       //  33 MHz, from uboot
+                       bus-frequency = <0>;    // 166 MHz
+                       clock-frequency = <0>;  // 825 MHz, from uboot
+                       32-bit;
+                       linux,phandle = <201>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               linux,phandle = <300>;
+               reg = <00000000 08000000>;      // 128M at 0x0
+       };
+
+       soc8555@e0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 e0000000 00100000>;
+               reg = <e0000000 00100000>;      // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <1b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <40000>;
+                               interrupts = <35 0>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <0d 2 0e 2 12 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       local-mac-address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <13 2 14 2 18 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;       // reg base, size
+                       clock-frequency = <0>;  // should we fill in in uboot?
+                       interrupts = <1a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               pci@8000 {
+                       linux,phandle = <8000>;
+                       interrupt-map-mask = <1f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x10 */
+                               08000 0 0 1 40000 30 1
+                               08000 0 0 2 40000 31 1
+                               08000 0 0 3 40000 32 1
+                               08000 0 0 4 40000 33 1
+
+                               /* IDSEL 0x11 */
+                               08800 0 0 1 40000 30 1
+                               08800 0 0 2 40000 31 1
+                               08800 0 0 3 40000 32 1
+                               08800 0 0 4 40000 33 1
+
+                               /* IDSEL 0x12 (Slot 1) */
+                               09000 0 0 1 40000 30 1
+                               09000 0 0 2 40000 31 1
+                               09000 0 0 3 40000 32 1
+                               09000 0 0 4 40000 33 1
+
+                               /* IDSEL 0x13 (Slot 2) */
+                               09800 0 0 1 40000 31 1
+                               09800 0 0 2 40000 32 1
+                               09800 0 0 3 40000 33 1
+                               09800 0 0 4 40000 30 1
+
+                               /* IDSEL 0x14 (Slot 3) */
+                               0a000 0 0 1 40000 32 1
+                               0a000 0 0 2 40000 33 1
+                               0a000 0 0 3 40000 30 1
+                               0a000 0 0 4 40000 31 1
+
+                               /* IDSEL 0x15 (Slot 4) */
+                               0a800 0 0 1 40000 33 1
+                               0a800 0 0 2 40000 30 1
+                               0a800 0 0 3 40000 31 1
+                               0a800 0 0 4 40000 32 1
+
+                               /* Bus 1 (Tundra Bridge) */
+                               /* IDSEL 0x12 (ISA bridge) */
+                               19000 0 0 1 40000 30 1
+                               19000 0 0 2 40000 31 1
+                               19000 0 0 3 40000 32 1
+                               19000 0 0 4 40000 33 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <08 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 80000000 80000000 0 20000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+
+                       i8259@19000 {
+                               clock-frequency = <0>;
+                               interrupt-controller;
+                               device_type = "interrupt-controller";
+                               reg = <19000 0 0 0 1>;
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               built-in;
+                               compatible = "chrp,iic";
+                               big-endian;
+                               interrupts = <1>;
+                               interrupt-parent = <8000>;
+                       };
+               };
+
+               pci@9000 {
+                       linux,phandle = <9000>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+
+                               /* IDSEL 0x15 */
+                               a800 0 0 1 40000 3b 1
+                               a800 0 0 2 40000 3b 1
+                               a800 0 0 3 40000 3b 1
+                               a800 0 0 4 40000 3b 1>;
+                       interrupt-parent = <40000>;
+                       interrupts = <09 2>;
+                       bus-range = <0 0>;
+                       ranges = <02000000 0 a0000000 a0000000 0 20000000
+                                 01000000 0 00000000 e3000000 0 00100000>;
+                       clock-frequency = <3f940aa>;
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <9000 1000>;
+                       compatible = "85xx";
+                       device_type = "pci";
+               };
+
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                        big-endian;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
new file mode 100644 (file)
index 0000000..f0c7731
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+/ {
+       model = "MPC8641HPCN";
+       compatible = "mpc86xx";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #cpus = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8641@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       // 33 MHz, from uboot
+                       bus-frequency = <0>;            // From uboot
+                       clock-frequency = <0>;          // From uboot
+                       32-bit;
+                       linux,boot-cpu;
+               };
+               PowerPC,8641@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       d-cache-line-size = <20>;       // 32 bytes
+                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-size = <8000>;          // L1, 32K
+                       i-cache-size = <8000>;          // L1, 32K
+                       timebase-frequency = <0>;       // 33 MHz, from uboot
+                       bus-frequency = <0>;            // From uboot
+                       clock-frequency = <0>;          // From uboot
+                       32-bit;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <00000000 40000000>;      // 1G at 0x0
+       };
+
+       soc8641@f8000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               ranges = <0 f8000000 00100000>;
+               reg = <f8000000 00100000>;      // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c@3000 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3000 100>;
+                       interrupts = <2b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               i2c@3100 {
+                       device_type = "i2c";
+                       compatible = "fsl-i2c";
+                       reg = <3100 100>;
+                       interrupts = <2b 2>;
+                       interrupt-parent = <40000>;
+                       dfsrr;
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "mdio";
+                       compatible = "gianfar";
+                       reg = <24520 20>;
+                       linux,phandle = <24520>;
+                       ethernet-phy@0 {
+                               linux,phandle = <2452000>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <0>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@1 {
+                               linux,phandle = <2452001>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <1>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@2 {
+                               linux,phandle = <2452002>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <2>;
+                               device_type = "ethernet-phy";
+                       };
+                       ethernet-phy@3 {
+                               linux,phandle = <2452003>;
+                               interrupt-parent = <40000>;
+                               interrupts = <4a 1>;
+                               reg = <3>;
+                               device_type = "ethernet-phy";
+                       };
+               };
+
+               ethernet@24000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <24000 1000>;
+                       mac-address = [ 00 E0 0C 00 73 00 ];
+                       interrupts = <1d 2 1e 2 22 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452000>;
+               };
+
+               ethernet@25000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <25000 1000>;
+                       mac-address = [ 00 E0 0C 00 73 01 ];
+                       interrupts = <23 2 24 2 28 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452001>;
+               };
+               
+               ethernet@26000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <26000 1000>;
+                       mac-address = [ 00 E0 0C 00 02 FD ];
+                       interrupts = <1F 2 20 2 21 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452002>;
+               };
+
+               ethernet@27000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       device_type = "network";
+                       model = "TSEC";
+                       compatible = "gianfar";
+                       reg = <27000 1000>;
+                       mac-address = [ 00 E0 0C 00 03 FD ];
+                       interrupts = <25 2 26 2 27 2>;
+                       interrupt-parent = <40000>;
+                       phy-handle = <2452003>;
+               };
+               serial@4500 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4500 100>;
+                       clock-frequency = <0>;
+                       interrupts = <2a 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               serial@4600 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <4600 100>;
+                       clock-frequency = <0>;
+                       interrupts = <1c 2>;
+                       interrupt-parent = <40000>;
+               };
+
+               pci@8000 {
+                       compatible = "86xx";
+                       device_type = "pci";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = <8000 1000>;
+                       bus-range = <0 fe>;
+                       ranges = <02000000 0 80000000 80000000 0 20000000
+                                 01000000 0 00000000 e2000000 0 00100000>;
+                       clock-frequency = <1fca055>;
+                       interrupt-parent = <40000>;
+                       interrupts = <18 2>;
+                       interrupt-map-mask = <f800 0 0 7>;
+                       interrupt-map = <
+                               /* IDSEL 0x11 */
+                               8800 0 0 1 4d0 3 2
+                               8800 0 0 2 4d0 4 2
+                               8800 0 0 3 4d0 5 2
+                               8800 0 0 4 4d0 6 2
+
+                               /* IDSEL 0x12 */
+                               9000 0 0 1 4d0 4 2
+                               9000 0 0 2 4d0 5 2
+                               9000 0 0 3 4d0 6 2
+                               9000 0 0 4 4d0 3 2
+
+                               /* IDSEL 0x13 */
+                               9800 0 0 1 4d0 0 0
+                               9800 0 0 2 4d0 0 0
+                               9800 0 0 3 4d0 0 0
+                               9800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x14 */
+                               a000 0 0 1 4d0 0 0
+                               a000 0 0 2 4d0 0 0
+                               a000 0 0 3 4d0 0 0
+                               a000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x15 */
+                               a800 0 0 1 4d0 0 0
+                               a800 0 0 2 4d0 0 0
+                               a800 0 0 3 4d0 0 0
+                               a800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x16 */
+                               b000 0 0 1 4d0 0 0
+                               b000 0 0 2 4d0 0 0
+                               b000 0 0 3 4d0 0 0
+                               b000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x17 */
+                               b800 0 0 1 4d0 0 0
+                               b800 0 0 2 4d0 0 0
+                               b800 0 0 3 4d0 0 0
+                               b800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x18 */
+                               c000 0 0 1 4d0 0 0
+                               c000 0 0 2 4d0 0 0
+                               c000 0 0 3 4d0 0 0
+                               c000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x19 */
+                               c800 0 0 1 4d0 0 0
+                               c800 0 0 2 4d0 0 0
+                               c800 0 0 3 4d0 0 0
+                               c800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1a */
+                               d000 0 0 1 4d0 6 2
+                               d000 0 0 2 4d0 3 2
+                               d000 0 0 3 4d0 4 2
+                               d000 0 0 4 4d0 5 2
+
+
+                               /* IDSEL 0x1b */
+                               d800 0 0 1 4d0 5 2
+                               d800 0 0 2 4d0 0 0
+                               d800 0 0 3 4d0 0 0
+                               d800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1c */
+                               e000 0 0 1 4d0 9 2
+                               e000 0 0 2 4d0 a 2
+                               e000 0 0 3 4d0 c 2
+                               e000 0 0 4 4d0 7 2
+
+                               /* IDSEL 0x1d */
+                               e800 0 0 1 4d0 9 2
+                               e800 0 0 2 4d0 a 2
+                               e800 0 0 3 4d0 b 2
+                               e800 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1e */
+                               f000 0 0 1 4d0 c 2
+                               f000 0 0 2 4d0 0 0
+                               f000 0 0 3 4d0 0 0
+                               f000 0 0 4 4d0 0 0
+
+                               /* IDSEL 0x1f */
+                               f800 0 0 1 4d0 6 2
+                               f800 0 0 2 4d0 0 0
+                               f800 0 0 3 4d0 0 0
+                               f800 0 0 4 4d0 0 0
+                               >;
+                       i8259@4d0 {
+                               linux,phandle = <4d0>;
+                               clock-frequency = <0>;
+                               interrupt-controller;
+                               device_type = "interrupt-controller";
+                               #address-cells = <0>;
+                               #interrupt-cells = <2>;
+                               built-in;
+                               compatible = "chrp,iic";
+                               big-endian;
+                               interrupts = <49 2>;
+                               interrupt-parent = <40000>;
+                       };
+
+               };
+               pic@40000 {
+                       linux,phandle = <40000>;
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <40000 40000>;
+                       built-in;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                        big-endian;
+                       interrupts = <
+                               10 2 11 2 12 2 13 2
+                               14 2 15 2 16 2 17 2
+                               18 2 19 2 1a 2 1b 2
+                               1c 2 1d 2 1e 2 1f 2
+                               20 2 21 2 22 2 23 2
+                               24 2 25 2 26 2 27 2
+                               28 2 29 2 2a 2 2b 2
+                               2c 2 2d 2 2e 2 2f 2
+                               30 2 31 2 32 2 33 2
+                               34 2 35 2 36 2 37 2
+                               38 2 39 2 2a 2 3b 2
+                               3c 2 3d 2 3e 2 3f 2
+                               48 1 49 2 4a 1
+                               >;
+                       interrupt-parent = <40000>;
+               };
+       };
+};
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
new file mode 100644 (file)
index 0000000..bbf2b5f
--- /dev/null
@@ -0,0 +1,1397 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Sun Sep 10 10:22:54 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_CHRP=y
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+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_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_KEXEC is not set
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD 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 is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
+# CONFIG_IP_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_XD 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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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=y
+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=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+# CONFIG_TULIP is not set
+CONFIG_DE4X5=y
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=y
+# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_VIA_RHINE_NAPI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_MV643XX_ETH=y
+# CONFIG_MV643XX_ETH_0 is not set
+# CONFIG_MV643XX_ETH_1 is not set
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=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=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=y
+
+#
+# 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_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_RTAS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_HYDRA is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_MPC is not set
+# 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_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_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=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+# CONFIG_FB_MATROX_I2C is not set
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+# CONFIG_FB_ATY_GENERIC_LCD is not set
+CONFIG_FB_ATY_GX=y
+# 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=y
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=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
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+# 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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+# 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
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
new file mode 100644 (file)
index 0000000..719fba4
--- /dev/null
@@ -0,0 +1,963 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Sun Sep 10 10:26:55 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_PPC_ISERIES is not set
+CONFIG_EMBEDDED6xx=y
+# CONFIG_APUS is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE 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_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_PPC_TODC is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_HDPU is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_MPC7448HPC2=y
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_EV64360 is not set
+CONFIG_TSI108_BRIDGE=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+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_GENERIC_ISA_DMA=y
+CONFIG_MPIC_WEIRD=y
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# 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_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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_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_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+CONFIG_SCSI_SATA_MV=y
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIL24 is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_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_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_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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION 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
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO 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
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
new file mode 100644 (file)
index 0000000..8da6a47
--- /dev/null
@@ -0,0 +1,1344 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Sun Sep 10 10:28:05 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_PPC_GEN550=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MPC834x_ITX=y
+CONFIG_MPC834x=y
+# CONFIG_MPIC is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+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_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfe000000
+CONFIG_MTD_PHYSMAP_LEN=0x1000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_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 is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+# CONFIG_BLK_DEV_IDE is not set
+# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# 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
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_MV is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+CONFIG_SCSI_SATA_SIL=y
+# CONFIG_SCSI_SATA_SIL24 is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_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_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_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
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+CONFIG_CICADA_PHY=y
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_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_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MPC83xx=y
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A 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_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+CONFIG_USB_GADGET_NET2280=y
+CONFIG_USB_NET2280=y
+# CONFIG_USB_GADGET_PXA2XX 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_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=y
+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
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=y
+
+#
+# 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=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 is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+CONFIG_SERIAL_TEXT_DEBUG=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
new file mode 100644 (file)
index 0000000..9eefab9
--- /dev/null
@@ -0,0 +1,971 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Sun Sep 10 10:28:54 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_PPC_GEN550=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+CONFIG_MPC834x_SYS=y
+# CONFIG_MPC834x_ITX is not set
+CONFIG_MPC834x=y
+# CONFIG_MPIC is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+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_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# 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_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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_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=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=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_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_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_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A 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_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=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 is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
new file mode 100644 (file)
index 0000000..72edf9f
--- /dev/null
@@ -0,0 +1,895 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Sun Sep 10 10:29:49 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_85xx=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_85xx=y
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=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_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC85xx_CDS=y
+CONFIG_MPC8540=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPIC=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_MATH_EMULATION=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+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_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# 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_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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_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=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER 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
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
new file mode 100644 (file)
index 0000000..92a527f
--- /dev/null
@@ -0,0 +1,963 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc6
+# Sun Sep 10 10:30:15 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=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_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+# CONFIG_SLAB is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_SLOB=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# 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_WANT_EARLY_SERIAL is not set
+CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPIC=y
+
+#
+# Platform Support
+#
+CONFIG_MPC8641_HPCN=y
+CONFIG_MPC8641=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+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_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=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=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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_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_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+CONFIG_VITESSE_PHY=y
+# CONFIG_SMSC_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=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_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_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_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# 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_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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION 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
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS 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_RWSEMS 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_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER 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
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c
new file mode 100644 (file)
index 0000000..7fe5e63
--- /dev/null
@@ -0,0 +1,66 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_PPC64
+       extern int ppc32_classify_syscall(unsigned);
+       if (abi == AUDIT_ARCH_PPC)
+               return ppc32_classify_syscall(syscall);
+#endif
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 0;
+       }
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_PPC64
+       extern __u32 ppc32_dir_class[];
+       extern __u32 ppc32_write_class[];
+       extern __u32 ppc32_read_class[];
+       extern __u32 ppc32_chattr_class[];
+       audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
+       audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
+#endif
+       audit_register_class(AUDIT_CLASS_WRITE, write_class);
+       audit_register_class(AUDIT_CLASS_READ, read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+       return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c
new file mode 100644 (file)
index 0000000..640d4bb
--- /dev/null
@@ -0,0 +1,38 @@
+#undef __powerpc64__
+#include <asm/unistd.h>
+
+unsigned ppc32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned ppc32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned ppc32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned ppc32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int ppc32_classify_syscall(unsigned syscall)
+{
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 1;
+       }
+}
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
new file mode 100644 (file)
index 0000000..f770805
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * This file contains miscellaneous low-level functions.
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
+ * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.h>
+
+       .text
+
+/*
+ * Returns (address we are running at) - (address we were linked at)
+ * for use before the text and data are mapped to KERNELBASE.
+ */
+
+_GLOBAL(reloc_offset)
+       mflr    r0
+       bl      1f
+1:     mflr    r3
+       LOAD_REG_IMMEDIATE(r4,1b)
+       subf    r3,r4,r3
+       mtlr    r0
+       blr
+
+/*
+ * add_reloc_offset(x) returns x + reloc_offset().
+ */
+_GLOBAL(add_reloc_offset)
+       mflr    r0
+       bl      1f
+1:     mflr    r5
+       LOAD_REG_IMMEDIATE(r4,1b)
+       subf    r5,r4,r5
+       add     r3,r3,r5
+       mtlr    r0
+       blr
+
+/*
+ * I/O string operations
+ *
+ * insb(port, buf, len)
+ * outsb(port, buf, len)
+ * insw(port, buf, len)
+ * outsw(port, buf, len)
+ * insl(port, buf, len)
+ * outsl(port, buf, len)
+ * insw_ns(port, buf, len)
+ * outsw_ns(port, buf, len)
+ * insl_ns(port, buf, len)
+ * outsl_ns(port, buf, len)
+ *
+ * The *_ns versions don't do byte-swapping.
+ */
+_GLOBAL(_insb)
+       sync
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,1
+       blelr-
+00:    lbz     r5,0(r3)
+       eieio
+       stbu    r5,1(r4)
+       bdnz    00b
+       twi     0,r5,0
+       isync
+       blr
+
+_GLOBAL(_outsb)
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,1
+       blelr-
+       sync
+00:    lbzu    r5,1(r4)
+       stb     r5,0(r3)
+       bdnz    00b
+       sync
+       blr
+
+_GLOBAL(_insw)
+       sync
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,2
+       blelr-
+00:    lhbrx   r5,0,r3
+       eieio
+       sthu    r5,2(r4)
+       bdnz    00b
+       twi     0,r5,0
+       isync
+       blr
+
+_GLOBAL(_outsw)
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,2
+       blelr-
+       sync
+00:    lhzu    r5,2(r4)
+       sthbrx  r5,0,r3
+       bdnz    00b
+       sync
+       blr
+
+_GLOBAL(_insl)
+       sync
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,4
+       blelr-
+00:    lwbrx   r5,0,r3
+       eieio
+       stwu    r5,4(r4)
+       bdnz    00b
+       twi     0,r5,0
+       isync
+       blr
+
+_GLOBAL(_outsl)
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,4
+       blelr-
+       sync
+00:    lwzu    r5,4(r4)
+       stwbrx  r5,0,r3
+       bdnz    00b
+       sync
+       blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_insw)
+#endif
+_GLOBAL(_insw_ns)
+       sync
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,2
+       blelr-
+00:    lhz     r5,0(r3)
+       eieio
+       sthu    r5,2(r4)
+       bdnz    00b
+       twi     0,r5,0
+       isync
+       blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_outsw)
+#endif
+_GLOBAL(_outsw_ns)
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,2
+       blelr-
+       sync
+00:    lhzu    r5,2(r4)
+       sth     r5,0(r3)
+       bdnz    00b
+       sync
+       blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_insl)
+#endif
+_GLOBAL(_insl_ns)
+       sync
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,4
+       blelr-
+00:    lwz     r5,0(r3)
+       eieio
+       stwu    r5,4(r4)
+       bdnz    00b
+       twi     0,r5,0
+       isync
+       blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_outsl)
+#endif
+_GLOBAL(_outsl_ns)
+       cmpwi   0,r5,0
+       mtctr   r5
+       subi    r4,r4,4
+       blelr-
+       sync
+00:    lwzu    r5,4(r4)
+       stw     r5,0(r3)
+       bdnz    00b
+       sync
+       blr
+
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
new file mode 100644 (file)
index 0000000..8eed872
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc834x_itx.c
+ *
+ * MPC834x ITX board specific routines
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.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.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+#include <platforms/83xx/mpc834x_sys.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc834x_itx_setup_arch(void)
+{
+       struct device_node *np;
+
+       if (ppc_md.progress)
+               ppc_md.progress("mpc834x_itx_setup_arch()", 0);
+
+       np = of_find_node_by_type(NULL, "cpu");
+       if (np != 0) {
+               unsigned int *fp =
+                   (int *)get_property(np, "clock-frequency", NULL);
+               if (fp != 0)
+                       loops_per_jiffy = *fp / HZ;
+               else
+                       loops_per_jiffy = 50000000 / HZ;
+               of_node_put(np);
+       }
+#ifdef CONFIG_PCI
+       for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+               add_bridge(np);
+
+       ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+#ifdef  CONFIG_ROOT_NFS
+       ROOT_DEV = Root_NFS;
+#else
+       ROOT_DEV = Root_HDA1;
+#endif
+}
+
+void __init mpc834x_itx_init_IRQ(void)
+{
+       struct device_node *np;
+
+       np = of_find_node_by_type(NULL, "ipic");
+       if (!np)
+               return;
+
+       ipic_init(np, 0);
+
+       /* Initialize the default interrupt mapping priorities,
+        * in case the boot rom changed something on us.
+        */
+       ipic_set_default_priority();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc834x_itx_probe(void)
+{
+       /* We always match for now, eventually we should look at the flat
+          dev tree to ensure this is the board we are suppose to run on
+       */
+       return 1;
+}
+
+define_machine(mpc834x_itx) {
+       .name                   = "MPC834x ITX",
+       .probe                  = mpc834x_itx_probe,
+       .setup_arch             = mpc834x_itx_setup_arch,
+       .init_IRQ               = mpc834x_itx_init_IRQ,
+       .get_irq                = ipic_get_irq,
+       .restart                = mpc83xx_restart,
+       .time_init              = mpc83xx_time_init,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+#ifdef CONFIG_PCI
+       .pcibios_fixup          = mpc83xx_pcibios_fixup,
+#endif
+};
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.h b/arch/powerpc/platforms/83xx/mpc834x_itx.h
new file mode 100644 (file)
index 0000000..174ca4e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc834x_itx.h
+ *
+ * MPC834X ITX common board definitions
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.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.
+ *
+ */
+
+#ifndef __MACH_MPC83XX_ITX_H__
+#define __MACH_MPC83XX_ITX_H__
+
+#define PIRQA  MPC83xx_IRQ_EXT4
+#define PIRQB  MPC83xx_IRQ_EXT5
+#define PIRQC  MPC83xx_IRQ_EXT6
+#define PIRQD  MPC83xx_IRQ_EXT7
+
+#endif                         /* __MACH_MPC83XX_ITX_H__ */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
new file mode 100644 (file)
index 0000000..76b827c
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * MPC85xx setup and early boot code plus other random bits.
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/i8259.h>
+
+#include <sysdev/fsl_soc.h>
+#include "mpc85xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+static int cds_pci_slot = 2;
+static volatile u8 *cadmus;
+
+
+#ifdef CONFIG_PCI
+
+#define ARCADIA_HOST_BRIDGE_IDSEL      17
+#define ARCADIA_2ND_BRIDGE_IDSEL       3
+
+extern int mpc85xx_pci2_busno;
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+       if (bus == 0 && PCI_SLOT(devfn) == 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       if (mpc85xx_pci2_busno)
+               if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       /* We explicitly do not go past the Tundra 320 Bridge */
+       if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       else
+               return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+mpc85xx_cds_pcibios_fixup(void)
+{
+       struct pci_dev *dev;
+       u_char          c;
+
+       if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+                                       PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+               /*
+                * U-Boot does not set the enable bits
+                * for the IDE device. Force them on here.
+                */
+               pci_read_config_byte(dev, 0x40, &c);
+               c |= 0x03; /* IDE: Chip Enable Bits */
+               pci_write_config_byte(dev, 0x40, c);
+
+               /*
+                * Since only primary interface works, force the
+                * IDE function to standard primary IDE interrupt
+                * w/ 8259 offset
+                */
+               dev->irq = 14;
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+               pci_dev_put(dev);
+       }
+
+       /*
+        * Force legacy USB interrupt routing
+        */
+       if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+                                       PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
+               dev->irq = 10;
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+               pci_dev_put(dev);
+       }
+
+       if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+                                       PCI_DEVICE_ID_VIA_82C586_2, dev))) {
+               dev->irq = 11;
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+               pci_dev_put(dev);
+       }
+
+       /* Now map all the PCI irqs */
+       dev = NULL;
+       for_each_pci_dev(dev)
+               pci_read_irq_line(dev);
+}
+
+#ifdef CONFIG_PPC_I8259
+#warning The i8259 PIC support is currently broken
+static void mpc85xx_8259_cascade(unsigned int irq, struct
+               irq_desc *desc, struct pt_regs *regs)
+{
+       unsigned int cascade_irq = i8259_irq(regs);
+
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq, regs);
+
+       desc->chip->eoi(irq);
+}
+#endif /* PPC_I8259 */
+#endif /* CONFIG_PCI */
+
+void __init mpc85xx_cds_pic_init(void)
+{
+       struct mpic *mpic;
+       struct resource r;
+       struct device_node *np = NULL;
+       struct device_node *cascade_node = NULL;
+       int cascade_irq;
+
+       np = of_find_node_by_type(np, "open-pic");
+
+       if (np == NULL) {
+               printk(KERN_ERR "Could not find open-pic node\n");
+               return;
+       }
+
+       if (of_address_to_resource(np, 0, &r)) {
+               printk(KERN_ERR "Failed to map mpic register space\n");
+               of_node_put(np);
+               return;
+       }
+
+       mpic = mpic_alloc(np, r.start,
+                       MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+                       4, 0, " OpenPIC  ");
+       BUG_ON(mpic == NULL);
+
+       /* Return the mpic node */
+       of_node_put(np);
+
+       mpic_assign_isu(mpic, 0, r.start + 0x10200);
+       mpic_assign_isu(mpic, 1, r.start + 0x10280);
+       mpic_assign_isu(mpic, 2, r.start + 0x10300);
+       mpic_assign_isu(mpic, 3, r.start + 0x10380);
+       mpic_assign_isu(mpic, 4, r.start + 0x10400);
+       mpic_assign_isu(mpic, 5, r.start + 0x10480);
+       mpic_assign_isu(mpic, 6, r.start + 0x10500);
+       mpic_assign_isu(mpic, 7, r.start + 0x10580);
+
+       /* Used only for 8548 so far, but no harm in
+        * allocating them for everyone */
+       mpic_assign_isu(mpic, 8, r.start + 0x10600);
+       mpic_assign_isu(mpic, 9, r.start + 0x10680);
+       mpic_assign_isu(mpic, 10, r.start + 0x10700);
+       mpic_assign_isu(mpic, 11, r.start + 0x10780);
+
+       /* External Interrupts */
+       mpic_assign_isu(mpic, 12, r.start + 0x10000);
+       mpic_assign_isu(mpic, 13, r.start + 0x10080);
+       mpic_assign_isu(mpic, 14, r.start + 0x10100);
+
+       mpic_init(mpic);
+
+#ifdef CONFIG_PPC_I8259
+       /* Initialize the i8259 controller */
+       for_each_node_by_type(np, "interrupt-controller")
+               if (device_is_compatible(np, "chrp,iic")) {
+                       cascade_node = np;
+                       break;
+               }
+
+       if (cascade_node == NULL) {
+               printk(KERN_DEBUG "Could not find i8259 PIC\n");
+               return;
+       }
+
+       cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+       if (cascade_irq == NO_IRQ) {
+               printk(KERN_ERR "Failed to map cascade interrupt\n");
+               return;
+       }
+
+       i8259_init(cascade_node, 0);
+       of_node_put(cascade_node);
+
+       set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade);
+#endif /* CONFIG_PPC_I8259 */
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init
+mpc85xx_cds_setup_arch(void)
+{
+       struct device_node *cpu;
+#ifdef CONFIG_PCI
+       struct device_node *np;
+#endif
+
+       if (ppc_md.progress)
+               ppc_md.progress("mpc85xx_cds_setup_arch()", 0);
+
+       cpu = of_find_node_by_type(NULL, "cpu");
+       if (cpu != 0) {
+               unsigned int *fp;
+
+               fp = (int *)get_property(cpu, "clock-frequency", NULL);
+               if (fp != 0)
+                       loops_per_jiffy = *fp / HZ;
+               else
+                       loops_per_jiffy = 500000000 / HZ;
+               of_node_put(cpu);
+       }
+
+       cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);
+       cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
+
+       if (ppc_md.progress) {
+               char buf[40];
+               snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n",
+                               cadmus[CM_VER], cds_pci_slot);
+               ppc_md.progress(buf, 0);
+       }
+
+#ifdef CONFIG_PCI
+       for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+               add_bridge(np);
+
+       ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+       ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+#endif
+
+#ifdef  CONFIG_ROOT_NFS
+       ROOT_DEV = Root_NFS;
+#else
+       ROOT_DEV = Root_HDA1;
+#endif
+}
+
+
+void
+mpc85xx_cds_show_cpuinfo(struct seq_file *m)
+{
+       uint pvid, svid, phid1;
+       uint memsize = total_memory;
+
+       pvid = mfspr(SPRN_PVR);
+       svid = mfspr(SPRN_SVR);
+
+       seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+       seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]);
+       seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+       seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+       /* Display cpu Pll setting */
+       phid1 = mfspr(SPRN_HID1);
+       seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+       /* Display the amount of memory */
+       seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_cds_probe(void)
+{
+       /* We always match for now, eventually we should look at
+        * the flat dev tree to ensure this is the board we are
+        * supposed to run on
+        */
+       return 1;
+}
+
+define_machine(mpc85xx_cds) {
+       .name           = "MPC85xx CDS",
+       .probe          = mpc85xx_cds_probe,
+       .setup_arch     = mpc85xx_cds_setup_arch,
+       .init_IRQ       = mpc85xx_cds_pic_init,
+       .show_cpuinfo   = mpc85xx_cds_show_cpuinfo,
+       .get_irq        = mpic_get_irq,
+       .restart        = mpc85xx_restart,
+       .calibrate_decr = generic_calibrate_decr,
+       .progress       = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
new file mode 100644 (file)
index 0000000..671f54f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+ *
+ * MPC85xx CDS board definitions
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_CDS_H__
+#define __MACH_MPC85XX_CDS_H__
+
+/* CADMUS info */
+#define CADMUS_BASE (0xf8004000)
+#define CADMUS_SIZE (256)
+#define CM_VER (0)
+#define CM_CSR (1)
+#define CM_RST (2)
+
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR   (0xf8000000)
+#define CDS_RTC_SIZE   (8 * 1024)
+
+/* PCI interrupt controller */
+#define PIRQ0A                 MPC85xx_IRQ_EXT0
+#define PIRQ0B                 MPC85xx_IRQ_EXT1
+#define PIRQ0C                 MPC85xx_IRQ_EXT2
+#define PIRQ0D                 MPC85xx_IRQ_EXT3
+#define PIRQ1A                 MPC85xx_IRQ_EXT11
+
+#define NR_8259_INTS           16
+#define CPM_IRQ_OFFSET         NR_8259_INTS
+
+#define MPC85xx_OPENPIC_IRQ_OFFSET     80
+
+#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
new file mode 100644 (file)
index 0000000..d1ecc0f
--- /dev/null
@@ -0,0 +1,32 @@
+menu "Platform Support"
+       depends on PPC_86xx
+
+choice
+       prompt "Machine Type"
+       default MPC8641_HPCN
+
+config MPC8641_HPCN
+       bool "Freescale MPC8641 HPCN"
+       select PPC_I8259
+       help
+         This option enables support for the MPC8641 HPCN board.
+
+endchoice
+
+
+config MPC8641
+       bool
+       select PPC_INDIRECT_PCI
+       select PPC_UDBG_16550
+       default y if MPC8641_HPCN
+
+config MPIC
+       bool
+       default y
+
+config PPC_INDIRECT_PCI_BE
+       bool
+       depends on PPC_86xx
+       default y
+
+endmenu
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
new file mode 100644 (file)
index 0000000..476a6ee
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the PowerPC 86xx linux kernel.
+#
+
+obj-$(CONFIG_SMP)              += mpc86xx_smp.o
+obj-$(CONFIG_MPC8641_HPCN)     += mpc86xx_hpcn.o
+obj-$(CONFIG_PCI)              += pci.o mpc86xx_pcie.o
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
new file mode 100644 (file)
index 0000000..41e554c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * MPC8641 HPCN board definitions
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Author: Xianghua Xiao <x.xiao@freescale.com>
+ */
+
+#ifndef __MPC8641_HPCN_H__
+#define __MPC8641_HPCN_H__
+
+#include <linux/init.h>
+
+#define MPC86XX_RSTCR_OFFSET   (0xe00b0)       /* Reset Control Register */
+
+#endif /* __MPC8641_HPCN_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
new file mode 100644 (file)
index 0000000..2834462
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MPC86XX_H__
+#define __MPC86XX_H__
+
+/*
+ * Declaration for the various functions exported by the
+ * mpc86xx_* files. Mostly for use by mpc86xx_setup().
+ */
+
+extern int add_bridge(struct device_node *dev);
+
+extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
+
+extern void setup_indirect_pcie(struct pci_controller *hose,
+                                      u32 cfg_addr, u32 cfg_data);
+extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
+                                            void __iomem *cfg_addr,
+                                            void __iomem *cfg_data);
+
+extern void __init mpc86xx_smp_init(void);
+
+#endif /* __MPC86XX_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
new file mode 100644 (file)
index 0000000..5e583cf
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * MPC86xx HPCN board specific routines
+ *
+ * Recode: ZHANG WEI <wei.zhang@freescale.com>
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/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/root_dev.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/i8259.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+#include "mpc8641_hpcn.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(KERN_ERR fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+
+#ifdef CONFIG_PCI
+static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
+                                struct pt_regs *regs)
+{
+       unsigned int cascade_irq = i8259_irq(regs);
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq, regs);
+       desc->chip->eoi(irq);
+}
+#endif /* CONFIG_PCI */
+
+void __init
+mpc86xx_hpcn_init_irq(void)
+{
+       struct mpic *mpic1;
+       struct device_node *np;
+       struct resource res;
+#ifdef CONFIG_PCI
+       struct device_node *cascade_node = NULL;
+       int cascade_irq;
+#endif
+
+       /* Determine PIC address. */
+       np = of_find_node_by_type(NULL, "open-pic");
+       if (np == NULL)
+               return;
+       of_address_to_resource(np, 0, &res);
+
+       /* Alloc mpic structure and per isu has 16 INT entries. */
+       mpic1 = mpic_alloc(np, res.start,
+                       MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+                       16, NR_IRQS - 4,
+                       " MPIC     ");
+       BUG_ON(mpic1 == NULL);
+
+       mpic_assign_isu(mpic1, 0, res.start + 0x10000);
+
+       /* 48 Internal Interrupts */
+       mpic_assign_isu(mpic1, 1, res.start + 0x10200);
+       mpic_assign_isu(mpic1, 2, res.start + 0x10400);
+       mpic_assign_isu(mpic1, 3, res.start + 0x10600);
+
+       /* 16 External interrupts
+        * Moving them from [0 - 15] to [64 - 79]
+        */
+       mpic_assign_isu(mpic1, 4, res.start + 0x10000);
+
+       mpic_init(mpic1);
+
+#ifdef CONFIG_PCI
+       /* Initialize i8259 controller */
+       for_each_node_by_type(np, "interrupt-controller")
+               if (device_is_compatible(np, "chrp,iic")) {
+                       cascade_node = np;
+                       break;
+               }
+       if (cascade_node == NULL) {
+               printk(KERN_DEBUG "mpc86xxhpcn: no ISA interrupt controller\n");
+               return;
+       }
+
+       cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+       if (cascade_irq == NO_IRQ) {
+               printk(KERN_ERR "mpc86xxhpcn: failed to map cascade interrupt");
+               return;
+       }
+       DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
+
+       i8259_init(cascade_node, 0);
+       set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
+#endif
+}
+
+#ifdef CONFIG_PCI
+
+enum pirq{PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH};
+const unsigned char uli1575_irq_route_table[16] = {
+       0,      /* 0: Reserved */
+       0x8,    /* 1: 0b1000 */
+       0,      /* 2: Reserved */
+       0x2,    /* 3: 0b0010 */
+       0x4,    /* 4: 0b0100 */
+       0x5,    /* 5: 0b0101 */
+       0x7,    /* 6: 0b0111 */
+       0x6,    /* 7: 0b0110 */
+       0,      /* 8: Reserved */
+       0x1,    /* 9: 0b0001 */
+       0x3,    /* 10: 0b0011 */
+       0x9,    /* 11: 0b1001 */
+       0xb,    /* 12: 0b1011 */
+       0,      /* 13: Reserved */
+       0xd,    /* 14, 0b1101 */
+       0xf,    /* 15, 0b1111 */
+};
+
+static int __devinit
+get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin)
+{
+       struct of_irq oirq;
+       u32 laddr[3];
+       struct device_node *hosenode = hose ? hose->arch_data : NULL;
+
+       if (!hosenode) return -EINVAL;
+
+       laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8);
+       laddr[1] = laddr[2] = 0;
+       of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
+       DBG("mpc86xx_hpcn: pci irq addr %x, slot %d, pin %d, irq %d\n",
+                       laddr[0], slot, pin, oirq.specifier[0]);
+       return oirq.specifier[0];
+}
+
+static void __devinit quirk_uli1575(struct pci_dev *dev)
+{
+       unsigned short temp;
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       unsigned char irq2pin[16];
+       unsigned long pirq_map_word = 0;
+       u32 irq;
+       int i;
+
+       /*
+        * ULI1575 interrupts route setup
+        */
+       memset(irq2pin, 0, 16); /* Initialize default value 0 */
+
+       /*
+        * PIRQA -> PIRQD mapping read from OF-tree
+        *
+        * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
+        *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
+        */
+       for (i = 0; i < 4; i++){
+               irq = get_pci_irq_from_of(hose, 17, i + 1);
+               if (irq > 0 && irq < 16)
+                       irq2pin[irq] = PIRQA + i;
+               else
+                       printk(KERN_WARNING "ULI1575 device"
+                           "(slot %d, pin %d) irq %d is invalid.\n",
+                           17, i, irq);
+       }
+
+       /*
+        * PIRQE -> PIRQF mapping set manually
+        *
+        * IRQ pin   IRQ#
+        * PIRQE ---- 9
+        * PIRQF ---- 10
+        * PIRQG ---- 11
+        * PIRQH ---- 12
+        */
+       for (i = 0; i < 4; i++) irq2pin[i + 9] = PIRQE + i;
+
+       /* Set IRQ-PIRQ Mapping to ULI1575 */
+       for (i = 0; i < 16; i++)
+               if (irq2pin[i])
+                       pirq_map_word |= (uli1575_irq_route_table[i] & 0xf)
+                               << ((irq2pin[i] - PIRQA) * 4);
+
+       /* ULI1575 IRQ mapping conf register default value is 0xb9317542 */
+       DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n",
+                       pirq_map_word);
+       pci_write_config_dword(dev, 0x48, pirq_map_word);
+
+#define ULI1575_SET_DEV_IRQ(slot, pin, reg)                            \
+       do {                                                            \
+               int irq;                                                \
+               irq = get_pci_irq_from_of(hose, slot, pin);             \
+               if (irq > 0 && irq < 16)                                \
+                       pci_write_config_byte(dev, reg, irq2pin[irq]);  \
+               else                                                    \
+                       printk(KERN_WARNING "ULI1575 device"            \
+                           "(slot %d, pin %d) irq %d is invalid.\n",   \
+                           slot, pin, irq);                            \
+       } while(0)
+
+       /* USB 1.1 OHCI controller 1, slot 28, pin 1 */
+       ULI1575_SET_DEV_IRQ(28, 1, 0x86);
+
+       /* USB 1.1 OHCI controller 2, slot 28, pin 2 */
+       ULI1575_SET_DEV_IRQ(28, 2, 0x87);
+
+       /* USB 1.1 OHCI controller 3, slot 28, pin 3 */
+       ULI1575_SET_DEV_IRQ(28, 3, 0x88);
+
+       /* USB 2.0 controller, slot 28, pin 4 */
+       irq = get_pci_irq_from_of(hose, 28, 4);
+       if (irq >= 0 && irq <=15)
+               pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]);
+
+       /* Audio controller, slot 29, pin 1 */
+       ULI1575_SET_DEV_IRQ(29, 1, 0x8a);
+
+       /* Modem controller, slot 29, pin 2 */
+       ULI1575_SET_DEV_IRQ(29, 2, 0x8b);
+
+       /* HD audio controller, slot 29, pin 3 */
+       ULI1575_SET_DEV_IRQ(29, 3, 0x8c);
+
+       /* SMB interrupt: slot 30, pin 1 */
+       ULI1575_SET_DEV_IRQ(30, 1, 0x8e);
+
+       /* PMU ACPI SCI interrupt: slot 30, pin 2 */
+       ULI1575_SET_DEV_IRQ(30, 2, 0x8f);
+
+       /* Serial ATA interrupt: slot 31, pin 1 */
+       ULI1575_SET_DEV_IRQ(31, 1, 0x8d);
+
+       /* Primary PATA IDE IRQ: 14
+        * Secondary PATA IDE IRQ: 15
+        */
+       pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]);
+       pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]);
+
+       /* Set IRQ14 and IRQ15 to legacy IRQs */
+       pci_read_config_word(dev, 0x46, &temp);
+       temp |= 0xc000;
+       pci_write_config_word(dev, 0x46, temp);
+
+       /* Set i8259 interrupt trigger
+        * IRQ 3:  Level
+        * IRQ 4:  Level
+        * IRQ 5:  Level
+        * IRQ 6:  Level
+        * IRQ 7:  Level
+        * IRQ 9:  Level
+        * IRQ 10: Level
+        * IRQ 11: Level
+        * IRQ 12: Level
+        * IRQ 14: Edge
+        * IRQ 15: Edge
+        */
+       outb(0xfa, 0x4d0);
+       outb(0x1e, 0x4d1);
+
+#undef ULI1575_SET_DEV_IRQ
+}
+
+static void __devinit quirk_uli5288(struct pci_dev *dev)
+{
+       unsigned char c;
+
+       pci_read_config_byte(dev,0x83,&c);
+       c |= 0x80;
+       pci_write_config_byte(dev, 0x83, c);
+
+       pci_write_config_byte(dev, 0x09, 0x01);
+       pci_write_config_byte(dev, 0x0a, 0x06);
+
+       pci_read_config_byte(dev,0x83,&c);
+       c &= 0x7f;
+       pci_write_config_byte(dev, 0x83, c);
+
+       pci_read_config_byte(dev,0x84,&c);
+       c |= 0x01;
+       pci_write_config_byte(dev, 0x84, c);
+}
+
+static void __devinit quirk_uli5229(struct pci_dev *dev)
+{
+       unsigned short temp;
+       pci_write_config_word(dev, 0x04, 0x0405);
+       pci_read_config_word(dev, 0x4a, &temp);
+       temp |= 0x1000;
+       pci_write_config_word(dev, 0x4a, temp);
+}
+
+static void __devinit early_uli5249(struct pci_dev *dev)
+{
+       unsigned char temp;
+       pci_write_config_word(dev, 0x04, 0x0007);
+       pci_read_config_byte(dev, 0x7c, &temp);
+       pci_write_config_byte(dev, 0x7c, 0x80);
+       pci_write_config_byte(dev, 0x09, 0x01);
+       pci_write_config_byte(dev, 0x7c, temp);
+       dev->class |= 0x1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
+#endif /* CONFIG_PCI */
+
+
+static void __init
+mpc86xx_hpcn_setup_arch(void)
+{
+       struct device_node *np;
+
+       if (ppc_md.progress)
+               ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
+
+       np = of_find_node_by_type(NULL, "cpu");
+       if (np != 0) {
+               unsigned int *fp;
+
+               fp = (int *)get_property(np, "clock-frequency", NULL);
+               if (fp != 0)
+                       loops_per_jiffy = *fp / HZ;
+               else
+                       loops_per_jiffy = 50000000 / HZ;
+               of_node_put(np);
+       }
+
+#ifdef CONFIG_PCI
+       for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+               add_bridge(np);
+
+       ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+#endif
+
+       printk("MPC86xx HPCN board from Freescale Semiconductor\n");
+
+#ifdef  CONFIG_ROOT_NFS
+       ROOT_DEV = Root_NFS;
+#else
+       ROOT_DEV = Root_HDA1;
+#endif
+
+#ifdef CONFIG_SMP
+       mpc86xx_smp_init();
+#endif
+}
+
+
+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 = 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));
+}
+
+
+void __init mpc86xx_hpcn_pcibios_fixup(void)
+{
+       struct pci_dev *dev = NULL;
+
+       for_each_pci_dev(dev)
+               pci_read_irq_line(dev);
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc86xx_hpcn_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (of_flat_dt_is_compatible(root, "mpc86xx"))
+               return 1;       /* Looks good */
+
+       return 0;
+}
+
+
+void
+mpc86xx_restart(char *cmd)
+{
+       void __iomem *rstcr;
+
+       rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
+
+       local_irq_disable();
+
+       /* Assert reset request to Reset Control Register */
+       out_be32(rstcr, 0x2);
+
+       /* not reached */
+}
+
+
+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;
+}
+
+
+define_machine(mpc86xx_hpcn) {
+       .name                   = "MPC86xx HPCN",
+       .probe                  = mpc86xx_hpcn_probe,
+       .setup_arch             = mpc86xx_hpcn_setup_arch,
+       .init_IRQ               = mpc86xx_hpcn_init_irq,
+       .show_cpuinfo           = mpc86xx_hpcn_show_cpuinfo,
+       .pcibios_fixup          = mpc86xx_hpcn_pcibios_fixup,
+       .get_irq                = mpic_get_irq,
+       .restart                = mpc86xx_restart,
+       .time_init              = mpc86xx_time_init,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
new file mode 100644 (file)
index 0000000..a2f4f73
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * "Temporary" MPC8548 Errata file -
+ * The standard indirect_pci code should work with future silicon versions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "mpc86xx.h"
+
+#define PCI_CFG_OUT out_be32
+
+/* ERRATA PCI-Ex 14 PCIE Controller timeout */
+#define PCIE_FIX               out_be32(hose->cfg_addr+0x4, 0x0400ffff)
+
+
+static int
+indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+                    int len, u32 *val)
+{
+       struct pci_controller *hose = bus->sysdata;
+       volatile void __iomem *cfg_data;
+       u32 temp;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(bus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /* Possible artifact of CDCpp50937 needs further investigation */
+       if (devfn != 0x0 && bus->number == 0xff)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       PCIE_FIX;
+       if (bus->number == 0xff) {
+               PCI_CFG_OUT(hose->cfg_addr,
+                           (0x80000000 | ((offset & 0xf00) << 16) |
+                            ((bus->number - hose->bus_offset) << 16)
+                            | (devfn << 8) | ((offset & 0xfc) )));
+       } else {
+               PCI_CFG_OUT(hose->cfg_addr,
+                           (0x80000001 | ((offset & 0xf00) << 16) |
+                            ((bus->number - hose->bus_offset) << 16)
+                            | (devfn << 8) | ((offset & 0xfc) )));
+       }
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+       /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+       cfg_data = hose->cfg_data;
+       PCIE_FIX;
+       temp = in_le32(cfg_data);
+       switch (len) {
+       case 1:
+               *val = (temp >> (((offset & 3))*8)) & 0xff;
+               break;
+       case 2:
+               *val = (temp >> (((offset & 3))*8)) & 0xffff;
+               break;
+       default:
+               *val = temp;
+               break;
+       }
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+                     int len, u32 val)
+{
+       struct pci_controller *hose = bus->sysdata;
+       volatile void __iomem *cfg_data;
+       u32 temp;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(bus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /* Possible artifact of CDCpp50937 needs further investigation */
+       if (devfn != 0x0 && bus->number == 0xff)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       PCIE_FIX;
+       if (bus->number == 0xff) {
+               PCI_CFG_OUT(hose->cfg_addr,
+                           (0x80000000 | ((offset & 0xf00) << 16) |
+                            ((bus->number - hose->bus_offset) << 16)
+                            | (devfn << 8) | ((offset & 0xfc) )));
+       } else {
+               PCI_CFG_OUT(hose->cfg_addr,
+                           (0x80000001 | ((offset & 0xf00) << 16) |
+                            ((bus->number - hose->bus_offset) << 16)
+                            | (devfn << 8) | ((offset & 0xfc) )));
+        }
+
+       /*
+        * Note: the caller has already checked that offset is
+        * suitably aligned and that len is 1, 2 or 4.
+        */
+       /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+       cfg_data = hose->cfg_data;
+       switch (len) {
+       case 1:
+               PCIE_FIX;
+               temp = in_le32(cfg_data);
+               temp = (temp & ~(0xff << ((offset & 3) * 8))) |
+                       (val << ((offset & 3) * 8));
+               PCIE_FIX;
+               out_le32(cfg_data, temp);
+               break;
+       case 2:
+               PCIE_FIX;
+               temp = in_le32(cfg_data);
+               temp = (temp & ~(0xffff << ((offset & 3) * 8)));
+               temp |= (val << ((offset & 3) * 8)) ;
+               PCIE_FIX;
+               out_le32(cfg_data, temp);
+               break;
+       default:
+               PCIE_FIX;
+               out_le32(cfg_data, val);
+               break;
+       }
+       PCIE_FIX;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pcie_ops = {
+       indirect_read_config_pcie,
+       indirect_write_config_pcie
+};
+
+void __init
+setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+       void __iomem * cfg_data)
+{
+       hose->cfg_addr = cfg_addr;
+       hose->cfg_data = cfg_data;
+       hose->ops = &indirect_pcie_ops;
+}
+
+void __init
+setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+       unsigned long base = cfg_addr & PAGE_MASK;
+       void __iomem *mbase, *addr, *data;
+
+       mbase = ioremap(base, PAGE_SIZE);
+       addr = mbase + (cfg_addr & ~PAGE_MASK);
+       if ((cfg_data & PAGE_MASK) != base)
+               mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+       data = mbase + (cfg_data & ~PAGE_MASK);
+       setup_indirect_pcie_nomap(hose, addr, data);
+}
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
new file mode 100644 (file)
index 0000000..bb7fb41
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Author: Xianghua Xiao <x.xiao@freescale.com>
+ *         Zhang Wei <wei.zhang@freescale.com>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/pci-bridge.h>
+#include <asm-powerpc/mpic.h>
+#include <asm/mpc86xx.h>
+#include <asm/cacheflush.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+extern void __secondary_start_mpc86xx(void);
+extern unsigned long __secondary_hold_acknowledge;
+
+
+static void __init
+smp_86xx_release_core(int nr)
+{
+       __be32 __iomem *mcm_vaddr;
+       unsigned long pcr;
+
+       if (nr < 0 || nr >= NR_CPUS)
+               return;
+
+       /*
+        * Startup Core #nr.
+        */
+       mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,
+                           MPC86xx_MCM_SIZE);
+       pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
+       pcr |= 1 << (nr + 24);
+       out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
+}
+
+
+static void __init
+smp_86xx_kick_cpu(int nr)
+{
+       unsigned int save_vector;
+       unsigned long target, flags;
+       int n = 0;
+       volatile unsigned int *vector
+                = (volatile unsigned int *)(KERNELBASE + 0x100);
+
+       if (nr < 0 || nr >= NR_CPUS)
+               return;
+
+       pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);
+
+       local_irq_save(flags);
+       local_irq_disable();
+
+       /* Save reset vector */
+       save_vector = *vector;
+
+       /* Setup fake reset vector to call __secondary_start_mpc86xx. */
+       target = (unsigned long) __secondary_start_mpc86xx;
+       create_branch((unsigned long)vector, target, BRANCH_SET_LINK);
+
+       /* Kick that CPU */
+       smp_86xx_release_core(nr);
+
+       /* Wait a bit for the CPU to take the exception. */
+       while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000))
+               mdelay(1);
+
+       /* Restore the exception vector */
+       *vector = save_vector;
+       flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+       local_irq_restore(flags);
+
+       pr_debug("wait CPU #%d for %d msecs.\n", nr, n);
+}
+
+
+static void __init
+smp_86xx_setup_cpu(int cpu_nr)
+{
+       mpic_setup_this_cpu();
+}
+
+
+struct smp_ops_t smp_86xx_ops = {
+       .message_pass = smp_mpic_message_pass,
+       .probe = smp_mpic_probe,
+       .kick_cpu = smp_86xx_kick_cpu,
+       .setup_cpu = smp_86xx_setup_cpu,
+       .take_timebase = smp_generic_take_timebase,
+       .give_timebase = smp_generic_give_timebase,
+};
+
+
+void __init
+mpc86xx_smp_init(void)
+{
+       smp_ops = &smp_86xx_ops;
+}
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
new file mode 100644 (file)
index 0000000..a8c8f0a
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * MPC86XX pci setup code
+ *
+ * Recode: ZHANG WEI <wei.zhang@freescale.com>
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/immap_86xx.h>
+#include <asm/pci-bridge.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
+struct pcie_outbound_window_regs {
+       uint    pexotar;               /* 0x.0 - PCI Express outbound translation address register */
+       uint    pexotear;              /* 0x.4 - PCI Express outbound translation extended address register */
+       uint    pexowbar;              /* 0x.8 - PCI Express outbound window base address register */
+       char    res1[4];
+       uint    pexowar;               /* 0x.10 - PCI Express outbound window attributes register */
+       char    res2[12];
+};
+
+struct pcie_inbound_window_regs {
+       uint    pexitar;               /* 0x.0 - PCI Express inbound translation address register */
+       char    res1[4];
+       uint    pexiwbar;              /* 0x.8 - PCI Express inbound window base address register */
+       uint    pexiwbear;             /* 0x.c - PCI Express inbound window base extended address register */
+       uint    pexiwar;               /* 0x.10 - PCI Express inbound window attributes register */
+       char    res2[12];
+};
+
+static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc)
+{
+       volatile struct ccsr_pex *pcie;
+       volatile struct pcie_outbound_window_regs *pcieow;
+       volatile struct pcie_inbound_window_regs *pcieiw;
+       int i = 0;
+
+       DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start,
+                       rsrc->end - rsrc->start + 1);
+       pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+
+       /* Disable all windows (except pexowar0 since its ignored) */
+       pcie->pexowar1 = 0;
+       pcie->pexowar2 = 0;
+       pcie->pexowar3 = 0;
+       pcie->pexowar4 = 0;
+       pcie->pexiwar1 = 0;
+       pcie->pexiwar2 = 0;
+       pcie->pexiwar3 = 0;
+
+       pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1;
+       pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1;
+
+       /* Setup outbound MEM window */
+       for(i = 0; i < 3; i++)
+               if (hose->mem_resources[i].flags & IORESOURCE_MEM){
+                       DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n",
+                               hose->mem_resources[i].start,
+                               hose->mem_resources[i].end
+                                 - hose->mem_resources[i].start + 1);
+                       pcieow->pexotar = (hose->mem_resources[i].start) >> 12
+                               & 0x000fffff;
+                       pcieow->pexotear = 0;
+                       pcieow->pexowbar = (hose->mem_resources[i].start) >> 12
+                               & 0x000fffff;
+                       /* Enable, Mem R/W */
+                       pcieow->pexowar = 0x80044000 |
+                               (__ilog2(hose->mem_resources[i].end
+                                        - hose->mem_resources[i].start + 1)
+                                - 1);
+                       pcieow++;
+               }
+
+       /* Setup outbound IO window */
+       if (hose->io_resource.flags & IORESOURCE_IO){
+               DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n",
+                       hose->io_resource.start,
+                       hose->io_resource.end - hose->io_resource.start + 1,
+                       hose->io_base_phys);
+               pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff;
+               pcieow->pexotear = 0;
+               pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff;
+               /* Enable, IO R/W */
+               pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end
+                                       - hose->io_resource.start + 1) - 1);
+       }
+
+       /* Setup 2G inbound Memory Window @ 0 */
+       pcieiw->pexitar = 0x00000000;
+       pcieiw->pexiwbar = 0x00000000;
+       /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */
+       pcieiw->pexiwar = 0xa0f5501e;
+}
+
+static void __init
+mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
+{
+       u16 cmd;
+       unsigned int temps;
+
+       DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
+                       pcie_offset, pcie_size);
+
+       early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
+       cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
+           | PCI_COMMAND_IO;
+       early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
+
+       early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
+
+       /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
+       early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
+       temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
+       early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
+}
+
+int mpc86xx_exclude_device(u_char bus, u_char devfn)
+{
+       if (bus == 0 && PCI_SLOT(devfn) == 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+int __init add_bridge(struct device_node *dev)
+{
+       int len;
+       struct pci_controller *hose;
+       struct resource rsrc;
+       int *bus_range;
+       int has_address = 0;
+       int primary = 0;
+
+       DBG("Adding PCIE host bridge %s\n", dev->full_name);
+
+       /* Fetch host bridge registers address */
+       has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+       /* Get bus range if any */
+       bus_range = (int *) get_property(dev, "bus-range", &len);
+       if (bus_range == NULL || len < 2 * sizeof(int))
+               printk(KERN_WARNING "Can't get bus-range for %s, assume"
+                      " bus 0\n", dev->full_name);
+
+       hose = pcibios_alloc_controller();
+       if (!hose)
+               return -ENOMEM;
+       hose->arch_data = dev;
+       hose->set_cfg_type = 1;
+
+       /* last_busno = 0xfe cause by MPC8641 PCIE bug */
+       hose->first_busno = bus_range ? bus_range[0] : 0x0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+
+       setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+
+       /* Setup the PCIE host controller. */
+       mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
+
+       if ((rsrc.start & 0xfffff) == 0x8000)
+               primary = 1;
+
+       printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
+              "Firmware bus number: %d->%d\n",
+              (unsigned long) rsrc.start,
+              hose->first_busno, hose->last_busno);
+
+       DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+               hose, hose->cfg_addr, hose->cfg_data);
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pci_process_bridge_OF_ranges(hose, dev, primary);
+
+       /* Setup PEX window registers */
+       setup_pcie_atmu(hose, &rsrc);
+
+       return 0;
+}
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
new file mode 100644 (file)
index 0000000..7315f66
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * cbe_regs.c
+ *
+ * Accessor routines for the various MMIO register blocks of the CBE
+ *
+ * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ */
+
+#include <linux/percpu.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/ptrace.h>
+
+#include "cbe_regs.h"
+
+#define MAX_CBE                2
+
+/*
+ * Current implementation uses "cpu" nodes. We build our own mapping
+ * array of cpu numbers to cpu nodes locally for now to allow interrupt
+ * time code to have a fast path rather than call of_get_cpu_node(). If
+ * we implement cpu hotplug, we'll have to install an appropriate norifier
+ * in order to release references to the cpu going away
+ */
+static struct cbe_regs_map
+{
+       struct device_node *cpu_node;
+       struct cbe_pmd_regs __iomem *pmd_regs;
+       struct cbe_iic_regs __iomem *iic_regs;
+} cbe_regs_maps[MAX_CBE];
+static int cbe_regs_map_count;
+
+static struct cbe_thread_map
+{
+       struct device_node *cpu_node;
+       struct cbe_regs_map *regs;
+} cbe_thread_map[NR_CPUS];
+
+static struct cbe_regs_map *cbe_find_map(struct device_node *np)
+{
+       int i;
+
+       for (i = 0; i < cbe_regs_map_count; i++)
+               if (cbe_regs_maps[i].cpu_node == np)
+                       return &cbe_regs_maps[i];
+       return NULL;
+}
+
+struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
+{
+       struct cbe_regs_map *map = cbe_find_map(np);
+       if (map == NULL)
+               return NULL;
+       return map->pmd_regs;
+}
+
+struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
+{
+       struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+       if (map == NULL)
+               return NULL;
+       return map->pmd_regs;
+}
+
+
+struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
+{
+       struct cbe_regs_map *map = cbe_find_map(np);
+       if (map == NULL)
+               return NULL;
+       return map->iic_regs;
+}
+struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
+{
+       struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+       if (map == NULL)
+               return NULL;
+       return map->iic_regs;
+}
+
+void __init cbe_regs_init(void)
+{
+       int i;
+       struct device_node *cpu;
+
+       /* Build local fast map of CPUs */
+       for_each_possible_cpu(i)
+               cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);
+
+       /* Find maps for each device tree CPU */
+       for_each_node_by_type(cpu, "cpu") {
+               struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
+
+               /* That hack must die die die ! */
+               struct address_prop {
+                       unsigned long address;
+                       unsigned int len;
+               } __attribute__((packed)) *prop;
+
+
+               if (cbe_regs_map_count > MAX_CBE) {
+                       printk(KERN_ERR "cbe_regs: More BE chips than supported"
+                              "!\n");
+                       cbe_regs_map_count--;
+                       return;
+               }
+               map->cpu_node = cpu;
+               for_each_possible_cpu(i)
+                       if (cbe_thread_map[i].cpu_node == cpu)
+                               cbe_thread_map[i].regs = map;
+
+               prop = (struct address_prop *)get_property(cpu, "pervasive",
+                                                          NULL);
+               if (prop != NULL)
+                       map->pmd_regs = ioremap(prop->address, prop->len);
+
+               prop = (struct address_prop *)get_property(cpu, "iic",
+                                                          NULL);
+               if (prop != NULL)
+                       map->iic_regs = ioremap(prop->address, prop->len);
+       }
+}
+
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
new file mode 100644 (file)
index 0000000..e76e4a6
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * cbe_regs.h
+ *
+ * This file is intended to hold the various register definitions for CBE
+ * on-chip system devices (memory controller, IO controller, etc...)
+ *
+ * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ */
+
+#ifndef CBE_REGS_H
+#define CBE_REGS_H
+
+/*
+ *
+ * Some HID register definitions
+ *
+ */
+
+/* CBE specific HID0 bits */
+#define HID0_CBE_THERM_WAKEUP  0x0000020000000000ul
+#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul
+#define HID0_CBE_THERM_INT_EN  0x0000000400000000ul
+#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
+
+
+/*
+ *
+ * Pervasive unit register definitions
+ *
+ */
+
+struct cbe_pmd_regs {
+       u8 pad_0x0000_0x0800[0x0800 - 0x0000];                  /* 0x0000 */
+
+       /* Thermal Sensor Registers */
+       u64  ts_ctsr1;                                          /* 0x0800 */
+       u64  ts_ctsr2;                                          /* 0x0808 */
+       u64  ts_mtsr1;                                          /* 0x0810 */
+       u64  ts_mtsr2;                                          /* 0x0818 */
+       u64  ts_itr1;                                           /* 0x0820 */
+       u64  ts_itr2;                                           /* 0x0828 */
+       u64  ts_gitr;                                           /* 0x0830 */
+       u64  ts_isr;                                            /* 0x0838 */
+       u64  ts_imr;                                            /* 0x0840 */
+       u64  tm_cr1;                                            /* 0x0848 */
+       u64  tm_cr2;                                            /* 0x0850 */
+       u64  tm_simr;                                           /* 0x0858 */
+       u64  tm_tpr;                                            /* 0x0860 */
+       u64  tm_str1;                                           /* 0x0868 */
+       u64  tm_str2;                                           /* 0x0870 */
+       u64  tm_tsr;                                            /* 0x0878 */
+
+       /* Power Management */
+       u64  pm_control;                                        /* 0x0880 */
+#define CBE_PMD_PAUSE_ZERO_CONTROL             0x10000
+       u64  pm_status;                                         /* 0x0888 */
+
+       /* Time Base Register */
+       u64  tbr;                                               /* 0x0890 */
+
+       u8   pad_0x0898_0x0c00 [0x0c00 - 0x0898];               /* 0x0898 */
+
+       /* Fault Isolation Registers */
+       u64  checkstop_fir;                                     /* 0x0c00 */
+       u64  recoverable_fir;
+       u64  spec_att_mchk_fir;
+       u64  fir_mode_reg;
+       u64  fir_enable_mask;
+
+       u8   pad_0x0c28_0x1000 [0x1000 - 0x0c28];               /* 0x0c28 */
+};
+
+extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
+extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
+
+/*
+ *
+ * IIC unit register definitions
+ *
+ */
+
+struct cbe_iic_pending_bits {
+       u32 data;
+       u8 flags;
+       u8 class;
+       u8 source;
+       u8 prio;
+};
+
+#define CBE_IIC_IRQ_VALID      0x80
+#define CBE_IIC_IRQ_IPI                0x40
+
+struct cbe_iic_thread_regs {
+       struct cbe_iic_pending_bits pending;
+       struct cbe_iic_pending_bits pending_destr;
+       u64 generate;
+       u64 prio;
+};
+
+struct cbe_iic_regs {
+       u8      pad_0x0000_0x0400[0x0400 - 0x0000];             /* 0x0000 */
+
+       /* IIC interrupt registers */
+       struct  cbe_iic_thread_regs thread[2];                  /* 0x0400 */
+       u64     iic_ir;                                         /* 0x0440 */
+       u64     iic_is;                                         /* 0x0448 */
+
+       u8      pad_0x0450_0x0500[0x0500 - 0x0450];             /* 0x0450 */
+
+       /* IOC FIR */
+       u64     ioc_fir_reset;                                  /* 0x0500 */
+       u64     ioc_fir_set;
+       u64     ioc_checkstop_enable;
+       u64     ioc_fir_error_mask;
+       u64     ioc_syserr_enable;
+       u64     ioc_fir;
+
+       u8      pad_0x0530_0x1000[0x1000 - 0x0530];             /* 0x0530 */
+};
+
+extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
+extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
+
+
+/* Init this module early */
+extern void cbe_regs_init(void);
+
+
+#endif /* CBE_REGS_H */
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
new file mode 100644 (file)
index 0000000..0984c70
--- /dev/null
@@ -0,0 +1,111 @@
+#define DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+#include "ras.h"
+#include "cbe_regs.h"
+
+
+static void dump_fir(int cpu)
+{
+       struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu);
+       struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu);
+
+       if (pregs == NULL)
+               return;
+
+       /* Todo: do some nicer parsing of bits and based on them go down
+        * to other sub-units FIRs and not only IIC
+        */
+       printk(KERN_ERR "Global Checkstop FIR    : 0x%016lx\n",
+              in_be64(&pregs->checkstop_fir));
+       printk(KERN_ERR "Global Recoverable FIR  : 0x%016lx\n",
+              in_be64(&pregs->checkstop_fir));
+       printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n",
+              in_be64(&pregs->spec_att_mchk_fir));
+
+       if (iregs == NULL)
+               return;
+       printk(KERN_ERR "IOC FIR                 : 0x%016lx\n",
+              in_be64(&iregs->ioc_fir));
+
+}
+
+void cbe_system_error_exception(struct pt_regs *regs)
+{
+       int cpu = smp_processor_id();
+
+       printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu);
+       dump_fir(cpu);
+       dump_stack();
+}
+
+void cbe_maintenance_exception(struct pt_regs *regs)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * Nothing implemented for the maintenance interrupt at this point
+        */
+
+       printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu);
+       dump_stack();
+}
+
+void cbe_thermal_exception(struct pt_regs *regs)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * Nothing implemented for the thermal interrupt at this point
+        */
+
+       printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu);
+       dump_stack();
+}
+
+static int cbe_machine_check_handler(struct pt_regs *regs)
+{
+       int cpu = smp_processor_id();
+
+       printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu);
+       dump_fir(cpu);
+
+       /* No recovery from this code now, lets continue */
+       return 0;
+}
+
+void __init cbe_ras_init(void)
+{
+       unsigned long hid0;
+
+       /*
+        * Enable System Error & thermal interrupts and wakeup conditions
+        */
+
+       hid0 = mfspr(SPRN_HID0);
+       hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP |
+               HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP;
+       mtspr(SPRN_HID0, hid0);
+       mb();
+
+       /*
+        * Install machine check handler. Leave setting of precise mode to
+        * what the firmware did for now
+        */
+       ppc_md.machine_check_exception = cbe_machine_check_handler;
+       mb();
+
+       /*
+        * For now, we assume that IOC_FIR is already set to forward some
+        * error conditions to the System Error handler. If that is not true
+        * then it will have to be fixed up here.
+        */
+}
diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h
new file mode 100644 (file)
index 0000000..eb7ee54
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef RAS_H
+#define RAS_H
+
+extern void cbe_system_error_exception(struct pt_regs *regs);
+extern void cbe_maintenance_exception(struct pt_regs *regs);
+extern void cbe_thermal_exception(struct pt_regs *regs);
+extern void cbe_ras_init(void);
+
+#endif /* RAS_H */
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
new file mode 100644 (file)
index 0000000..71b69f0
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * spu hypervisor abstraction for direct hardware access.
+ *
+ *  (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *  Copyright 2006 Sony 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; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+
+#include "interrupt.h"
+
+static void int_mask_and(struct spu *spu, int class, u64 mask)
+{
+       u64 old_mask;
+
+       old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+       out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
+}
+
+static void int_mask_or(struct spu *spu, int class, u64 mask)
+{
+       u64 old_mask;
+
+       old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+       out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
+}
+
+static void int_mask_set(struct spu *spu, int class, u64 mask)
+{
+       out_be64(&spu->priv1->int_mask_RW[class], mask);
+}
+
+static u64 int_mask_get(struct spu *spu, int class)
+{
+       return in_be64(&spu->priv1->int_mask_RW[class]);
+}
+
+static void int_stat_clear(struct spu *spu, int class, u64 stat)
+{
+       out_be64(&spu->priv1->int_stat_RW[class], stat);
+}
+
+static u64 int_stat_get(struct spu *spu, int class)
+{
+       return in_be64(&spu->priv1->int_stat_RW[class]);
+}
+
+static void cpu_affinity_set(struct spu *spu, int cpu)
+{
+       u64 target = iic_get_target_id(cpu);
+       u64 route = target << 48 | target << 32 | target << 16;
+       out_be64(&spu->priv1->int_route_RW, route);
+}
+
+static u64 mfc_dar_get(struct spu *spu)
+{
+       return in_be64(&spu->priv1->mfc_dar_RW);
+}
+
+static u64 mfc_dsisr_get(struct spu *spu)
+{
+       return in_be64(&spu->priv1->mfc_dsisr_RW);
+}
+
+static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
+{
+       out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
+}
+
+static void mfc_sdr_set(struct spu *spu, u64 sdr)
+{
+       out_be64(&spu->priv1->mfc_sdr_RW, sdr);
+}
+
+static void mfc_sr1_set(struct spu *spu, u64 sr1)
+{
+       out_be64(&spu->priv1->mfc_sr1_RW, sr1);
+}
+
+static u64 mfc_sr1_get(struct spu *spu)
+{
+       return in_be64(&spu->priv1->mfc_sr1_RW);
+}
+
+static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+{
+       out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
+}
+
+static u64 mfc_tclass_id_get(struct spu *spu)
+{
+       return in_be64(&spu->priv1->mfc_tclass_id_RW);
+}
+
+static void tlb_invalidate(struct spu *spu)
+{
+       out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
+}
+
+static void resource_allocation_groupID_set(struct spu *spu, u64 id)
+{
+       out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
+}
+
+static u64 resource_allocation_groupID_get(struct spu *spu)
+{
+       return in_be64(&spu->priv1->resource_allocation_groupID_RW);
+}
+
+static void resource_allocation_enable_set(struct spu *spu, u64 enable)
+{
+       out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
+}
+
+static u64 resource_allocation_enable_get(struct spu *spu)
+{
+       return in_be64(&spu->priv1->resource_allocation_enable_RW);
+}
+
+const struct spu_priv1_ops spu_priv1_mmio_ops =
+{
+       .int_mask_and = int_mask_and,
+       .int_mask_or = int_mask_or,
+       .int_mask_set = int_mask_set,
+       .int_mask_get = int_mask_get,
+       .int_stat_clear = int_stat_clear,
+       .int_stat_get = int_stat_get,
+       .cpu_affinity_set = cpu_affinity_set,
+       .mfc_dar_get = mfc_dar_get,
+       .mfc_dsisr_get = mfc_dsisr_get,
+       .mfc_dsisr_set = mfc_dsisr_set,
+       .mfc_sdr_set = mfc_sdr_set,
+       .mfc_sr1_set = mfc_sr1_set,
+       .mfc_sr1_get = mfc_sr1_get,
+       .mfc_tclass_id_set = mfc_tclass_id_set,
+       .mfc_tclass_id_get = mfc_tclass_id_get,
+       .tlb_invalidate = tlb_invalidate,
+       .resource_allocation_groupID_set = resource_allocation_groupID_set,
+       .resource_allocation_groupID_get = resource_allocation_groupID_get,
+       .resource_allocation_enable_set = resource_allocation_enable_set,
+       .resource_allocation_enable_get = resource_allocation_enable_get,
+};
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
new file mode 100644 (file)
index 0000000..fa499fe
--- /dev/null
@@ -0,0 +1,4 @@
+#
+# Makefile for the 6xx/7xx/7xxxx linux kernel.
+#
+obj-$(CONFIG_MPC7448HPC2)      += mpc7448_hpc2.o
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
new file mode 100644 (file)
index 0000000..6260bc5
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * mpc7448_hpc2.c
+ *
+ * Board setup routines for the Freescale mpc7448hpc2(taiga) platform
+ *
+ * Author: Jacob Pan
+ *      jacob.pan@freescale.com
+ * Author: Xianghua Xiao
+ *       x.xiao@freescale.com
+ * Maintainer: Roy Zang <tie-fei.zang@freescale.com>
+ *     Add Flat Device Tree support fot mpc7448hpc2 board
+ *
+ * Copyright 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/tsi108.h>
+#include <asm/pci-bridge.h>
+#include <asm/reg.h>
+#include <mm/mmu_decl.h>
+#include "mpc7448_hpc2.h"
+#include <asm/tsi108_irq.h>
+#include <asm/mpic.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+#ifndef CONFIG_PCI
+isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
+isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
+pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
+#endif
+
+extern int tsi108_setup_pci(struct device_node *dev);
+extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+extern void tsi108_pci_int_init(void);
+extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
+                           struct pt_regs *regs);
+
+int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
+{
+       if (bus == 0 && PCI_SLOT(devfn) == 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       else
+               return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * find pci slot by devfn in interrupt map of OF tree
+ */
+u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn)
+{
+       int i;
+       unsigned int tmp;
+       for (i = 0; i < 4; i++){
+               tmp = interrupt_map[i*4*7];
+               if ((tmp >> 11) == (devfn >> 3))
+                       return i;
+       }
+       return i;
+}
+
+/*
+ * Scans the interrupt map for pci device
+ */
+void mpc7448_hpc2_fixup_irq(struct pci_dev *dev)
+{
+       struct pci_controller *hose;
+       struct device_node *node;
+       unsigned int *interrupt;
+       int busnr;
+       int len;
+       u8 slot;
+       u8 pin;
+
+       /* Lookup the hose */
+       busnr = dev->bus->number;
+       hose = pci_bus_to_hose(busnr);
+       if (!hose)
+               printk(KERN_ERR "No pci hose found\n");
+
+       /* Check it has an OF node associated */
+       node = (struct device_node *) hose->arch_data;
+       if (!node)
+               printk(KERN_ERR "No pci node found\n");
+
+       interrupt = (unsigned int *) get_property(node, "interrupt-map", &len);
+       slot = find_slot_by_devfn(interrupt, dev->devfn);
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       if (pin == 0 || pin > 4)
+               pin = 1;
+       pin--;
+       dev->irq  = interrupt[slot*4*7 + pin*7 + 5];
+       DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq);
+}
+/* temporary pci irq map fixup*/
+
+void __init mpc7448_hpc2_pcibios_fixup(void)
+{
+       struct pci_dev *dev = NULL;
+       for_each_pci_dev(dev) {
+               mpc7448_hpc2_fixup_irq(dev);
+               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+       }
+}
+
+static void __init mpc7448_hpc2_setup_arch(void)
+{
+       struct device_node *cpu;
+       struct device_node *np;
+       if (ppc_md.progress)
+               ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
+
+       cpu = of_find_node_by_type(NULL, "cpu");
+       if (cpu != 0) {
+               unsigned int *fp;
+
+               fp = (int *)get_property(cpu, "clock-frequency", NULL);
+               if (fp != 0)
+                       loops_per_jiffy = *fp / HZ;
+               else
+                       loops_per_jiffy = 50000000 / HZ;
+               of_node_put(cpu);
+       }
+       tsi108_csr_vir_base = get_vir_csrbase();
+
+#ifdef CONFIG_ROOT_NFS
+       ROOT_DEV = Root_NFS;
+#else
+       ROOT_DEV = Root_HDA1;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       ROOT_DEV = Root_RAM0;
+#endif
+
+       /* setup PCI host bridge */
+#ifdef CONFIG_PCI
+       for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+               tsi108_setup_pci(np);
+
+       ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
+       if (ppc_md.progress)
+               ppc_md.progress("tsi108: resources set", 0x100);
+#endif
+
+       printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n");
+       printk(KERN_INFO
+              "Jointly ported by Freescale and Tundra Semiconductor\n");
+       printk(KERN_INFO
+              "Enabling L2 cache then enabling the HID0 prefetch engine.\n");
+}
+
+/*
+ * Interrupt setup and service.  Interrrupts on the mpc7448_hpc2 come
+ * from the four external INT pins, PCI interrupts are routed via
+ * PCI interrupt control registers, it generates internal IRQ23
+ *
+ * Interrupt routing on the Taiga Board:
+ * TSI108:PB_INT[0] -> CPU0:INT#
+ * TSI108:PB_INT[1] -> CPU0:MCP#
+ * TSI108:PB_INT[2] -> N/C
+ * TSI108:PB_INT[3] -> N/C
+ */
+static void __init mpc7448_hpc2_init_IRQ(void)
+{
+       struct mpic *mpic;
+       phys_addr_t mpic_paddr = 0;
+       unsigned int cascade_pci_irq;
+       struct device_node *tsi_pci;
+       struct device_node *tsi_pic;
+
+       tsi_pic = of_find_node_by_type(NULL, "open-pic");
+       if (tsi_pic) {
+               unsigned int size;
+               void *prop = get_property(tsi_pic, "reg", &size);
+               mpic_paddr = of_translate_address(tsi_pic, prop);
+       }
+
+       if (mpic_paddr == 0) {
+               printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
+               return;
+       }
+
+       DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
+           (u32) mpic_paddr);
+
+       mpic = mpic_alloc(tsi_pic, mpic_paddr,
+                       MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
+                       MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
+                       0, /* num_sources used */
+                       0, /* num_sources used */
+                       "Tsi108_PIC");
+
+       BUG_ON(mpic == NULL); /* XXXX */
+       mpic_init(mpic);
+
+       tsi_pci = of_find_node_by_type(NULL, "pci");
+       if (tsi_pci == 0) {
+               printk("%s: No tsi108 pci node found !\n", __FUNCTION__);
+               return;
+       }
+
+       cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
+       set_irq_data(cascade_pci_irq, mpic);
+       set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+
+       tsi108_pci_int_init();
+
+       /* Configure MPIC outputs to CPU0 */
+       tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
+       of_node_put(tsi_pic);
+}
+
+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)
+{
+       local_irq_disable();
+
+       /* Set exception prefix high - to the firmware */
+       _nmask_and_or_msr(0, MSR_IP);
+
+       for (;;) ;              /* Spin until reset happens */
+}
+
+void mpc7448_hpc2_power_off(void)
+{
+       local_irq_disable();
+       for (;;) ;              /* No way to shut power off with software */
+}
+
+void mpc7448_hpc2_halt(void)
+{
+       mpc7448_hpc2_power_off();
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc7448_hpc2_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (!of_flat_dt_is_compatible(root, "mpc74xx"))
+               return 0;
+       return 1;
+}
+
+static int mpc7448_machine_check_exception(struct pt_regs *regs)
+{
+       extern void tsi108_clear_pci_cfg_error(void);
+       const struct exception_table_entry *entry;
+
+       /* Are we prepared to handle this fault */
+       if ((entry = search_exception_tables(regs->nip)) != NULL) {
+               tsi108_clear_pci_cfg_error();
+               regs->msr |= MSR_RI;
+               regs->nip = entry->fixup;
+               return 1;
+       }
+       return 0;
+
+}
+
+define_machine(mpc7448_hpc2){
+       .name                   = "MPC7448 HPC2",
+       .probe                  = mpc7448_hpc2_probe,
+       .setup_arch             = mpc7448_hpc2_setup_arch,
+       .init_IRQ               = mpc7448_hpc2_init_IRQ,
+       .show_cpuinfo           = mpc7448_hpc2_show_cpuinfo,
+       .get_irq                = mpic_get_irq,
+       .pcibios_fixup          = mpc7448_hpc2_pcibios_fixup,
+       .restart                = mpc7448_hpc2_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .machine_check_exception= mpc7448_machine_check_exception,
+       .progress               = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
new file mode 100644 (file)
index 0000000..a543a52
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * mpc7448_hpc2.h
+ *
+ * Definitions for Freescale MPC7448_HPC2 platform
+ *
+ * Author: Jacob Pan
+ *         jacob.pan@freescale.com
+ * Maintainer: Roy Zang <roy.zang@freescale.com>
+ *
+ * 2006 (c) Freescale Semiconductor, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PLATFORMS_MPC7448_HPC2_H
+#define __PPC_PLATFORMS_MPC7448_HPC2_H
+
+#include <asm/ppcboot.h>
+
+/* Base Addresses for the PCI bus
+ */
+#define MPC7448_HPC2_PCI_MEM_OFFSET    (0x00000000)
+#define MPC7448_HPC2_ISA_IO_BASE       (0x00000000)
+#define MPC7448_HPC2_ISA_MEM_BASE      (0x00000000)
+#endif                         /* __PPC_PLATFORMS_MPC7448_HPC2_H */
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
new file mode 100644 (file)
index 0000000..d194140
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ *    Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation
+ *
+ *    Description:
+ *      This file contains all the routines to build a flattened device
+ *      tree for a legacy iSeries machine.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/threads.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>    /* ETH_ALEN */
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/lppaca.h>
+#include <asm/cputable.h>
+#include <asm/abs_addr.h>
+#include <asm/system.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
+#include <asm/udbg.h>
+
+#include "processor_vpd.h"
+#include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/*
+ * These are created by the linker script at the start and end
+ * of the section containing all the strings from this file.
+ */
+extern char __dt_strings_start[];
+extern char __dt_strings_end[];
+
+struct iseries_flat_dt {
+       struct boot_param_header header;
+       u64 reserve_map[2];
+};
+
+static void * __initdata dt_data;
+
+/*
+ * Putting these strings here keeps them out of the section
+ * that we rename to .dt_strings using objcopy and capture
+ * for the strings blob of the flattened device tree.
+ */
+static char __initdata device_type_cpu[] = "cpu";
+static char __initdata device_type_memory[] = "memory";
+static char __initdata device_type_serial[] = "serial";
+static char __initdata device_type_network[] = "network";
+static char __initdata device_type_block[] = "block";
+static char __initdata device_type_byte[] = "byte";
+static char __initdata device_type_pci[] = "pci";
+static char __initdata device_type_vdevice[] = "vdevice";
+static char __initdata device_type_vscsi[] = "vscsi";
+
+static struct iseries_flat_dt * __init dt_init(void)
+{
+       struct iseries_flat_dt *dt;
+       unsigned long str_len;
+
+       str_len = __dt_strings_end - __dt_strings_start;
+       dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
+       dt->header.off_mem_rsvmap =
+               offsetof(struct iseries_flat_dt, reserve_map);
+       dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
+       dt->header.off_dt_struct = dt->header.off_dt_strings
+               + ALIGN(str_len, 8);
+       dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
+       dt->header.dt_strings_size = str_len;
+
+       /* There is no notion of hardware cpu id on iSeries */
+       dt->header.boot_cpuid_phys = smp_processor_id();
+
+       memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
+                       str_len);
+
+       dt->header.magic = OF_DT_HEADER;
+       dt->header.version = 0x10;
+       dt->header.last_comp_version = 0x10;
+
+       dt->reserve_map[0] = 0;
+       dt->reserve_map[1] = 0;
+
+       return dt;
+}
+
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+{
+       *((u32 *)dt_data) = value;
+       dt_data += sizeof(u32);
+}
+
+#ifdef notyet
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+{
+       *((u64 *)dt_data) = value;
+       dt_data += sizeof(u64);
+}
+#endif
+
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
+               int len)
+{
+       memcpy(dt_data, data, len);
+       dt_data += ALIGN(len, 4);
+}
+
+static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
+{
+       dt_push_u32(dt, OF_DT_BEGIN_NODE);
+       dt_push_bytes(dt, name, strlen(name) + 1);
+}
+
+#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
+
+static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
+               const void *data, int len)
+{
+       unsigned long offset;
+
+       dt_push_u32(dt, OF_DT_PROP);
+
+       /* Length of the data */
+       dt_push_u32(dt, len);
+
+       offset = name - __dt_strings_start;
+
+       /* The offset of the properties name in the string blob. */
+       dt_push_u32(dt, (u32)offset);
+
+       /* The actual data. */
+       dt_push_bytes(dt, data, len);
+}
+
+static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
+               const char *data)
+{
+       dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
+}
+
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
+               u32 data)
+{
+       dt_prop(dt, name, &data, sizeof(u32));
+}
+
+#ifdef notyet
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
+               u64 data)
+{
+       dt_prop(dt, name, &data, sizeof(u64));
+}
+#endif
+
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
+               const char *name, u64 *data, int n)
+{
+       dt_prop(dt, name, data, sizeof(u64) * n);
+}
+
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
+               const char *name, u32 *data, int n)
+{
+       dt_prop(dt, name, data, sizeof(u32) * n);
+}
+
+#ifdef notyet
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
+{
+       dt_prop(dt, name, NULL, 0);
+}
+#endif
+
+static void __init dt_cpus(struct iseries_flat_dt *dt)
+{
+       unsigned char buf[32];
+       unsigned char *p;
+       unsigned int i, index;
+       struct IoHriProcessorVpd *d;
+       u32 pft_size[2];
+
+       /* yuck */
+       snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
+       p = strchr(buf, ' ');
+       if (!p) p = buf + strlen(buf);
+
+       dt_start_node(dt, "cpus");
+       dt_prop_u32(dt, "#address-cells", 1);
+       dt_prop_u32(dt, "#size-cells", 0);
+
+       pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
+       pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (lppaca[i].dyn_proc_status >= 2)
+                       continue;
+
+               snprintf(p, 32 - (p - buf), "@%d", i);
+               dt_start_node(dt, buf);
+
+               dt_prop_str(dt, "device_type", device_type_cpu);
+
+               index = lppaca[i].dyn_hv_phys_proc_index;
+               d = &xIoHriProcessorVpd[index];
+
+               dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
+               dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
+
+               dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
+               dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
+
+               /* magic conversions to Hz copied from old code */
+               dt_prop_u32(dt, "clock-frequency",
+                       ((1UL << 34) * 1000000) / d->xProcFreq);
+               dt_prop_u32(dt, "timebase-frequency",
+                       ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
+
+               dt_prop_u32(dt, "reg", i);
+
+               dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
+
+               dt_end_node(dt);
+       }
+
+       dt_end_node(dt);
+}
+
+static void __init dt_model(struct iseries_flat_dt *dt)
+{
+       char buf[16] = "IBM,";
+
+       /* N.B. lparcfg.c knows about the "IBM," prefixes ... */
+       /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+       strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+       strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+       buf[11] = '\0';
+       dt_prop_str(dt, "system-id", buf);
+
+       /* "IBM," + machineType[0:4] */
+       strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+       buf[8] = '\0';
+       dt_prop_str(dt, "model", buf);
+
+       dt_prop_str(dt, "compatible", "IBM,iSeries");
+       dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
+}
+
+static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
+               const char *name, u32 reg, int unit,
+               const char *type, const char *compat, int end)
+{
+       char buf[32];
+
+       snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
+       dt_start_node(dt, buf);
+       dt_prop_str(dt, "device_type", type);
+       if (compat)
+               dt_prop_str(dt, "compatible", compat);
+       dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
+       if (unit >= 0)
+               dt_prop_u32(dt, "linux,unit_address", unit);
+       if (end)
+               dt_end_node(dt);
+}
+
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
+{
+       u32 reg = 0;
+       HvLpIndexMap vlan_map;
+       int i;
+
+       dt_start_node(dt, "vdevice");
+       dt_prop_str(dt, "device_type", device_type_vdevice);
+       dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
+       dt_prop_u32(dt, "#address-cells", 1);
+       dt_prop_u32(dt, "#size-cells", 0);
+
+       dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1);
+       reg++;
+
+       dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
+                       "IBM,v-scsi", 1);
+       reg++;
+
+       vlan_map = HvLpConfig_getVirtualLanIndexMap();
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+               unsigned char mac_addr[ETH_ALEN];
+
+               if ((vlan_map & (0x8000 >> i)) == 0)
+                       continue;
+               dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
+                               "IBM,iSeries-l-lan", 0);
+               mac_addr[0] = 0x02;
+               mac_addr[1] = 0x01;
+               mac_addr[2] = 0xff;
+               mac_addr[3] = i;
+               mac_addr[4] = 0xff;
+               mac_addr[5] = HvLpConfig_getLpIndex_outline();
+               dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
+               dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
+               dt_prop_u32(dt, "max-frame-size", 9000);
+               dt_prop_u32(dt, "address-bits", 48);
+
+               dt_end_node(dt);
+       }
+       reg += HVMAXARCHITECTEDVIRTUALLANS;
+
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+               dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
+                               "IBM,iSeries-viodasd", 1);
+       reg += HVMAXARCHITECTEDVIRTUALDISKS;
+
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+               dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
+                               "IBM,iSeries-viocd", 1);
+       reg += HVMAXARCHITECTEDVIRTUALCDROMS;
+
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+               dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
+                               "IBM,iSeries-viotape", 1);
+
+       dt_end_node(dt);
+}
+
+struct pci_class_name {
+       u16 code;
+       const char *name;
+       const char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+       { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+       struct pci_class_name *cp;
+
+       for (cp = pci_class_name;
+                       cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+               if (cp->code == class_code)
+                       return cp;
+       return NULL;
+}
+
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+               HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
+{
+       HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+       u16 vendor_id;
+       u16 device_id;
+       u32 class_id;
+       int err;
+       char buf[32];
+       u32 reg[5];
+       int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+       int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+       HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+       u8 devfn;
+       struct pci_class_name *cp;
+
+       /*
+        * Connect all functions of any device found.
+        */
+       for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+               for (function = 0; function < 8; function++) {
+                       HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+                                       function);
+                       err = HvCallXm_connectBusUnit(bus, sub_bus,
+                                       agent_id, 0);
+                       if (err) {
+                               if (err != 0x302)
+                                       DBG("connectBusUnit(%x, %x, %x) %x\n",
+                                               bus, sub_bus, agent_id, err);
+                               continue;
+                       }
+
+                       err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+                                       PCI_VENDOR_ID, &vendor_id);
+                       if (err) {
+                               DBG("ReadVendor(%x, %x, %x) %x\n",
+                                       bus, sub_bus, agent_id, err);
+                               continue;
+                       }
+                       err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+                                       PCI_DEVICE_ID, &device_id);
+                       if (err) {
+                               DBG("ReadDevice(%x, %x, %x) %x\n",
+                                       bus, sub_bus, agent_id, err);
+                               continue;
+                       }
+                       err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+                                       PCI_CLASS_REVISION , &class_id);
+                       if (err) {
+                               DBG("ReadClass(%x, %x, %x) %x\n",
+                                       bus, sub_bus, agent_id, err);
+                               continue;
+                       }
+
+                       devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+                                       function);
+                       cp = dt_find_pci_class_name(class_id >> 16);
+                       if (cp && cp->name)
+                               strncpy(buf, cp->name, sizeof(buf) - 1);
+                       else
+                               snprintf(buf, sizeof(buf), "pci%x,%x",
+                                               vendor_id, device_id);
+                       buf[sizeof(buf) - 1] = '\0';
+                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+                                       "@%x", PCI_SLOT(devfn));
+                       buf[sizeof(buf) - 1] = '\0';
+                       if (function != 0)
+                               snprintf(buf + strlen(buf),
+                                       sizeof(buf) - strlen(buf),
+                                       ",%x", function);
+                       dt_start_node(dt, buf);
+                       reg[0] = (bus << 16) | (devfn << 8);
+                       reg[1] = 0;
+                       reg[2] = 0;
+                       reg[3] = 0;
+                       reg[4] = 0;
+                       dt_prop_u32_list(dt, "reg", reg, 5);
+                       if (cp && (cp->type || cp->name))
+                               dt_prop_str(dt, "device_type",
+                                       cp->type ? cp->type : cp->name);
+                       dt_prop_u32(dt, "vendor-id", vendor_id);
+                       dt_prop_u32(dt, "device-id", device_id);
+                       dt_prop_u32(dt, "class-code", class_id >> 8);
+                       dt_prop_u32(dt, "revision-id", class_id & 0xff);
+                       dt_prop_u32(dt, "linux,subbus", sub_bus);
+                       dt_prop_u32(dt, "linux,agent-id", agent_id);
+                       dt_prop_u32(dt, "linux,logical-slot-number",
+                                       bridge_info->logicalSlotNumber);
+                       dt_end_node(dt);
+
+               }
+       }
+}
+
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+               HvSubBusNumber sub_bus, int id_sel)
+{
+       struct HvCallPci_BridgeInfo bridge_info;
+       HvAgentId agent_id;
+       int function;
+       int ret;
+
+       /* Note: hvSubBus and irq is always be 0 at this level! */
+       for (function = 0; function < 8; ++function) {
+               agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+               ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+               if (ret != 0) {
+                       if (ret != 0xb)
+                               DBG("connectBusUnit(%x, %x, %x) %x\n",
+                                               bus, sub_bus, agent_id, ret);
+                       continue;
+               }
+               DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
+                               bus, id_sel, function, agent_id);
+               ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+                               iseries_hv_addr(&bridge_info),
+                               sizeof(struct HvCallPci_BridgeInfo));
+               if (ret != 0)
+                       continue;
+               DBG("bridge info: type %x subbus %x "
+                       "maxAgents %x maxsubbus %x logslot %x\n",
+                       bridge_info.busUnitInfo.deviceType,
+                       bridge_info.subBusNumber,
+                       bridge_info.maxAgents,
+                       bridge_info.maxSubBusNumber,
+                       bridge_info.logicalSlotNumber);
+               if (bridge_info.busUnitInfo.deviceType ==
+                               HvCallPci_BridgeDevice)
+                       scan_bridge_slot(dt, bus, &bridge_info);
+               else
+                       DBG("PCI: Invalid Bridge Configuration(0x%02X)",
+                               bridge_info.busUnitInfo.deviceType);
+       }
+}
+
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+       struct HvCallPci_DeviceInfo dev_info;
+       const HvSubBusNumber sub_bus = 0;       /* EADs is always 0. */
+       int err;
+       int id_sel;
+       const int max_agents = 8;
+
+       /*
+        * Probe for EADs Bridges
+        */
+       for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+               err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+                               iseries_hv_addr(&dev_info),
+                               sizeof(struct HvCallPci_DeviceInfo));
+               if (err) {
+                       if (err != 0x302)
+                               DBG("getDeviceInfo(%x, %x, %x) %x\n",
+                                               bus, sub_bus, id_sel, err);
+                       continue;
+               }
+               if (dev_info.deviceType != HvCallPci_NodeDevice) {
+                       DBG("PCI: Invalid System Configuration"
+                                       "(0x%02X) for bus 0x%02x id 0x%02x.\n",
+                                       dev_info.deviceType, bus, id_sel);
+                       continue;
+               }
+               scan_bridge(dt, bus, sub_bus, id_sel);
+       }
+}
+
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
+{
+       HvBusNumber bus;
+       char buf[32];
+       u32 buses[2];
+       int phb_num = 0;
+
+       /* Check all possible buses. */
+       for (bus = 0; bus < 256; bus++) {
+               int err = HvCallXm_testBus(bus);
+
+               if (err) {
+                       /*
+                        * Check for Unexpected Return code, a clue that
+                        * something has gone wrong.
+                        */
+                       if (err != 0x0301)
+                               DBG("Unexpected Return on Probe(0x%02X) "
+                                               "0x%04X\n", bus, err);
+                       continue;
+               }
+               DBG("bus %d appears to exist\n", bus);
+               snprintf(buf, 32, "pci@%d", phb_num);
+               dt_start_node(dt, buf);
+               dt_prop_str(dt, "device_type", device_type_pci);
+               dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+               dt_prop_u32(dt, "#address-cells", 3);
+               dt_prop_u32(dt, "#size-cells", 2);
+               buses[0] = buses[1] = bus;
+               dt_prop_u32_list(dt, "bus-range", buses, 2);
+               scan_phb(dt, bus);
+               dt_end_node(dt);
+               phb_num++;
+       }
+}
+
+static void dt_finish(struct iseries_flat_dt *dt)
+{
+       dt_push_u32(dt, OF_DT_END);
+       dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
+       klimit = ALIGN((unsigned long)dt_data, 8);
+}
+
+void * __init build_flat_dt(unsigned long phys_mem_size)
+{
+       struct iseries_flat_dt *iseries_dt;
+       u64 tmp[2];
+
+       iseries_dt = dt_init();
+
+       dt_start_node(iseries_dt, "");
+
+       dt_prop_u32(iseries_dt, "#address-cells", 2);
+       dt_prop_u32(iseries_dt, "#size-cells", 2);
+       dt_model(iseries_dt);
+
+       /* /memory */
+       dt_start_node(iseries_dt, "memory@0");
+       dt_prop_str(iseries_dt, "device_type", device_type_memory);
+       tmp[0] = 0;
+       tmp[1] = phys_mem_size;
+       dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
+       dt_end_node(iseries_dt);
+
+       /* /chosen */
+       dt_start_node(iseries_dt, "chosen");
+       dt_prop_str(iseries_dt, "bootargs", cmd_line);
+       dt_end_node(iseries_dt);
+
+       dt_cpus(iseries_dt);
+
+       dt_vdevices(iseries_dt);
+       dt_pci_devices(iseries_dt);
+
+       dt_end_node(iseries_dt);
+
+       dt_finish(iseries_dt);
+
+       return iseries_dt;
+}
diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c
new file mode 100644 (file)
index 0000000..0a65980
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
+ * Real Time Clocks/Timekeepers.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/bcd.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+
+/*
+ * Depending on the hardware on your board and your board design, the
+ * RTC/NVRAM may be accessed either directly (like normal memory) or via
+ * address/data registers.  If your board uses the direct method, set
+ * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
+ * 'nvram_as1' NULL.  If your board uses address/data regs to access nvram,
+ * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
+ * address of the upper byte (leave NULL if using mc146818), and set
+ * 'nvram_data' to the address of the 8-bit data register.
+ *
+ * Note: Even though the documentation for the various RTC chips say that it
+ *      take up to a second before it starts updating once the 'R' bit is
+ *      cleared, they always seem to update even though we bang on it many
+ *      times a second.  This is true, except for the Dallas Semi 1746/1747
+ *      (possibly others).  Those chips seem to have a real problem whenever
+ *      we set the 'R' bit before reading them, they basically stop counting.
+ *                                             --MAG
+ */
+
+/*
+ * 'todc_info' should be initialized in your *_setup.c file to
+ * point to a fully initialized 'todc_info_t' structure.
+ * This structure holds all the register offsets for your particular
+ * TODC/RTC chip.
+ * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you.
+ */
+
+#ifdef RTC_FREQ_SELECT
+#undef RTC_FREQ_SELECT
+#define        RTC_FREQ_SELECT         control_b       /* Register A */
+#endif
+
+#ifdef RTC_CONTROL
+#undef RTC_CONTROL
+#define        RTC_CONTROL             control_a       /* Register B */
+#endif
+
+#ifdef RTC_INTR_FLAGS
+#undef RTC_INTR_FLAGS
+#define        RTC_INTR_FLAGS          watchdog        /* Register C */
+#endif
+
+#ifdef RTC_VALID
+#undef RTC_VALID
+#define        RTC_VALID               interrupts      /* Register D */
+#endif
+
+/* Access routines when RTC accessed directly (like normal memory) */
+u_char
+todc_direct_read_val(int addr)
+{
+       return readb((void __iomem *)(todc_info->nvram_data + addr));
+}
+
+void
+todc_direct_write_val(int addr, unsigned char val)
+{
+       writeb(val, (void __iomem *)(todc_info->nvram_data + addr));
+       return;
+}
+
+/* Access routines for accessing m48txx type chips via addr/data regs */
+u_char
+todc_m48txx_read_val(int addr)
+{
+       outb(addr, todc_info->nvram_as0);
+       outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
+       return inb(todc_info->nvram_data);
+}
+
+void
+todc_m48txx_write_val(int addr, unsigned char val)
+{
+       outb(addr, todc_info->nvram_as0);
+       outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
+       outb(val, todc_info->nvram_data);
+       return;
+}
+
+/* Access routines for accessing mc146818 type chips via addr/data regs */
+u_char
+todc_mc146818_read_val(int addr)
+{
+       outb_p(addr, todc_info->nvram_as0);
+       return inb_p(todc_info->nvram_data);
+}
+
+void
+todc_mc146818_write_val(int addr, unsigned char val)
+{
+       outb_p(addr, todc_info->nvram_as0);
+       outb_p(val, todc_info->nvram_data);
+}
+
+
+/*
+ * Routines to make RTC chips with NVRAM buried behind an addr/data pair
+ * have the NVRAM and clock regs appear at the same level.
+ * The NVRAM will appear to start at addr 0 and the clock regs will appear
+ * to start immediately after the NVRAM (actually, start at offset
+ * todc_info->nvram_size).
+ */
+static inline u_char
+todc_read_val(int addr)
+{
+       u_char  val;
+
+       if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
+               if (addr < todc_info->nvram_size) { /* NVRAM */
+                       ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
+                       val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
+               } else { /* Clock Reg */
+                       addr -= todc_info->nvram_size;
+                       val = ppc_md.rtc_read_val(addr);
+               }
+       } else
+               val = ppc_md.rtc_read_val(addr);
+
+       return val;
+}
+
+static inline void
+todc_write_val(int addr, u_char val)
+{
+       if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
+               if (addr < todc_info->nvram_size) { /* NVRAM */
+                       ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
+                       ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
+               } else { /* Clock Reg */
+                       addr -= todc_info->nvram_size;
+                       ppc_md.rtc_write_val(addr, val);
+               }
+       } else
+               ppc_md.rtc_write_val(addr, val);
+}
+
+/*
+ * TODC routines
+ *
+ * There is some ugly stuff in that there are assumptions for the mc146818.
+ *
+ * Assumptions:
+ *     - todc_info->control_a has the offset as mc146818 Register B reg
+ *     - todc_info->control_b has the offset as mc146818 Register A reg
+ *     - m48txx control reg's write enable or 'W' bit is same as
+ *       mc146818 Register B 'SET' bit (i.e., 0x80)
+ *
+ * These assumptions were made to make the code simpler.
+ */
+long __init
+todc_time_init(void)
+{
+       u_char  cntl_b;
+
+       if (!ppc_md.rtc_read_val)
+               ppc_md.rtc_read_val = ppc_md.nvram_read_val;
+       if (!ppc_md.rtc_write_val)
+               ppc_md.rtc_write_val = ppc_md.nvram_write_val;
+
+       cntl_b = todc_read_val(todc_info->control_b);
+
+       if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+               if ((cntl_b & 0x70) != 0x20) {
+                       printk(KERN_INFO "TODC real-time-clock was stopped."
+                               "  Now starting...");
+                       cntl_b &= ~0x70;
+                       cntl_b |= 0x20;
+               }
+
+               todc_write_val(todc_info->control_b, cntl_b);
+       } else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
+               u_char mode;
+
+               mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
+               /* Make sure countdown clear is not set */
+               mode &= ~0x40;
+               /* Enable oscillator, extended register set */
+               mode |= 0x30;
+               todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
+
+       } else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
+               u_char  month;
+
+               todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
+               todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
+
+               month = todc_read_val(todc_info->month);
+
+               if ((month & 0x80) == 0x80) {
+                       printk(KERN_INFO "TODC %s %s\n",
+                               "real-time-clock was stopped.",
+                               "Now starting...");
+                       month &= ~0x80;
+                       todc_write_val(todc_info->month, month);
+               }
+
+               cntl_b &= ~TODC_DS1501_CNTL_B_TE;
+               todc_write_val(todc_info->control_b, cntl_b);
+       } else { /* must be a m48txx type */
+               u_char  cntl_a;
+
+               todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
+               todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
+
+               cntl_a = todc_read_val(todc_info->control_a);
+
+               /* Check & clear STOP bit in control B register */
+               if (cntl_b & TODC_MK48TXX_DAY_CB) {
+                       printk(KERN_INFO "TODC %s %s\n",
+                               "real-time-clock was stopped.",
+                               "Now starting...");
+
+                       cntl_a |= todc_info->enable_write;
+                       cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
+
+                       todc_write_val(todc_info->control_a, cntl_a);
+                       todc_write_val(todc_info->control_b, cntl_b);
+               }
+
+               /* Make sure READ & WRITE bits are cleared. */
+               cntl_a &= ~(todc_info->enable_write | todc_info->enable_read);
+               todc_write_val(todc_info->control_a, cntl_a);
+       }
+
+       return 0;
+}
+
+/*
+ * There is some ugly stuff in that there are assumptions that for a mc146818,
+ * the todc_info->control_a has the offset of the mc146818 Register B reg and
+ * that the register'ss 'SET' bit is the same as the m48txx's write enable
+ * bit in the control register of the m48txx (i.e., 0x80).
+ *
+ * It was done to make the code look simpler.
+ */
+void
+todc_get_rtc_time(struct rtc_time *tm)
+{
+       uint    year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0;
+       uint    limit, i;
+       u_char  save_control, uip = 0;
+       extern void GregorianDay(struct rtc_time *);
+
+       spin_lock(&rtc_lock);
+       save_control = todc_read_val(todc_info->control_a);
+
+       if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+               limit = 1;
+
+               switch (todc_info->rtc_type) {
+               case TODC_TYPE_DS1553:
+               case TODC_TYPE_DS1557:
+               case TODC_TYPE_DS1743:
+               case TODC_TYPE_DS1746:  /* XXXX BAD HACK -> FIX */
+               case TODC_TYPE_DS1747:
+               case TODC_TYPE_DS17285:
+                       break;
+               default:
+                       todc_write_val(todc_info->control_a,
+                               (save_control | todc_info->enable_read));
+               }
+       } else
+               limit = 100000000;
+
+       for (i=0; i<limit; i++) {
+               if (todc_info->rtc_type == TODC_TYPE_MC146818)
+                       uip = todc_read_val(todc_info->RTC_FREQ_SELECT);
+
+               sec = todc_read_val(todc_info->seconds) & 0x7f;
+               min = todc_read_val(todc_info->minutes) & 0x7f;
+               hour = todc_read_val(todc_info->hours) & 0x3f;
+               mday = todc_read_val(todc_info->day_of_month) & 0x3f;
+               mon = todc_read_val(todc_info->month) & 0x1f;
+               year = todc_read_val(todc_info->year) & 0xff;
+
+               if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+                       uip |= todc_read_val(todc_info->RTC_FREQ_SELECT);
+                       if ((uip & RTC_UIP) == 0)
+                               break;
+               }
+       }
+
+       if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+               switch (todc_info->rtc_type) {
+               case TODC_TYPE_DS1553:
+               case TODC_TYPE_DS1557:
+               case TODC_TYPE_DS1743:
+               case TODC_TYPE_DS1746:  /* XXXX BAD HACK -> FIX */
+               case TODC_TYPE_DS1747:
+               case TODC_TYPE_DS17285:
+                       break;
+               default:
+                       save_control &= ~(todc_info->enable_read);
+                       todc_write_val(todc_info->control_a, save_control);
+               }
+       }
+       spin_unlock(&rtc_lock);
+
+       if ((todc_info->rtc_type != TODC_TYPE_MC146818)
+                       || ((save_control & RTC_DM_BINARY) == 0)
+                       || RTC_ALWAYS_BCD) {
+               BCD_TO_BIN(sec);
+               BCD_TO_BIN(min);
+               BCD_TO_BIN(hour);
+               BCD_TO_BIN(mday);
+               BCD_TO_BIN(mon);
+               BCD_TO_BIN(year);
+       }
+
+       if ((year + 1900) < 1970) {
+               year += 100;
+       }
+
+       tm->tm_sec = sec;
+       tm->tm_min = min;
+       tm->tm_hour = hour;
+       tm->tm_mday = mday;
+       tm->tm_mon = mon;
+       tm->tm_year = year;
+
+       GregorianDay(tm);
+}
+
+int
+todc_set_rtc_time(struct rtc_time *tm)
+{
+       u_char save_control, save_freq_select = 0;
+
+       spin_lock(&rtc_lock);
+       save_control = todc_read_val(todc_info->control_a);
+
+       /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
+       todc_write_val(todc_info->control_a,
+               (save_control | todc_info->enable_write));
+       save_control &= ~(todc_info->enable_write); /* in case it was set */
+
+       if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+               save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT);
+               todc_write_val(todc_info->RTC_FREQ_SELECT,
+                       save_freq_select | RTC_DIV_RESET2);
+       }
+
+       if ((todc_info->rtc_type != TODC_TYPE_MC146818)
+                       || ((save_control & RTC_DM_BINARY) == 0)
+                       || 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);
+       }
+
+       todc_write_val(todc_info->seconds, tm->tm_sec);
+       todc_write_val(todc_info->minutes, tm->tm_min);
+       todc_write_val(todc_info->hours, tm->tm_hour);
+       todc_write_val(todc_info->month, tm->tm_mon);
+       todc_write_val(todc_info->day_of_month, tm->tm_mday);
+       todc_write_val(todc_info->year, tm->tm_year);
+
+       todc_write_val(todc_info->control_a, save_control);
+
+       if (todc_info->rtc_type == TODC_TYPE_MC146818)
+               todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select);
+
+       spin_unlock(&rtc_lock);
+       return 0;
+}
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
new file mode 100644 (file)
index 0000000..11de090
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * tsi108/109 device setup code
+ *
+ * Maintained by Roy Zang < tie-fei.zang@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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/tsi108.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+static phys_addr_t tsi108_csr_base = -1;
+
+phys_addr_t get_csrbase(void)
+{
+       struct device_node *tsi;
+
+       if (tsi108_csr_base != -1)
+               return tsi108_csr_base;
+
+       tsi = of_find_node_by_type(NULL, "tsi-bridge");
+       if (tsi) {
+               unsigned int size;
+               void *prop = get_property(tsi, "reg", &size);
+               tsi108_csr_base = of_translate_address(tsi, prop);
+               of_node_put(tsi);
+       };
+       return tsi108_csr_base;
+}
+
+u32 get_vir_csrbase(void)
+{
+       return (u32) (ioremap(get_csrbase(), 0x10000));
+}
+
+EXPORT_SYMBOL(get_csrbase);
+EXPORT_SYMBOL(get_vir_csrbase);
+
+static int __init tsi108_eth_of_init(void)
+{
+       struct device_node *np;
+       unsigned int i;
+       struct platform_device *tsi_eth_dev;
+       struct resource res;
+       int ret;
+
+       for (np = NULL, i = 0;
+            (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+            i++) {
+               struct resource r[2];
+               struct device_node *phy;
+               hw_info tsi_eth_data;
+               unsigned int *id;
+               unsigned int *phy_id;
+               void *mac_addr;
+               phandle *ph;
+
+               memset(r, 0, sizeof(r));
+               memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
+
+               ret = of_address_to_resource(np, 0, &r[0]);
+               DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+                       __FUNCTION__,r[0].name, r[0].start, r[0].end);
+               if (ret)
+                       goto err;
+
+               r[1].name = "tx";
+               r[1].start = irq_of_parse_and_map(np, 0);
+               r[1].end = irq_of_parse_and_map(np, 0);
+               r[1].flags = IORESOURCE_IRQ;
+               DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+                       __FUNCTION__,r[1].name, r[1].start, r[1].end);
+
+               tsi_eth_dev =
+                   platform_device_register_simple("tsi-ethernet", i, &r[0],
+                                                   1);
+
+               if (IS_ERR(tsi_eth_dev)) {
+                       ret = PTR_ERR(tsi_eth_dev);
+                       goto err;
+               }
+
+               mac_addr = get_property(np, "address", NULL);
+               memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
+
+               ph = (phandle *) get_property(np, "phy-handle", NULL);
+               phy = of_find_node_by_phandle(*ph);
+
+               if (phy == NULL) {
+                       ret = -ENODEV;
+                       goto unreg;
+               }
+
+               id = (u32 *) get_property(phy, "reg", NULL);
+               phy_id = (u32 *) get_property(phy, "phy-id", NULL);
+               ret = of_address_to_resource(phy, 0, &res);
+               if (ret) {
+                       of_node_put(phy);
+                       goto unreg;
+               }
+               tsi_eth_data.regs = r[0].start;
+               tsi_eth_data.phyregs = res.start;
+               tsi_eth_data.phy = *phy_id;
+               tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
+               of_node_put(phy);
+               ret =
+                   platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
+                                            sizeof(hw_info));
+               if (ret)
+                       goto unreg;
+       }
+       return 0;
+unreg:
+       platform_device_unregister(tsi_eth_dev);
+err:
+       return ret;
+}
+
+arch_initcall(tsi108_eth_of_init);
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
new file mode 100644 (file)
index 0000000..2ab06ed
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * Common routines for Tundra Semiconductor TSI108 host bridge.
+ *
+ * 2004-2005 (c) Tundra Semiconductor Corp.
+ * Author: Alex Bounine (alexandreb@tundra.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/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/tsi108.h>
+#include <asm/tsi108_irq.h>
+#include <asm/prom.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define tsi_mk_config_addr(bus, devfunc, offset) \
+       ((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base)
+
+u32 tsi108_pci_cfg_base;
+u32 tsi108_csr_vir_base;
+
+extern u32 get_vir_csrbase(void);
+extern u32 tsi108_read_reg(u32 reg_offset);
+extern void tsi108_write_reg(u32 reg_offset, u32 val);
+
+int
+tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
+                          int offset, int len, u32 val)
+{
+       volatile unsigned char *cfg_addr;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(bus->number, devfunc))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
+                                                       devfunc, offset) |
+                                                       (offset & 0x03));
+
+#ifdef DEBUG
+       printk("PCI CFG write : ");
+       printk("%d:0x%x:0x%x ", bus->number, devfunc, offset);
+       printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
+       printk("data = 0x%08x\n", val);
+#endif
+
+       switch (len) {
+       case 1:
+               out_8((u8 *) cfg_addr, val);
+               break;
+       case 2:
+               out_le16((u16 *) cfg_addr, val);
+               break;
+       default:
+               out_le32((u32 *) cfg_addr, val);
+               break;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+void tsi108_clear_pci_error(u32 pci_cfg_base)
+{
+       u32 err_stat, err_addr, pci_stat;
+
+       /*
+        * Quietly clear PB and PCI error flags set as result
+        * of PCI/X configuration read requests.
+        */
+
+       /* Read PB Error Log Registers */
+
+       err_stat = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS);
+       err_addr = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_AERR);
+
+       if (err_stat & TSI108_PB_ERRCS_ES) {
+               /* Clear error flag */
+               tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS,
+                                TSI108_PB_ERRCS_ES);
+
+               /* Clear read error reported in PB_ISR */
+               tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ISR,
+                                TSI108_PB_ISR_PBS_RD_ERR);
+
+               /* Clear PCI/X bus cfg errors if applicable */
+               if ((err_addr & 0xFF000000) == pci_cfg_base) {
+                       pci_stat =
+                           tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR);
+                       tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR,
+                                        pci_stat);
+               }
+       }
+
+       return;
+}
+
+#define __tsi108_read_pci_config(x, addr, op)          \
+       __asm__ __volatile__(                           \
+               "       "op" %0,0,%1\n"         \
+               "1:     eieio\n"                        \
+               "2:\n"                                  \
+               ".section .fixup,\"ax\"\n"              \
+               "3:     li %0,-1\n"                     \
+               "       b 2b\n"                         \
+               ".section __ex_table,\"a\"\n"           \
+               "       .align 2\n"                     \
+               "       .long 1b,3b\n"                  \
+               ".text"                                 \
+               : "=r"(x) : "r"(addr))
+
+int
+tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+                         int len, u32 * val)
+{
+       volatile unsigned char *cfg_addr;
+       u32 temp;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(bus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
+                                                       devfn,
+                                                       offset) | (offset &
+                                                                  0x03));
+
+       switch (len) {
+       case 1:
+               __tsi108_read_pci_config(temp, cfg_addr, "lbzx");
+               break;
+       case 2:
+               __tsi108_read_pci_config(temp, cfg_addr, "lhbrx");
+               break;
+       default:
+               __tsi108_read_pci_config(temp, cfg_addr, "lwbrx");
+               break;
+       }
+
+       *val = temp;
+
+#ifdef DEBUG
+       if ((0xFFFFFFFF != temp) && (0xFFFF != temp) && (0xFF != temp)) {
+               printk("PCI CFG read : ");
+               printk("%d:0x%x:0x%x ", bus->number, devfn, offset);
+               printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
+               printk("data = 0x%x\n", *val);
+       }
+#endif
+       return PCIBIOS_SUCCESSFUL;
+}
+
+void tsi108_clear_pci_cfg_error(void)
+{
+       tsi108_clear_pci_error(TSI108_PCI_CFG_BASE_PHYS);
+}
+
+static struct pci_ops tsi108_direct_pci_ops = {
+       tsi108_direct_read_config,
+       tsi108_direct_write_config
+};
+
+int __init tsi108_setup_pci(struct device_node *dev)
+{
+       int len;
+       struct pci_controller *hose;
+       struct resource rsrc;
+       int *bus_range;
+       int primary = 0, has_address = 0;
+
+       /* PCI Config mapping */
+       tsi108_pci_cfg_base = (u32)ioremap(TSI108_PCI_CFG_BASE_PHYS,
+                       TSI108_PCI_CFG_SIZE);
+       DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
+           tsi108_pci_cfg_base);
+
+       /* Fetch host bridge registers address */
+       has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+       /* Get bus range if any */
+       bus_range = (int *)get_property(dev, "bus-range", &len);
+       if (bus_range == NULL || len < 2 * sizeof(int)) {
+               printk(KERN_WARNING "Can't get bus-range for %s, assume"
+                      " bus 0\n", dev->full_name);
+       }
+
+       hose = pcibios_alloc_controller();
+
+       if (!hose) {
+               printk("PCI Host bridge init failed\n");
+               return -ENOMEM;
+       }
+       hose->arch_data = dev;
+       hose->set_cfg_type = 1;
+
+       hose->first_busno = bus_range ? bus_range[0] : 0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+       (hose)->ops = &tsi108_direct_pci_ops;
+
+       printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. "
+              "Firmware bus number: %d->%d\n",
+              rsrc.start, hose->first_busno, hose->last_busno);
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pci_process_bridge_OF_ranges(hose, dev, primary);
+       return 0;
+}
+
+/*
+ * Low level utility functions
+ */
+
+static void tsi108_pci_int_mask(u_int irq)
+{
+       u_int irp_cfg;
+       int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+       irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+       mb();
+       irp_cfg |= (1 << int_line);     /* INTx_DIR = output */
+       irp_cfg &= ~(3 << (8 + (int_line * 2)));        /* INTx_TYPE = unused */
+       tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+       mb();
+       irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+}
+
+static void tsi108_pci_int_unmask(u_int irq)
+{
+       u_int irp_cfg;
+       int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+       irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+       mb();
+       irp_cfg &= ~(1 << int_line);
+       irp_cfg |= (3 << (8 + (int_line * 2)));
+       tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+       mb();
+}
+
+static void init_pci_source(void)
+{
+       tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
+                       0x0000ff00);
+       tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+                       TSI108_PCI_IRP_ENABLE_P_INT);
+       mb();
+}
+
+static inline unsigned int get_pci_source(void)
+{
+       u_int temp = 0;
+       int irq = -1;
+       int i;
+       u_int pci_irp_stat;
+       static int mask = 0;
+
+       /* Read PCI/X block interrupt status register */
+       pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+       mb();
+
+       if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) {
+               /* Process Interrupt from PCI bus INTA# - INTD# lines */
+               temp =
+                   tsi108_read_reg(TSI108_PCI_OFFSET +
+                                   TSI108_PCI_IRP_INTAD) & 0xf;
+               mb();
+               for (i = 0; i < 4; i++, mask++) {
+                       if (temp & (1 << mask % 4)) {
+                               irq = IRQ_PCI_INTA + mask % 4;
+                               mask++;
+                               break;
+                       }
+               }
+
+               /* Disable interrupts from PCI block */
+               temp = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+               tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+                               temp & ~TSI108_PCI_IRP_ENABLE_P_INT);
+               mb();
+               (void)tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+               mb();
+       }
+#ifdef DEBUG
+       else {
+               printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n");
+               pci_irp_stat =
+                   tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+               temp =
+                   tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD);
+               mb();
+               printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp);
+               temp =
+                   tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+               mb();
+               printk("cfg_ctl=0x%08x ", temp);
+               temp =
+                   tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+               mb();
+               printk("irp_enable=0x%08x\n", temp);
+       }
+#endif /* end of DEBUG */
+
+       return irq;
+}
+
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+static void tsi108_pci_irq_enable(u_int irq)
+{
+       tsi108_pci_int_unmask(irq);
+}
+
+static void tsi108_pci_irq_disable(u_int irq)
+{
+       tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_ack(u_int irq)
+{
+       tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_end(u_int irq)
+{
+       tsi108_pci_int_unmask(irq);
+
+       /* Enable interrupts from PCI block */
+       tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+                        tsi108_read_reg(TSI108_PCI_OFFSET +
+                                        TSI108_PCI_IRP_ENABLE) |
+                        TSI108_PCI_IRP_ENABLE_P_INT);
+       mb();
+}
+
+/*
+ * Interrupt controller descriptor for cascaded PCI interrupt controller.
+ */
+
+static struct irq_chip tsi108_pci_irq = {
+       .typename = "tsi108_PCI_int",
+       .mask = tsi108_pci_irq_disable,
+       .ack = tsi108_pci_irq_ack,
+       .end = tsi108_pci_irq_end,
+       .unmask = tsi108_pci_irq_enable,
+};
+
+/*
+ * Exported functions
+ */
+
+/*
+ * The Tsi108 PCI interrupts initialization routine.
+ *
+ * The INTA# - INTD# interrupts on the PCI bus are reported by the PCI block
+ * to the MPIC using single interrupt source (IRQ_TSI108_PCI). Therefore the
+ * PCI block has to be treated as a cascaded interrupt controller connected
+ * to the MPIC.
+ */
+
+void __init tsi108_pci_int_init(void)
+{
+       u_int i;
+
+       DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
+
+       for (i = 0; i < NUM_PCI_IRQS; i++) {
+               irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq;
+               irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
+       }
+
+       init_pci_source();
+}
+
+void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
+                           struct pt_regs *regs)
+{
+       unsigned int cascade_irq = get_pci_source();
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq, regs);
+       desc->chip->eoi(irq);
+}
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile
new file mode 100644 (file)
index 0000000..f4b00cd
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux hypfs filesystem routines.
+#
+
+obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
+
+s390_hypfs-objs := inode.o hypfs_diag.o
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
new file mode 100644 (file)
index 0000000..ea5567b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  fs/hypfs/hypfs.h
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _HYPFS_H_
+#define _HYPFS_H_
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+#define REG_FILE_MODE    0440
+#define UPDATE_FILE_MODE 0220
+#define DIR_MODE         0550
+
+extern struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
+                                 const char *name);
+
+extern struct dentry *hypfs_create_u64(struct super_block *sb,
+                                      struct dentry *dir, const char *name,
+                                      __u64 value);
+
+extern struct dentry *hypfs_create_str(struct super_block *sb,
+                                      struct dentry *dir, const char *name,
+                                      char *string);
+
+#endif /* _HYPFS_H_ */
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
new file mode 100644 (file)
index 0000000..1785bce
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ *  fs/hypfs/hypfs_diag.c
+ *    Hypervisor filesystem for Linux on s390. Diag 204 and 224
+ *    implementation.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+
+#define LPAR_NAME_LEN 8                /* lpar name len in diag 204 data */
+#define CPU_NAME_LEN 16                /* type name len of cpus in diag224 name table */
+#define TMP_SIZE 64            /* size of temporary buffers */
+
+/* diag 204 subcodes */
+enum diag204_sc {
+       SUBC_STIB4 = 4,
+       SUBC_RSI = 5,
+       SUBC_STIB6 = 6,
+       SUBC_STIB7 = 7
+};
+
+/* The two available diag 204 data formats */
+enum diag204_format {
+       INFO_SIMPLE = 0,
+       INFO_EXT = 0x00010000
+};
+
+/* bit is set in flags, when physical cpu info is included in diag 204 data */
+#define LPAR_PHYS_FLG  0x80
+
+static char *diag224_cpu_names;                        /* diag 224 name table */
+static enum diag204_sc diag204_store_sc;       /* used subcode for store */
+static enum diag204_format diag204_info_type;  /* used diag 204 data format */
+
+static void *diag204_buf;              /* 4K aligned buffer for diag204 data */
+static void *diag204_buf_vmalloc;      /* vmalloc pointer for diag204 data */
+static int diag204_buf_pages;          /* number of pages for diag204 data */
+
+/*
+ * DIAG 204 data structures and member access functions.
+ *
+ * Since we have two different diag 204 data formats for old and new s390
+ * machines, we do not access the structs directly, but use getter functions for
+ * each struct member instead. This should make the code more readable.
+ */
+
+/* Time information block */
+
+struct info_blk_hdr {
+       __u8  npar;
+       __u8  flags;
+       __u16 tslice;
+       __u16 phys_cpus;
+       __u16 this_part;
+       __u64 curtod;
+} __attribute__ ((packed));
+
+struct x_info_blk_hdr {
+       __u8  npar;
+       __u8  flags;
+       __u16 tslice;
+       __u16 phys_cpus;
+       __u16 this_part;
+       __u64 curtod1;
+       __u64 curtod2;
+       char reserved[40];
+} __attribute__ ((packed));
+
+static inline int info_blk_hdr__size(enum diag204_format type)
+{
+       if (type == INFO_SIMPLE)
+               return sizeof(struct info_blk_hdr);
+       else /* INFO_EXT */
+               return sizeof(struct x_info_blk_hdr);
+}
+
+static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct info_blk_hdr *)hdr)->npar;
+       else /* INFO_EXT */
+               return ((struct x_info_blk_hdr *)hdr)->npar;
+}
+
+static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct info_blk_hdr *)hdr)->flags;
+       else /* INFO_EXT */
+               return ((struct x_info_blk_hdr *)hdr)->flags;
+}
+
+static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct info_blk_hdr *)hdr)->phys_cpus;
+       else /* INFO_EXT */
+               return ((struct x_info_blk_hdr *)hdr)->phys_cpus;
+}
+
+/* Partition header */
+
+struct part_hdr {
+       __u8 pn;
+       __u8 cpus;
+       char reserved[6];
+       char part_name[LPAR_NAME_LEN];
+} __attribute__ ((packed));
+
+struct x_part_hdr {
+       __u8  pn;
+       __u8  cpus;
+       __u8  rcpus;
+       __u8  pflag;
+       __u32 mlu;
+       char  part_name[LPAR_NAME_LEN];
+       char  lpc_name[8];
+       char  os_name[8];
+       __u64 online_cs;
+       __u64 online_es;
+       __u8  upid;
+       char  reserved1[3];
+       __u32 group_mlu;
+       char  group_name[8];
+       char  reserved2[32];
+} __attribute__ ((packed));
+
+static inline int part_hdr__size(enum diag204_format type)
+{
+       if (type == INFO_SIMPLE)
+               return sizeof(struct part_hdr);
+       else /* INFO_EXT */
+               return sizeof(struct x_part_hdr);
+}
+
+static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct part_hdr *)hdr)->cpus;
+       else /* INFO_EXT */
+               return ((struct x_part_hdr *)hdr)->rcpus;
+}
+
+static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
+                                      char *name)
+{
+       if (type == INFO_SIMPLE)
+               memcpy(name, ((struct part_hdr *)hdr)->part_name,
+                      LPAR_NAME_LEN);
+       else /* INFO_EXT */
+               memcpy(name, ((struct x_part_hdr *)hdr)->part_name,
+                      LPAR_NAME_LEN);
+       EBCASC(name, LPAR_NAME_LEN);
+       name[LPAR_NAME_LEN] = 0;
+       strstrip(name);
+}
+
+struct cpu_info {
+       __u16 cpu_addr;
+       char  reserved1[2];
+       __u8  ctidx;
+       __u8  cflag;
+       __u16 weight;
+       __u64 acc_time;
+       __u64 lp_time;
+} __attribute__ ((packed));
+
+struct x_cpu_info {
+       __u16 cpu_addr;
+       char  reserved1[2];
+       __u8  ctidx;
+       __u8  cflag;
+       __u16 weight;
+       __u64 acc_time;
+       __u64 lp_time;
+       __u16 min_weight;
+       __u16 cur_weight;
+       __u16 max_weight;
+       char  reseved2[2];
+       __u64 online_time;
+       __u64 wait_time;
+       __u32 pma_weight;
+       __u32 polar_weight;
+       char  reserved3[40];
+} __attribute__ ((packed));
+
+/* CPU info block */
+
+static inline int cpu_info__size(enum diag204_format type)
+{
+       if (type == INFO_SIMPLE)
+               return sizeof(struct cpu_info);
+       else /* INFO_EXT */
+               return sizeof(struct x_cpu_info);
+}
+
+static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct cpu_info *)hdr)->ctidx;
+       else /* INFO_EXT */
+               return ((struct x_cpu_info *)hdr)->ctidx;
+}
+
+static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct cpu_info *)hdr)->cpu_addr;
+       else /* INFO_EXT */
+               return ((struct x_cpu_info *)hdr)->cpu_addr;
+}
+
+static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct cpu_info *)hdr)->acc_time;
+       else /* INFO_EXT */
+               return ((struct x_cpu_info *)hdr)->acc_time;
+}
+
+static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct cpu_info *)hdr)->lp_time;
+       else /* INFO_EXT */
+               return ((struct x_cpu_info *)hdr)->lp_time;
+}
+
+static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return 0;       /* online_time not available in simple info */
+       else /* INFO_EXT */
+               return ((struct x_cpu_info *)hdr)->online_time;
+}
+
+/* Physical header */
+
+struct phys_hdr {
+       char reserved1[1];
+       __u8 cpus;
+       char reserved2[6];
+       char mgm_name[8];
+} __attribute__ ((packed));
+
+struct x_phys_hdr {
+       char reserved1[1];
+       __u8 cpus;
+       char reserved2[6];
+       char mgm_name[8];
+       char reserved3[80];
+} __attribute__ ((packed));
+
+static inline int phys_hdr__size(enum diag204_format type)
+{
+       if (type == INFO_SIMPLE)
+               return sizeof(struct phys_hdr);
+       else /* INFO_EXT */
+               return sizeof(struct x_phys_hdr);
+}
+
+static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct phys_hdr *)hdr)->cpus;
+       else /* INFO_EXT */
+               return ((struct x_phys_hdr *)hdr)->cpus;
+}
+
+/* Physical CPU info block */
+
+struct phys_cpu {
+       __u16 cpu_addr;
+       char  reserved1[2];
+       __u8  ctidx;
+       char  reserved2[3];
+       __u64 mgm_time;
+       char  reserved3[8];
+} __attribute__ ((packed));
+
+struct x_phys_cpu {
+       __u16 cpu_addr;
+       char  reserved1[2];
+       __u8  ctidx;
+       char  reserved2[3];
+       __u64 mgm_time;
+       char  reserved3[80];
+} __attribute__ ((packed));
+
+static inline int phys_cpu__size(enum diag204_format type)
+{
+       if (type == INFO_SIMPLE)
+               return sizeof(struct phys_cpu);
+       else /* INFO_EXT */
+               return sizeof(struct x_phys_cpu);
+}
+
+static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct phys_cpu *)hdr)->cpu_addr;
+       else /* INFO_EXT */
+               return ((struct x_phys_cpu *)hdr)->cpu_addr;
+}
+
+static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct phys_cpu *)hdr)->mgm_time;
+       else /* INFO_EXT */
+               return ((struct x_phys_cpu *)hdr)->mgm_time;
+}
+
+static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
+{
+       if (type == INFO_SIMPLE)
+               return ((struct phys_cpu *)hdr)->ctidx;
+       else /* INFO_EXT */
+               return ((struct x_phys_cpu *)hdr)->ctidx;
+}
+
+/* Diagnose 204 functions */
+
+static int diag204(unsigned long subcode, unsigned long size, void *addr)
+{
+       register unsigned long _subcode asm("0") = subcode;
+       register unsigned long _size asm("1") = size;
+
+       asm volatile ("   diag    %2,%0,0x204\n"
+                     "0: \n" ".section __ex_table,\"a\"\n"
+#ifndef __s390x__
+                     "    .align 4\n"
+                     "    .long  0b,0b\n"
+#else
+                     "    .align 8\n"
+                     "    .quad  0b,0b\n"
+#endif
+                     ".previous":"+d" (_subcode), "+d"(_size)
+                     :"d"(addr)
+                     :"memory");
+       if (_subcode)
+               return -1;
+       else
+               return _size;
+}
+
+/*
+ * For the old diag subcode 4 with simple data format we have to use real
+ * memory. If we use subcode 6 or 7 with extended data format, we can (and
+ * should) use vmalloc, since we need a lot of memory in that case. Currently
+ * up to 93 pages!
+ */
+
+static void diag204_free_buffer(void)
+{
+       if (!diag204_buf)
+               return;
+       if (diag204_buf_vmalloc) {
+               vfree(diag204_buf_vmalloc);
+               diag204_buf_vmalloc = NULL;
+       } else {
+               free_pages((unsigned long) diag204_buf, 0);
+       }
+       diag204_buf_pages = 0;
+       diag204_buf = NULL;
+}
+
+static void *diag204_alloc_vbuf(int pages)
+{
+       /* The buffer has to be page aligned! */
+       diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));
+       if (!diag204_buf_vmalloc)
+               return ERR_PTR(-ENOMEM);
+       diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc
+                               & ~0xfffUL) + 0x1000;
+       diag204_buf_pages = pages;
+       return diag204_buf;
+}
+
+static void *diag204_alloc_rbuf(void)
+{
+       diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
+       if (diag204_buf)
+               return ERR_PTR(-ENOMEM);
+       diag204_buf_pages = 1;
+       return diag204_buf;
+}
+
+static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
+{
+       if (diag204_buf) {
+               *pages = diag204_buf_pages;
+               return diag204_buf;
+       }
+       if (fmt == INFO_SIMPLE) {
+               *pages = 1;
+               return diag204_alloc_rbuf();
+       } else {/* INFO_EXT */
+               *pages = diag204(SUBC_RSI | INFO_EXT, 0, NULL);
+               if (*pages <= 0)
+                       return ERR_PTR(-ENOSYS);
+               else
+                       return diag204_alloc_vbuf(*pages);
+       }
+}
+
+/*
+ * diag204_probe() has to find out, which type of diagnose 204 implementation
+ * we have on our machine. Currently there are three possible scanarios:
+ *   - subcode 4   + simple data format (only one page)
+ *   - subcode 4-6 + extended data format
+ *   - subcode 4-7 + extended data format
+ *
+ * Subcode 5 is used to retrieve the size of the data, provided by subcodes
+ * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition
+ * to subcode 6 it provides also information about secondary cpus.
+ * In order to get as much information as possible, we first try
+ * subcode 7, then 6 and if both fail, we use subcode 4.
+ */
+
+static int diag204_probe(void)
+{
+       void *buf;
+       int pages, rc;
+
+       buf = diag204_get_buffer(INFO_EXT, &pages);
+       if (!IS_ERR(buf)) {
+               if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) {
+                       diag204_store_sc = SUBC_STIB7;
+                       diag204_info_type = INFO_EXT;
+                       goto out;
+               }
+               if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) {
+                       diag204_store_sc = SUBC_STIB7;
+                       diag204_info_type = INFO_EXT;
+                       goto out;
+               }
+               diag204_free_buffer();
+       }
+
+       /* subcodes 6 and 7 failed, now try subcode 4 */
+
+       buf = diag204_get_buffer(INFO_SIMPLE, &pages);
+       if (IS_ERR(buf)) {
+               rc = PTR_ERR(buf);
+               goto fail_alloc;
+       }
+       if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) {
+               diag204_store_sc = SUBC_STIB4;
+               diag204_info_type = INFO_SIMPLE;
+               goto out;
+       } else {
+               rc = -ENOSYS;
+               goto fail_store;
+       }
+out:
+       rc = 0;
+fail_store:
+       diag204_free_buffer();
+fail_alloc:
+       return rc;
+}
+
+static void *diag204_store(void)
+{
+       void *buf;
+       int pages;
+
+       buf = diag204_get_buffer(diag204_info_type, &pages);
+       if (IS_ERR(buf))
+               goto out;
+       if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0)
+               return ERR_PTR(-ENOSYS);
+out:
+       return buf;
+}
+
+/* Diagnose 224 functions */
+
+static void diag224(void *ptr)
+{
+       asm volatile("   diag    %0,%1,0x224\n"
+                    : :"d" (0), "d"(ptr) : "memory");
+}
+
+static int diag224_get_name_table(void)
+{
+       /* memory must be below 2GB */
+       diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+       if (!diag224_cpu_names)
+               return -ENOMEM;
+       diag224(diag224_cpu_names);
+       EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
+       return 0;
+}
+
+static void diag224_delete_name_table(void)
+{
+       kfree(diag224_cpu_names);
+}
+
+static int diag224_idx2name(int index, char *name)
+{
+       memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),
+               CPU_NAME_LEN);
+       name[CPU_NAME_LEN] = 0;
+       strstrip(name);
+       return 0;
+}
+
+__init int hypfs_diag_init(void)
+{
+       int rc;
+
+       if (diag204_probe()) {
+               printk(KERN_ERR "hypfs: diag 204 not working.");
+               return -ENODATA;
+       }
+       rc = diag224_get_name_table();
+       if (rc) {
+               diag224_delete_name_table();
+               printk(KERN_ERR "hypfs: could not get name table.\n");
+       }
+       return rc;
+}
+
+__exit void hypfs_diag_exit(void)
+{
+       diag224_delete_name_table();
+       diag204_free_buffer();
+}
+
+/*
+ * Functions to create the directory structure
+ * *******************************************
+ */
+
+static int hypfs_create_cpu_files(struct super_block *sb,
+                                 struct dentry *cpus_dir, void *cpu_info)
+{
+       struct dentry *cpu_dir;
+       char buffer[TMP_SIZE];
+       void *rc;
+
+       snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,
+                                                           cpu_info));
+       cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+       rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+                             cpu_info__acc_time(diag204_info_type, cpu_info) -
+                             cpu_info__lp_time(diag204_info_type, cpu_info));
+       if (IS_ERR(rc))
+               return PTR_ERR(rc);
+       rc = hypfs_create_u64(sb, cpu_dir, "cputime",
+                             cpu_info__lp_time(diag204_info_type, cpu_info));
+       if (IS_ERR(rc))
+               return PTR_ERR(rc);
+       if (diag204_info_type == INFO_EXT) {
+               rc = hypfs_create_u64(sb, cpu_dir, "onlinetime",
+                                     cpu_info__online_time(diag204_info_type,
+                                                           cpu_info));
+               if (IS_ERR(rc))
+                       return PTR_ERR(rc);
+       }
+       diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
+       rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
+       if (IS_ERR(rc))
+               return PTR_ERR(rc);
+       return 0;
+}
+
+static void *hypfs_create_lpar_files(struct super_block *sb,
+                                    struct dentry *systems_dir, void *part_hdr)
+{
+       struct dentry *cpus_dir;
+       struct dentry *lpar_dir;
+       char lpar_name[LPAR_NAME_LEN + 1];
+       void *cpu_info;
+       int i;
+
+       part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
+       lpar_name[LPAR_NAME_LEN] = 0;
+       lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name);
+       if (IS_ERR(lpar_dir))
+               return lpar_dir;
+       cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus");
+       if (IS_ERR(cpus_dir))
+               return cpus_dir;
+       cpu_info = part_hdr + part_hdr__size(diag204_info_type);
+       for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
+               int rc;
+               rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);
+               if (rc)
+                       return ERR_PTR(rc);
+               cpu_info += cpu_info__size(diag204_info_type);
+       }
+       return cpu_info;
+}
+
+static int hypfs_create_phys_cpu_files(struct super_block *sb,
+                                      struct dentry *cpus_dir, void *cpu_info)
+{
+       struct dentry *cpu_dir;
+       char buffer[TMP_SIZE];
+       void *rc;
+
+       snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,
+                                                           cpu_info));
+       cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+       if (IS_ERR(cpu_dir))
+               return PTR_ERR(cpu_dir);
+       rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+                             phys_cpu__mgm_time(diag204_info_type, cpu_info));
+       if (IS_ERR(rc))
+               return PTR_ERR(rc);
+       diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
+       rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
+       if (IS_ERR(rc))
+               return PTR_ERR(rc);
+       return 0;
+}
+
+static void *hypfs_create_phys_files(struct super_block *sb,
+                                    struct dentry *parent_dir, void *phys_hdr)
+{
+       int i;
+       void *cpu_info;
+       struct dentry *cpus_dir;
+
+       cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus");
+       if (IS_ERR(cpus_dir))
+               return cpus_dir;
+       cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
+       for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
+               int rc;
+               rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);
+               if (rc)
+                       return ERR_PTR(rc);
+               cpu_info += phys_cpu__size(diag204_info_type);
+       }
+       return cpu_info;
+}
+
+int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
+{
+       struct dentry *systems_dir, *hyp_dir;
+       void *time_hdr, *part_hdr;
+       int i, rc;
+       void *buffer, *ptr;
+
+       buffer = diag204_store();
+       if (IS_ERR(buffer))
+               return PTR_ERR(buffer);
+
+       systems_dir = hypfs_mkdir(sb, root, "systems");
+       if (IS_ERR(systems_dir)) {
+               rc = PTR_ERR(systems_dir);
+               goto err_out;
+       }
+       time_hdr = (struct x_info_blk_hdr *)buffer;
+       part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
+       for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
+               part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);
+               if (IS_ERR(part_hdr)) {
+                       rc = PTR_ERR(part_hdr);
+                       goto err_out;
+               }
+       }
+       if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) {
+               ptr = hypfs_create_phys_files(sb, root, part_hdr);
+               if (IS_ERR(ptr)) {
+                       rc = PTR_ERR(ptr);
+                       goto err_out;
+               }
+       }
+       hyp_dir = hypfs_mkdir(sb, root, "hyp");
+       if (IS_ERR(hyp_dir)) {
+               rc = PTR_ERR(hyp_dir);
+               goto err_out;
+       }
+       ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor");
+       if (IS_ERR(ptr)) {
+               rc = PTR_ERR(ptr);
+               goto err_out;
+       }
+       rc = 0;
+
+err_out:
+       return rc;
+}
diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h
new file mode 100644 (file)
index 0000000..793dea6
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  fs/hypfs/hypfs_diag.h
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _HYPFS_DIAG_H_
+#define _HYPFS_DIAG_H_
+
+extern int hypfs_diag_init(void);
+extern void hypfs_diag_exit(void);
+extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
+
+#endif /* _HYPFS_DIAG_H_ */
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
new file mode 100644 (file)
index 0000000..666b946
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ *  fs/hypfs/inode.c
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/vfs.h>
+#include <linux/pagemap.h>
+#include <linux/gfp.h>
+#include <linux/time.h>
+#include <linux/parser.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+#include "hypfs_diag.h"
+
+#define HYPFS_MAGIC 0x687970   /* ASCII 'hyp' */
+#define TMP_SIZE 64            /* size of temporary buffers */
+
+static struct dentry *hypfs_create_update_file(struct super_block *sb,
+                                              struct dentry *dir);
+
+struct hypfs_sb_info {
+       uid_t uid;                      /* uid used for files and dirs */
+       gid_t gid;                      /* gid used for files and dirs */
+       struct dentry *update_file;     /* file to trigger update */
+       time_t last_update;             /* last update time in secs since 1970 */
+       struct mutex lock;              /* lock to protect update process */
+};
+
+static struct file_operations hypfs_file_ops;
+static struct file_system_type hypfs_type;
+static struct super_operations hypfs_s_ops;
+
+/* start of list of all dentries, which have to be deleted on update */
+static struct dentry *hypfs_last_dentry;
+
+static void hypfs_update_update(struct super_block *sb)
+{
+       struct hypfs_sb_info *sb_info = sb->s_fs_info;
+       struct inode *inode = sb_info->update_file->d_inode;
+
+       sb_info->last_update = get_seconds();
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+/* directory tree removal functions */
+
+static void hypfs_add_dentry(struct dentry *dentry)
+{
+       dentry->d_fsdata = hypfs_last_dentry;
+       hypfs_last_dentry = dentry;
+}
+
+static void hypfs_remove(struct dentry *dentry)
+{
+       struct dentry *parent;
+
+       parent = dentry->d_parent;
+       if (S_ISDIR(dentry->d_inode->i_mode))
+               simple_rmdir(parent->d_inode, dentry);
+       else
+               simple_unlink(parent->d_inode, dentry);
+       d_delete(dentry);
+       dput(dentry);
+}
+
+static void hypfs_delete_tree(struct dentry *root)
+{
+       while (hypfs_last_dentry) {
+               struct dentry *next_dentry;
+               next_dentry = hypfs_last_dentry->d_fsdata;
+               hypfs_remove(hypfs_last_dentry);
+               hypfs_last_dentry = next_dentry;
+       }
+}
+
+static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
+{
+       struct inode *ret = new_inode(sb);
+
+       if (ret) {
+               struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+               ret->i_mode = mode;
+               ret->i_uid = hypfs_info->uid;
+               ret->i_gid = hypfs_info->gid;
+               ret->i_blocks = 0;
+               ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+               if (mode & S_IFDIR)
+                       ret->i_nlink = 2;
+               else
+                       ret->i_nlink = 1;
+       }
+       return ret;
+}
+
+static void hypfs_drop_inode(struct inode *inode)
+{
+       kfree(inode->i_private);
+       generic_delete_inode(inode);
+}
+
+static int hypfs_open(struct inode *inode, struct file *filp)
+{
+       char *data = filp->f_dentry->d_inode->i_private;
+       struct hypfs_sb_info *fs_info;
+
+       if (filp->f_mode & FMODE_WRITE) {
+               if (!(inode->i_mode & S_IWUGO))
+                       return -EACCES;
+       }
+       if (filp->f_mode & FMODE_READ) {
+               if (!(inode->i_mode & S_IRUGO))
+                       return -EACCES;
+       }
+
+       fs_info = inode->i_sb->s_fs_info;
+       if(data) {
+               mutex_lock(&fs_info->lock);
+               filp->private_data = kstrdup(data, GFP_KERNEL);
+               if (!filp->private_data) {
+                       mutex_unlock(&fs_info->lock);
+                       return -ENOMEM;
+               }
+               mutex_unlock(&fs_info->lock);
+       }
+       return 0;
+}
+
+static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
+                             size_t count, loff_t offset)
+{
+       char *data;
+       size_t len;
+       struct file *filp = iocb->ki_filp;
+
+       data = filp->private_data;
+       len = strlen(data);
+       if (offset > len) {
+               count = 0;
+               goto out;
+       }
+       if (count > len - offset)
+               count = len - offset;
+       if (copy_to_user(buf, data + offset, count)) {
+               count = -EFAULT;
+               goto out;
+       }
+       iocb->ki_pos += count;
+       file_accessed(filp);
+out:
+       return count;
+}
+static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf,
+                              size_t count, loff_t pos)
+{
+       int rc;
+       struct super_block *sb;
+       struct hypfs_sb_info *fs_info;
+
+       sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
+       fs_info = sb->s_fs_info;
+       /*
+        * Currently we only allow one update per second for two reasons:
+        * 1. diag 204 is VERY expensive
+        * 2. If several processes do updates in parallel and then read the
+        *    hypfs data, the likelihood of collisions is reduced, if we restrict
+        *    the minimum update interval. A collision occurs, if during the
+        *    data gathering of one process another process triggers an update
+        *    If the first process wants to ensure consistent data, it has
+        *    to restart data collection in this case.
+        */
+       mutex_lock(&fs_info->lock);
+       if (fs_info->last_update == get_seconds()) {
+               rc = -EBUSY;
+               goto out;
+       }
+       hypfs_delete_tree(sb->s_root);
+       rc = hypfs_diag_create_files(sb, sb->s_root);
+       if (rc) {
+               printk(KERN_ERR "hypfs: Update failed\n");
+               hypfs_delete_tree(sb->s_root);
+               goto out;
+       }
+       hypfs_update_update(sb);
+       rc = count;
+out:
+       mutex_unlock(&fs_info->lock);
+       return rc;
+}
+
+static int hypfs_release(struct inode *inode, struct file *filp)
+{
+       kfree(filp->private_data);
+       return 0;
+}
+
+enum { opt_uid, opt_gid, opt_err };
+
+static match_table_t hypfs_tokens = {
+       {opt_uid, "uid=%u"},
+       {opt_gid, "gid=%u"},
+       {opt_err, NULL}
+};
+
+static int hypfs_parse_options(char *options, struct super_block *sb)
+{
+       char *str;
+       substring_t args[MAX_OPT_ARGS];
+
+       if (!options)
+               return 0;
+       while ((str = strsep(&options, ",")) != NULL) {
+               int token, option;
+               struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+
+               if (!*str)
+                       continue;
+               token = match_token(str, hypfs_tokens, args);
+               switch (token) {
+               case opt_uid:
+                       if (match_int(&args[0], &option))
+                               return -EINVAL;
+                       hypfs_info->uid = option;
+                       break;
+               case opt_gid:
+                       if (match_int(&args[0], &option))
+                               return -EINVAL;
+                       hypfs_info->gid = option;
+                       break;
+               case opt_err:
+               default:
+                       printk(KERN_ERR "hypfs: Unrecognized mount option "
+                              "\"%s\" or missing value\n", str);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct inode *root_inode;
+       struct dentry *root_dentry;
+       int rc = 0;
+       struct hypfs_sb_info *sbi;
+
+       sbi = kzalloc(sizeof(struct hypfs_sb_info), GFP_KERNEL);
+       if (!sbi)
+               return -ENOMEM;
+       mutex_init(&sbi->lock);
+       sbi->uid = current->uid;
+       sbi->gid = current->gid;
+       sb->s_fs_info = sbi;
+       sb->s_blocksize = PAGE_CACHE_SIZE;
+       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+       sb->s_magic = HYPFS_MAGIC;
+       sb->s_op = &hypfs_s_ops;
+       if (hypfs_parse_options(data, sb)) {
+               rc = -EINVAL;
+               goto err_alloc;
+       }
+       root_inode = hypfs_make_inode(sb, S_IFDIR | 0755);
+       if (!root_inode) {
+               rc = -ENOMEM;
+               goto err_alloc;
+       }
+       root_inode->i_op = &simple_dir_inode_operations;
+       root_inode->i_fop = &simple_dir_operations;
+       root_dentry = d_alloc_root(root_inode);
+       if (!root_dentry) {
+               iput(root_inode);
+               rc = -ENOMEM;
+               goto err_alloc;
+       }
+       rc = hypfs_diag_create_files(sb, root_dentry);
+       if (rc)
+               goto err_tree;
+       sbi->update_file = hypfs_create_update_file(sb, root_dentry);
+       if (IS_ERR(sbi->update_file)) {
+               rc = PTR_ERR(sbi->update_file);
+               goto err_tree;
+       }
+       hypfs_update_update(sb);
+       sb->s_root = root_dentry;
+       return 0;
+
+err_tree:
+       hypfs_delete_tree(root_dentry);
+       d_genocide(root_dentry);
+       dput(root_dentry);
+err_alloc:
+       kfree(sbi);
+       return rc;
+}
+
+static int hypfs_get_super(struct file_system_type *fst, int flags,
+                       const char *devname, void *data, struct vfsmount *mnt)
+{
+       return get_sb_single(fst, flags, data, hypfs_fill_super, mnt);
+}
+
+static void hypfs_kill_super(struct super_block *sb)
+{
+       struct hypfs_sb_info *sb_info = sb->s_fs_info;
+
+       hypfs_delete_tree(sb->s_root);
+       hypfs_remove(sb_info->update_file);
+       kfree(sb->s_fs_info);
+       sb->s_fs_info = NULL;
+       kill_litter_super(sb);
+}
+
+static struct dentry *hypfs_create_file(struct super_block *sb,
+                                       struct dentry *parent, const char *name,
+                                       char *data, mode_t mode)
+{
+       struct dentry *dentry;
+       struct inode *inode;
+       struct qstr qname;
+
+       qname.name = name;
+       qname.len = strlen(name);
+       qname.hash = full_name_hash(name, qname.len);
+       dentry = lookup_one_len(name, parent, strlen(name));
+       if (IS_ERR(dentry))
+               return ERR_PTR(-ENOMEM);
+       inode = hypfs_make_inode(sb, mode);
+       if (!inode) {
+               dput(dentry);
+               return ERR_PTR(-ENOMEM);
+       }
+       if (mode & S_IFREG) {
+               inode->i_fop = &hypfs_file_ops;
+               if (data)
+                       inode->i_size = strlen(data);
+               else
+                       inode->i_size = 0;
+       } else if (mode & S_IFDIR) {
+               inode->i_op = &simple_dir_inode_operations;
+               inode->i_fop = &simple_dir_operations;
+               parent->d_inode->i_nlink++;
+       } else
+               BUG();
+       inode->i_private = data;
+       d_instantiate(dentry, inode);
+       dget(dentry);
+       return dentry;
+}
+
+struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
+                          const char *name)
+{
+       struct dentry *dentry;
+
+       dentry = hypfs_create_file(sb, parent, name, NULL, S_IFDIR | DIR_MODE);
+       if (IS_ERR(dentry))
+               return dentry;
+       hypfs_add_dentry(dentry);
+       parent->d_inode->i_nlink++;
+       return dentry;
+}
+
+static struct dentry *hypfs_create_update_file(struct super_block *sb,
+                                              struct dentry *dir)
+{
+       struct dentry *dentry;
+
+       dentry = hypfs_create_file(sb, dir, "update", NULL,
+                                  S_IFREG | UPDATE_FILE_MODE);
+       /*
+        * We do not put the update file on the 'delete' list with
+        * hypfs_add_dentry(), since it should not be removed when the tree
+        * is updated.
+        */
+       return dentry;
+}
+
+struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir,
+                               const char *name, __u64 value)
+{
+       char *buffer;
+       char tmp[TMP_SIZE];
+       struct dentry *dentry;
+
+       snprintf(tmp, TMP_SIZE, "%lld\n", (unsigned long long int)value);
+       buffer = kstrdup(tmp, GFP_KERNEL);
+       if (!buffer)
+               return ERR_PTR(-ENOMEM);
+       dentry =
+           hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+       if (IS_ERR(dentry)) {
+               kfree(buffer);
+               return ERR_PTR(-ENOMEM);
+       }
+       hypfs_add_dentry(dentry);
+       return dentry;
+}
+
+struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir,
+                               const char *name, char *string)
+{
+       char *buffer;
+       struct dentry *dentry;
+
+       buffer = kmalloc(strlen(string) + 2, GFP_KERNEL);
+       if (!buffer)
+               return ERR_PTR(-ENOMEM);
+       sprintf(buffer, "%s\n", string);
+       dentry =
+           hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+       if (IS_ERR(dentry)) {
+               kfree(buffer);
+               return ERR_PTR(-ENOMEM);
+       }
+       hypfs_add_dentry(dentry);
+       return dentry;
+}
+
+static struct file_operations hypfs_file_ops = {
+       .open           = hypfs_open,
+       .release        = hypfs_release,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .aio_read       = hypfs_aio_read,
+       .aio_write      = hypfs_aio_write,
+};
+
+static struct file_system_type hypfs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "s390_hypfs",
+       .get_sb         = hypfs_get_super,
+       .kill_sb        = hypfs_kill_super
+};
+
+static struct super_operations hypfs_s_ops = {
+       .statfs         = simple_statfs,
+       .drop_inode     = hypfs_drop_inode,
+};
+
+static decl_subsys(s390, NULL, NULL);
+
+static int __init hypfs_init(void)
+{
+       int rc;
+
+       if (MACHINE_IS_VM)
+               return -ENODATA;
+       if (hypfs_diag_init()) {
+               rc = -ENODATA;
+               goto fail_diag;
+       }
+       kset_set_kset_s(&s390_subsys, hypervisor_subsys);
+       rc = subsystem_register(&s390_subsys);
+       if (rc)
+               goto fail_sysfs;
+       rc = register_filesystem(&hypfs_type);
+       if (rc)
+               goto fail_filesystem;
+       return 0;
+
+fail_filesystem:
+       subsystem_unregister(&s390_subsys);
+fail_sysfs:
+       hypfs_diag_exit();
+fail_diag:
+       printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc);
+       return rc;
+}
+
+static void __exit hypfs_exit(void)
+{
+       hypfs_diag_exit();
+       unregister_filesystem(&hypfs_type);
+       subsystem_unregister(&s390_subsys);
+}
+
+module_init(hypfs_init)
+module_exit(hypfs_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Holzheu <holzheu@de.ibm.com>");
+MODULE_DESCRIPTION("s390 Hypervisor Filesystem");
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c
new file mode 100644 (file)
index 0000000..0741d91
--- /dev/null
@@ -0,0 +1,66 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_COMPAT
+       extern int s390_classify_syscall(unsigned);
+       if (abi == AUDIT_ARCH_S390)
+               return s390_classify_syscall(syscall);
+#endif
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 0;
+       }
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_COMPAT
+       extern __u32 s390_dir_class[];
+       extern __u32 s390_write_class[];
+       extern __u32 s390_read_class[];
+       extern __u32 s390_chattr_class[];
+       audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
+       audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
+#endif
+       audit_register_class(AUDIT_CLASS_WRITE, write_class);
+       audit_register_class(AUDIT_CLASS_READ, read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+       return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c
new file mode 100644 (file)
index 0000000..16d9436
--- /dev/null
@@ -0,0 +1,38 @@
+#undef __s390x__
+#include <asm/unistd.h>
+
+unsigned s390_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned s390_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned s390_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned s390_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int s390_classify_syscall(unsigned syscall)
+{
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 1;
+       }
+}
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..d9428a0
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * arch/s390/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ *  Copyright (C) IBM Corp. 2006
+ *  Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/kallsyms.h>
+
+static inline unsigned long save_context_stack(struct stack_trace *trace,
+                                              unsigned int *skip,
+                                              unsigned long sp,
+                                              unsigned long low,
+                                              unsigned long high)
+{
+       struct stack_frame *sf;
+       struct pt_regs *regs;
+       unsigned long addr;
+
+       while(1) {
+               sp &= PSW_ADDR_INSN;
+               if (sp < low || sp > high)
+                       return sp;
+               sf = (struct stack_frame *)sp;
+               while(1) {
+                       addr = sf->gprs[8] & PSW_ADDR_INSN;
+                       if (!(*skip))
+                               trace->entries[trace->nr_entries++] = addr;
+                       else
+                               (*skip)--;
+                       if (trace->nr_entries >= trace->max_entries)
+                               return sp;
+                       low = sp;
+                       sp = sf->back_chain & PSW_ADDR_INSN;
+                       if (!sp)
+                               break;
+                       if (sp <= low || sp > high - sizeof(*sf))
+                               return sp;
+                       sf = (struct stack_frame *)sp;
+               }
+               /* Zero backchain detected, check for interrupt frame. */
+               sp = (unsigned long)(sf + 1);
+               if (sp <= low || sp > high - sizeof(*regs))
+                       return sp;
+               regs = (struct pt_regs *)sp;
+               addr = regs->psw.addr & PSW_ADDR_INSN;
+               if (!(*skip))
+                       trace->entries[trace->nr_entries++] = addr;
+               else
+                       (*skip)--;
+               if (trace->nr_entries >= trace->max_entries)
+                       return sp;
+               low = sp;
+               sp = regs->gprs[15];
+       }
+}
+
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+       register unsigned long sp asm ("15");
+       unsigned long orig_sp;
+
+       sp &= PSW_ADDR_INSN;
+       orig_sp = sp;
+
+       sp = save_context_stack(trace, &trace->skip, sp,
+                               S390_lowcore.panic_stack - PAGE_SIZE,
+                               S390_lowcore.panic_stack);
+       if ((sp != orig_sp) && !trace->all_contexts)
+               return;
+       sp = save_context_stack(trace, &trace->skip, sp,
+                               S390_lowcore.async_stack - ASYNC_SIZE,
+                               S390_lowcore.async_stack);
+       if ((sp != orig_sp) && !trace->all_contexts)
+               return;
+       if (task)
+               save_context_stack(trace, &trace->skip, sp,
+                                  (unsigned long) task_stack_page(task),
+                                  (unsigned long) task_stack_page(task) + THREAD_SIZE);
+       else
+               save_context_stack(trace, &trace->skip, sp,
+                                  S390_lowcore.thread_info,
+                                  S390_lowcore.thread_info + THREAD_SIZE);
+       return;
+}
diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c
new file mode 100644 (file)
index 0000000..0481f34
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *  arch/s390/lib/div64.c
+ *
+ *  __div64_32 implementation for 31 bit.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_MARCH_G5
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 31 bit integer using signed 64/32 bit division.
+ */
+static uint32_t __div64_31(uint64_t *n, uint32_t base)
+{
+       register uint32_t reg2 asm("2");
+       register uint32_t reg3 asm("3");
+       uint32_t *words = (uint32_t *) n;
+       uint32_t tmp;
+
+       /* Special case base==1, remainder = 0, quotient = n */
+       if (base == 1)
+               return 0;
+       /*
+        * Special case base==0 will cause a fixed point divide exception
+        * on the dr instruction and may not happen anyway. For the
+        * following calculation we can assume base > 1. The first
+        * signed 64 / 32 bit division with an upper half of 0 will
+        * give the correct upper half of the 64 bit quotient.
+        */
+       reg2 = 0UL;
+       reg3 = words[0];
+       asm volatile(
+               "       dr      %0,%2\n"
+               : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+       words[0] = reg3;
+       reg3 = words[1];
+       /*
+        * To get the lower half of the 64 bit quotient and the 32 bit
+        * remainder we have to use a little trick. Since we only have
+        * a signed division the quotient can get too big. To avoid this
+        * the 64 bit dividend is halved, then the signed division will
+        * work. Afterwards the quotient and the remainder are doubled.
+        * If the last bit of the dividend has been one the remainder
+        * is increased by one then checked against the base. If the
+        * remainder has overflown subtract base and increase the
+        * quotient. Simple, no ?
+        */
+       asm volatile(
+               "       nr      %2,%1\n"
+               "       srdl    %0,1\n"
+               "       dr      %0,%3\n"
+               "       alr     %0,%0\n"
+               "       alr     %1,%1\n"
+               "       alr     %0,%2\n"
+               "       clr     %0,%3\n"
+               "       jl      0f\n"
+               "       slr     %0,%3\n"
+               "       alr     %1,%2\n"
+               "0:\n"
+               : "+d" (reg2), "+d" (reg3), "=d" (tmp)
+               : "d" (base), "2" (1UL) : "cc" );
+       words[1] = reg3;
+       return reg2;
+}
+
+/*
+ * Function to divide an unsigned 64 bit integer by an unsigned
+ * 32 bit integer using the unsigned 64/31 bit division.
+ */
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+       uint32_t r;
+
+       /*
+        * If the most significant bit of base is set, divide n by
+        * (base/2). That allows to use 64/31 bit division and gives a
+        * good approximation of the result: n = (base/2)*q + r. The
+        * result needs to be corrected with two simple transformations.
+        * If base is already < 2^31-1 __div64_31 can be used directly.
+        */
+       r = __div64_31(n, ((signed) base < 0) ? (base/2) : base);
+       if ((signed) base < 0) {
+               uint64_t q = *n;
+               /*
+                * First transformation:
+                * n = (base/2)*q + r
+                *   = ((base/2)*2)*(q/2) + ((q&1) ? (base/2) : 0) + r
+                * Since r < (base/2), r + (base/2) < base.
+                * With q1 = (q/2) and r1 = r + ((q&1) ? (base/2) : 0)
+                * n = ((base/2)*2)*q1 + r1 with r1 < base.
+                */
+               if (q & 1)
+                       r += base/2;
+               q >>= 1;
+               /*
+                * Second transformation. ((base/2)*2) could have lost the
+                * last bit.
+                * n = ((base/2)*2)*q1 + r1
+                *   = base*q1 - ((base&1) ? q1 : 0) + r1
+                */
+               if (base & 1) {
+                       int64_t rx = r - q;
+                       /*
+                        * base is >= 2^31. The worst case for the while
+                        * loop is n=2^64-1 base=2^31+1. That gives a
+                        * maximum for q=(2^64-1)/2^31 = 0x1ffffffff. Since
+                        * base >= 2^31 the loop is finished after a maximum
+                        * of three iterations.
+                        */
+                       while (rx < 0) {
+                               rx += base;
+                               q--;
+                       }
+                       r = rx;
+               }
+               *n = q;
+       }
+       return r;
+}
+
+#else /* MARCH_G5 */
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+       register uint32_t reg2 asm("2");
+       register uint32_t reg3 asm("3");
+       uint32_t *words = (uint32_t *) n;
+
+       reg2 = 0UL;
+       reg3 = words[0];
+       asm volatile(
+               "       dlr     %0,%2\n"
+               : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+       words[0] = reg3;
+       reg3 = words[1];
+       asm volatile(
+               "       dlr     %0,%2\n"
+               : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" );
+       words[1] = reg3;
+       return reg2;
+}
+
+#endif /* MARCH_G5 */
+
+EXPORT_SYMBOL(__div64_32);
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
new file mode 100644 (file)
index 0000000..74bef2a
--- /dev/null
@@ -0,0 +1,823 @@
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+                                       const struct of_device *dev)
+{
+       if (!dev->node)
+               return NULL;
+       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+               int match = 1;
+               if (matches->name[0])
+                       match &= dev->node->name
+                               && !strcmp(matches->name, dev->node->name);
+               if (matches->type[0])
+                       match &= dev->node->type
+                               && !strcmp(matches->type, dev->node->type);
+               if (matches->compatible[0])
+                       match &= of_device_is_compatible(dev->node,
+                                                        matches->compatible);
+               if (match)
+                       return matches;
+               matches++;
+       }
+       return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+       const struct of_device_id * matches = of_drv->match_table;
+
+       if (!matches)
+               return 0;
+
+       return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+       struct device *tmp;
+
+       if (!dev)
+               return NULL;
+       tmp = get_device(&dev->dev);
+       if (tmp)
+               return to_of_device(tmp);
+       else
+               return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+       if (dev)
+               put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+       int error = -ENODEV;
+       struct of_platform_driver *drv;
+       struct of_device *of_dev;
+       const struct of_device_id *match;
+
+       drv = to_of_platform_driver(dev->driver);
+       of_dev = to_of_device(dev);
+
+       if (!drv->probe)
+               return error;
+
+       of_dev_get(of_dev);
+
+       match = of_match_device(drv->match_table, of_dev);
+       if (match)
+               error = drv->probe(of_dev, match);
+       if (error)
+               of_dev_put(of_dev);
+
+       return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+       if (dev->driver && drv->remove)
+               drv->remove(of_dev);
+       return 0;
+}
+
+static int of_device_suspend(struct device *dev, pm_message_t state)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+       int error = 0;
+
+       if (dev->driver && drv->suspend)
+               error = drv->suspend(of_dev, state);
+       return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+       int error = 0;
+
+       if (dev->driver && drv->resume)
+               error = drv->resume(of_dev);
+       return error;
+}
+
+static int node_match(struct device *dev, void *data)
+{
+       struct of_device *op = to_of_device(dev);
+       struct device_node *dp = data;
+
+       return (op->node == dp);
+}
+
+struct of_device *of_find_device_by_node(struct device_node *dp)
+{
+       struct device *dev = bus_find_device(&of_bus_type, NULL,
+                                            dp, node_match);
+
+       if (dev)
+               return to_of_device(dev);
+
+       return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_node);
+
+#ifdef CONFIG_PCI
+struct bus_type ebus_bus_type = {
+       .name   = "ebus",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(ebus_bus_type);
+#endif
+
+#ifdef CONFIG_SBUS
+struct bus_type sbus_bus_type = {
+       .name   = "sbus",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(sbus_bus_type);
+#endif
+
+struct bus_type of_bus_type = {
+       .name   = "of",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(of_bus_type);
+
+static inline u64 of_read_addr(const u32 *cell, int size)
+{
+       u64 r = 0;
+       while (size--)
+               r = (r << 32) | *(cell++);
+       return r;
+}
+
+static void __init get_cells(struct device_node *dp,
+                            int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = of_n_addr_cells(dp);
+       if (sizec)
+               *sizec = of_n_size_cells(dp);
+}
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS      4
+
+struct of_bus {
+       const char      *name;
+       const char      *addr_prop_name;
+       int             (*match)(struct device_node *parent);
+       void            (*count_cells)(struct device_node *child,
+                                      int *addrc, int *sizec);
+       int             (*map)(u32 *addr, const u32 *range,
+                              int na, int ns, int pna);
+       unsigned int    (*get_flags)(u32 *addr);
+};
+
+/*
+ * Default translator (generic bus)
+ */
+
+static void of_bus_default_count_cells(struct device_node *dev,
+                                      int *addrc, int *sizec)
+{
+       get_cells(dev, addrc, sizec);
+}
+
+/* Make sure the least significant 64-bits are in-range.  Even
+ * for 3 or 4 cell values it is a good enough approximation.
+ */
+static int of_out_of_range(const u32 *addr, const u32 *base,
+                          const u32 *size, int na, int ns)
+{
+       u64 a = of_read_addr(addr, na);
+       u64 b = of_read_addr(base, na);
+
+       if (a < b)
+               return 1;
+
+       b += of_read_addr(size, ns);
+       if (a >= b)
+               return 1;
+
+       return 0;
+}
+
+static int of_bus_default_map(u32 *addr, const u32 *range,
+                             int na, int ns, int pna)
+{
+       u32 result[OF_MAX_ADDR_CELLS];
+       int i;
+
+       if (ns > 2) {
+               printk("of_device: Cannot handle size cells (%d) > 2.", ns);
+               return -EINVAL;
+       }
+
+       if (of_out_of_range(addr, range, range + na + pna, na, ns))
+               return -EINVAL;
+
+       /* Start with the parent range base.  */
+       memcpy(result, range + na, pna * 4);
+
+       /* Add in the child address offset.  */
+       for (i = 0; i < na; i++)
+               result[pna - 1 - i] +=
+                       (addr[na - 1 - i] -
+                        range[na - 1 - i]);
+
+       memcpy(addr, result, pna * 4);
+
+       return 0;
+}
+
+static unsigned int of_bus_default_get_flags(u32 *addr)
+{
+       return IORESOURCE_MEM;
+}
+
+/*
+ * PCI bus specific translator
+ */
+
+static int of_bus_pci_match(struct device_node *np)
+{
+       if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+               /* Do not do PCI specific frobbing if the
+                * PCI bridge lacks a ranges property.  We
+                * want to pass it through up to the next
+                * parent as-is, not with the PCI translate
+                * method which chops off the top address cell.
+                */
+               if (!of_find_property(np, "ranges", NULL))
+                       return 0;
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static void of_bus_pci_count_cells(struct device_node *np,
+                                  int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = 3;
+       if (sizec)
+               *sizec = 2;
+}
+
+static int of_bus_pci_map(u32 *addr, const u32 *range,
+                         int na, int ns, int pna)
+{
+       u32 result[OF_MAX_ADDR_CELLS];
+       int i;
+
+       /* Check address type match */
+       if ((addr[0] ^ range[0]) & 0x03000000)
+               return -EINVAL;
+
+       if (of_out_of_range(addr + 1, range + 1, range + na + pna,
+                           na - 1, ns))
+               return -EINVAL;
+
+       /* Start with the parent range base.  */
+       memcpy(result, range + na, pna * 4);
+
+       /* Add in the child address offset, skipping high cell.  */
+       for (i = 0; i < na - 1; i++)
+               result[pna - 1 - i] +=
+                       (addr[na - 1 - i] -
+                        range[na - 1 - i]);
+
+       memcpy(addr, result, pna * 4);
+
+       return 0;
+}
+
+static unsigned int of_bus_pci_get_flags(u32 *addr)
+{
+       unsigned int flags = 0;
+       u32 w = addr[0];
+
+       switch((w >> 24) & 0x03) {
+       case 0x01:
+               flags |= IORESOURCE_IO;
+       case 0x02: /* 32 bits */
+       case 0x03: /* 64 bits */
+               flags |= IORESOURCE_MEM;
+       }
+       if (w & 0x40000000)
+               flags |= IORESOURCE_PREFETCH;
+       return flags;
+}
+
+/*
+ * SBUS bus specific translator
+ */
+
+static int of_bus_sbus_match(struct device_node *np)
+{
+       return !strcmp(np->name, "sbus") ||
+               !strcmp(np->name, "sbi");
+}
+
+static void of_bus_sbus_count_cells(struct device_node *child,
+                                  int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = 2;
+       if (sizec)
+               *sizec = 1;
+}
+
+static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+{
+       return of_bus_default_map(addr, range, na, ns, pna);
+}
+
+static unsigned int of_bus_sbus_get_flags(u32 *addr)
+{
+       return IORESOURCE_MEM;
+}
+
+
+/*
+ * Array of bus specific translators
+ */
+
+static struct of_bus of_busses[] = {
+       /* PCI */
+       {
+               .name = "pci",
+               .addr_prop_name = "assigned-addresses",
+               .match = of_bus_pci_match,
+               .count_cells = of_bus_pci_count_cells,
+               .map = of_bus_pci_map,
+               .get_flags = of_bus_pci_get_flags,
+       },
+       /* SBUS */
+       {
+               .name = "sbus",
+               .addr_prop_name = "reg",
+               .match = of_bus_sbus_match,
+               .count_cells = of_bus_sbus_count_cells,
+               .map = of_bus_sbus_map,
+               .get_flags = of_bus_sbus_get_flags,
+       },
+       /* Default */
+       {
+               .name = "default",
+               .addr_prop_name = "reg",
+               .match = NULL,
+               .count_cells = of_bus_default_count_cells,
+               .map = of_bus_default_map,
+               .get_flags = of_bus_default_get_flags,
+       },
+};
+
+static struct of_bus *of_match_bus(struct device_node *np)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(of_busses); i ++)
+               if (!of_busses[i].match || of_busses[i].match(np))
+                       return &of_busses[i];
+       BUG();
+       return NULL;
+}
+
+static int __init build_one_resource(struct device_node *parent,
+                                    struct of_bus *bus,
+                                    struct of_bus *pbus,
+                                    u32 *addr,
+                                    int na, int ns, int pna)
+{
+       u32 *ranges;
+       unsigned int rlen;
+       int rone;
+
+       ranges = of_get_property(parent, "ranges", &rlen);
+       if (ranges == NULL || rlen == 0) {
+               u32 result[OF_MAX_ADDR_CELLS];
+               int i;
+
+               memset(result, 0, pna * 4);
+               for (i = 0; i < na; i++)
+                       result[pna - 1 - i] =
+                               addr[na - 1 - i];
+
+               memcpy(addr, result, pna * 4);
+               return 0;
+       }
+
+       /* Now walk through the ranges */
+       rlen /= 4;
+       rone = na + pna + ns;
+       for (; rlen >= rone; rlen -= rone, ranges += rone) {
+               if (!bus->map(addr, ranges, na, ns, pna))
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int of_resource_verbose;
+
+static void __init build_device_resources(struct of_device *op,
+                                         struct device *parent)
+{
+       struct of_device *p_op;
+       struct of_bus *bus;
+       int na, ns;
+       int index, num_reg;
+       void *preg;
+
+       if (!parent)
+               return;
+
+       p_op = to_of_device(parent);
+       bus = of_match_bus(p_op->node);
+       bus->count_cells(op->node, &na, &ns);
+
+       preg = of_get_property(op->node, bus->addr_prop_name, &num_reg);
+       if (!preg || num_reg == 0)
+               return;
+
+       /* Convert to num-cells.  */
+       num_reg /= 4;
+
+       /* Conver to num-entries.  */
+       num_reg /= na + ns;
+
+       for (index = 0; index < num_reg; index++) {
+               struct resource *r = &op->resource[index];
+               u32 addr[OF_MAX_ADDR_CELLS];
+               u32 *reg = (preg + (index * ((na + ns) * 4)));
+               struct device_node *dp = op->node;
+               struct device_node *pp = p_op->node;
+               struct of_bus *pbus;
+               u64 size, result = OF_BAD_ADDR;
+               unsigned long flags;
+               int dna, dns;
+               int pna, pns;
+
+               size = of_read_addr(reg + na, ns);
+               flags = bus->get_flags(reg);
+
+               memcpy(addr, reg, na * 4);
+
+               /* If the immediate parent has no ranges property to apply,
+                * just use a 1<->1 mapping.
+                */
+               if (of_find_property(pp, "ranges", NULL) == NULL) {
+                       result = of_read_addr(addr, na);
+                       goto build_res;
+               }
+
+               dna = na;
+               dns = ns;
+
+               while (1) {
+                       dp = pp;
+                       pp = dp->parent;
+                       if (!pp) {
+                               result = of_read_addr(addr, dna);
+                               break;
+                       }
+
+                       pbus = of_match_bus(pp);
+                       pbus->count_cells(dp, &pna, &pns);
+
+                       if (build_one_resource(dp, bus, pbus, addr,
+                                              dna, dns, pna))
+                               break;
+
+                       dna = pna;
+                       dns = pns;
+                       bus = pbus;
+               }
+
+       build_res:
+               memset(r, 0, sizeof(*r));
+
+               if (of_resource_verbose)
+                       printk("%s reg[%d] -> %llx\n",
+                              op->node->full_name, index,
+                              result);
+
+               if (result != OF_BAD_ADDR) {
+                       r->start = result & 0xffffffff;
+                       r->end = result + size - 1;
+                       r->flags = flags | ((result >> 32ULL) & 0xffUL);
+               } else {
+                       r->start = ~0UL;
+                       r->end = ~0UL;
+               }
+               r->name = op->node->name;
+       }
+}
+
+static struct of_device * __init scan_one_device(struct device_node *dp,
+                                                struct device *parent)
+{
+       struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
+       struct linux_prom_irqs *intr;
+       int len, i;
+
+       if (!op)
+               return NULL;
+
+       op->node = dp;
+
+       op->clock_freq = of_getintprop_default(dp, "clock-frequency",
+                                              (25*1000*1000));
+       op->portid = of_getintprop_default(dp, "upa-portid", -1);
+       if (op->portid == -1)
+               op->portid = of_getintprop_default(dp, "portid", -1);
+
+       intr = of_get_property(dp, "intr", &len);
+       if (intr) {
+               op->num_irqs = len / sizeof(struct linux_prom_irqs);
+               for (i = 0; i < op->num_irqs; i++)
+                       op->irqs[i] = intr[i].pri;
+       } else {
+               unsigned int *irq = of_get_property(dp, "interrupts", &len);
+
+               if (irq) {
+                       op->num_irqs = len / sizeof(unsigned int);
+                       for (i = 0; i < op->num_irqs; i++)
+                               op->irqs[i] = irq[i];
+               } else {
+                       op->num_irqs = 0;
+               }
+       }
+       if (sparc_cpu_model == sun4d) {
+               static int pil_to_sbus[] = {
+                       0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
+               };
+               struct device_node *io_unit, *sbi = dp->parent;
+               struct linux_prom_registers *regs;
+               int board, slot;
+
+               while (sbi) {
+                       if (!strcmp(sbi->name, "sbi"))
+                               break;
+
+                       sbi = sbi->parent;
+               }
+               if (!sbi)
+                       goto build_resources;
+
+               regs = of_get_property(dp, "reg", NULL);
+               if (!regs)
+                       goto build_resources;
+
+               slot = regs->which_io;
+
+               /* If SBI's parent is not io-unit or the io-unit lacks
+                * a "board#" property, something is very wrong.
+                */
+               if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
+                       printk("%s: Error, parent is not io-unit.\n",
+                              sbi->full_name);
+                       goto build_resources;
+               }
+               io_unit = sbi->parent;
+               board = of_getintprop_default(io_unit, "board#", -1);
+               if (board == -1) {
+                       printk("%s: Error, lacks board# property.\n",
+                              io_unit->full_name);
+                       goto build_resources;
+               }
+
+               for (i = 0; i < op->num_irqs; i++) {
+                       int this_irq = op->irqs[i];
+                       int sbusl = pil_to_sbus[this_irq];
+
+                       if (sbusl)
+                               this_irq = (((board + 1) << 5) +
+                                           (sbusl << 2) +
+                                           slot);
+
+                       op->irqs[i] = this_irq;
+               }
+       }
+
+build_resources:
+       build_device_resources(op, parent);
+
+       op->dev.parent = parent;
+       op->dev.bus = &of_bus_type;
+       if (!parent)
+               strcpy(op->dev.bus_id, "root");
+       else
+               strcpy(op->dev.bus_id, dp->path_component_name);
+
+       if (of_device_register(op)) {
+               printk("%s: Could not register of device.\n",
+                      dp->full_name);
+               kfree(op);
+               op = NULL;
+       }
+
+       return op;
+}
+
+static void __init scan_tree(struct device_node *dp, struct device *parent)
+{
+       while (dp) {
+               struct of_device *op = scan_one_device(dp, parent);
+
+               if (op)
+                       scan_tree(dp->child, &op->dev);
+
+               dp = dp->sibling;
+       }
+}
+
+static void __init scan_of_devices(void)
+{
+       struct device_node *root = of_find_node_by_path("/");
+       struct of_device *parent;
+
+       parent = scan_one_device(root, NULL);
+       if (!parent)
+               return;
+
+       scan_tree(root->child, &parent->dev);
+}
+
+static int __init of_bus_driver_init(void)
+{
+       int err;
+
+       err = bus_register(&of_bus_type);
+#ifdef CONFIG_PCI
+       if (!err)
+               err = bus_register(&ebus_bus_type);
+#endif
+#ifdef CONFIG_SBUS
+       if (!err)
+               err = bus_register(&sbus_bus_type);
+#endif
+
+       if (!err)
+               scan_of_devices();
+
+       return err;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+static int __init of_debug(char *str)
+{
+       int val = 0;
+
+       get_option(&str, &val);
+       if (val & 1)
+               of_resource_verbose = 1;
+       return 1;
+}
+
+__setup("of_debug=", of_debug);
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+       /* initialize common driver fields */
+       drv->driver.name = drv->name;
+       drv->driver.bus = bus;
+
+       /* register with core */
+       return driver_register(&drv->driver);
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct of_device *ofdev;
+
+       ofdev = to_of_device(dev);
+       return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+       struct of_device *ofdev;
+
+        ofdev = to_of_device(dev);
+
+       kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+       int rc;
+
+       BUG_ON(ofdev->node == NULL);
+
+       rc = device_register(&ofdev->dev);
+       if (rc)
+               return rc;
+
+       rc = device_create_file(&ofdev->dev, &dev_attr_devspec);
+       if (rc)
+               device_unregister(&ofdev->dev);
+
+       return rc;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+       device_remove_file(&ofdev->dev, &dev_attr_devspec);
+       device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+                                           const char *bus_id,
+                                           struct device *parent,
+                                           struct bus_type *bus)
+{
+       struct of_device *dev;
+
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+       memset(dev, 0, sizeof(*dev));
+
+       dev->dev.parent = parent;
+       dev->dev.bus = bus;
+       dev->dev.release = of_release_dev;
+
+       strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+       if (of_device_register(dev) != 0) {
+               kfree(dev);
+               return NULL;
+       }
+
+       return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
new file mode 100644 (file)
index 0000000..4ca9e5f
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras      August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc32 by David S. Miller davem@davemloft.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/oplib.h>
+
+static struct device_node *allnodes;
+
+/* use when traversing tree through the allnext, child, sibling,
+ * or parent members of struct device_node.
+ */
+static DEFINE_RWLOCK(devtree_lock);
+
+int of_device_is_compatible(struct device_node *device, const char *compat)
+{
+       const char* cp;
+       int cplen, l;
+
+       cp = (char *) of_get_property(device, "compatible", &cplen);
+       if (cp == NULL)
+               return 0;
+       while (cplen > 0) {
+               if (strncmp(cp, compat, strlen(compat)) == 0)
+                       return 1;
+               l = strlen(cp) + 1;
+               cp += l;
+               cplen -= l;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(of_device_is_compatible);
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+       struct device_node *np;
+
+       if (!node)
+               return NULL;
+
+       np = node->parent;
+
+       return np;
+}
+EXPORT_SYMBOL(of_get_parent);
+
+struct device_node *of_get_next_child(const struct device_node *node,
+       struct device_node *prev)
+{
+       struct device_node *next;
+
+       next = prev ? prev->sibling : node->child;
+       for (; next != 0; next = next->sibling) {
+               break;
+       }
+
+       return next;
+}
+EXPORT_SYMBOL(of_get_next_child);
+
+struct device_node *of_find_node_by_path(const char *path)
+{
+       struct device_node *np = allnodes;
+
+       for (; np != 0; np = np->allnext) {
+               if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
+                       break;
+       }
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_path);
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+       struct device_node *np;
+
+       for (np = allnodes; np != 0; np = np->allnext)
+               if (np->node == handle)
+                       break;
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+struct device_node *of_find_node_by_name(struct device_node *from,
+       const char *name)
+{
+       struct device_node *np;
+
+       np = from ? from->allnext : allnodes;
+       for (; np != NULL; np = np->allnext)
+               if (np->name != NULL && strcmp(np->name, name) == 0)
+                       break;
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_name);
+
+struct device_node *of_find_node_by_type(struct device_node *from,
+       const char *type)
+{
+       struct device_node *np;
+
+       np = from ? from->allnext : allnodes;
+       for (; np != 0; np = np->allnext)
+               if (np->type != 0 && strcmp(np->type, type) == 0)
+                       break;
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_type);
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+       const char *type, const char *compatible)
+{
+       struct device_node *np;
+
+       np = from ? from->allnext : allnodes;
+       for (; np != 0; np = np->allnext) {
+               if (type != NULL
+                   && !(np->type != 0 && strcmp(np->type, type) == 0))
+                       continue;
+               if (of_device_is_compatible(np, compatible))
+                       break;
+       }
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_compatible_node);
+
+struct property *of_find_property(struct device_node *np, const char *name,
+                                 int *lenp)
+{
+       struct property *pp;
+
+       for (pp = np->properties; pp != 0; pp = pp->next) {
+               if (strcmp(pp->name, name) == 0) {
+                       if (lenp != 0)
+                               *lenp = pp->length;
+                       break;
+               }
+       }
+       return pp;
+}
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+       struct property *pp = of_find_property(np,name,lenp);
+       return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+       struct property *prop;
+       int len;
+
+       prop = of_find_property(np, name, &len);
+       if (!prop || len != 4)
+               return def;
+
+       return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+int of_n_addr_cells(struct device_node *np)
+{
+       int* ip;
+       do {
+               if (np->parent)
+                       np = np->parent;
+               ip = of_get_property(np, "#address-cells", NULL);
+               if (ip != NULL)
+                       return *ip;
+       } while (np->parent);
+       /* No #address-cells property for the root node, default to 2 */
+       return 2;
+}
+EXPORT_SYMBOL(of_n_addr_cells);
+
+int of_n_size_cells(struct device_node *np)
+{
+       int* ip;
+       do {
+               if (np->parent)
+                       np = np->parent;
+               ip = of_get_property(np, "#size-cells", NULL);
+               if (ip != NULL)
+                       return *ip;
+       } while (np->parent);
+       /* No #size-cells property for the root node, default to 1 */
+       return 1;
+}
+EXPORT_SYMBOL(of_n_size_cells);
+
+int of_set_property(struct device_node *dp, const char *name, void *val, int len)
+{
+       struct property **prevp;
+       void *new_val;
+       int err;
+
+       new_val = kmalloc(len, GFP_KERNEL);
+       if (!new_val)
+               return -ENOMEM;
+
+       memcpy(new_val, val, len);
+
+       err = -ENODEV;
+
+       write_lock(&devtree_lock);
+       prevp = &dp->properties;
+       while (*prevp) {
+               struct property *prop = *prevp;
+
+               if (!strcmp(prop->name, name)) {
+                       void *old_val = prop->value;
+                       int ret;
+
+                       ret = prom_setprop(dp->node, name, val, len);
+                       err = -EINVAL;
+                       if (ret >= 0) {
+                               prop->value = new_val;
+                               prop->length = len;
+
+                               if (OF_IS_DYNAMIC(prop))
+                                       kfree(old_val);
+
+                               OF_MARK_DYNAMIC(prop);
+
+                               err = 0;
+                       }
+                       break;
+               }
+               prevp = &(*prevp)->next;
+       }
+       write_unlock(&devtree_lock);
+
+       /* XXX Upate procfs if necessary... */
+
+       return err;
+}
+EXPORT_SYMBOL(of_set_property);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+       void *ret;
+
+       ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+       if (ret != NULL)
+               memset(ret, 0, size);
+
+       prom_early_allocated += size;
+
+       return ret;
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+       if (!dp)
+               return 0;
+
+       return (dp->parent == NULL);
+}
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ */
+static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom_registers *regs;
+       struct property *rprop;
+
+       rprop = of_find_property(dp, "reg", NULL);
+       if (!rprop)
+               return;
+
+       regs = rprop->value;
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name,
+               regs->which_io, regs->phys_addr);
+}
+
+/* "name@slot,offset"  */
+static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom_registers *regs;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name,
+               regs->which_io,
+               regs->phys_addr);
+}
+
+/* "name@devnum[,func]" */
+static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom_pci_registers *regs;
+       struct property *prop;
+       unsigned int devfn;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+       devfn = (regs->phys_hi >> 8) & 0xff;
+       if (devfn & 0x07) {
+               sprintf(tmp_buf, "%s@%x,%x",
+                       dp->name,
+                       devfn >> 3,
+                       devfn & 0x07);
+       } else {
+               sprintf(tmp_buf, "%s@%x",
+                       dp->name,
+                       devfn >> 3);
+       }
+}
+
+/* "name@addrhi,addrlo" */
+static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom_registers *regs;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name,
+               regs->which_io, regs->phys_addr);
+}
+
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct device_node *parent = dp->parent;
+
+       if (parent != NULL) {
+               if (!strcmp(parent->type, "pci") ||
+                   !strcmp(parent->type, "pciex"))
+                       return pci_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "sbus"))
+                       return sbus_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "ebus"))
+                       return ebus_path_component(dp, tmp_buf);
+
+               /* "isa" is handled with platform naming */
+       }
+
+       /* Use platform naming convention.  */
+       return sparc32_path_component(dp, tmp_buf);
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+       char tmp_buf[64], *n;
+
+       tmp_buf[0] = '\0';
+       __build_path_component(dp, tmp_buf);
+       if (tmp_buf[0] == '\0')
+               strcpy(tmp_buf, dp->name);
+
+       n = prom_early_alloc(strlen(tmp_buf) + 1);
+       strcpy(n, tmp_buf);
+
+       return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+       int len, ourlen, plen;
+       char *n;
+
+       plen = strlen(dp->parent->full_name);
+       ourlen = strlen(dp->path_component_name);
+       len = ourlen + plen + 2;
+
+       n = prom_early_alloc(len);
+       strcpy(n, dp->parent->full_name);
+       if (!is_root_node(dp->parent)) {
+               strcpy(n + plen, "/");
+               plen++;
+       }
+       strcpy(n + plen, dp->path_component_name);
+
+       return n;
+}
+
+static unsigned int unique_id;
+
+static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
+{
+       static struct property *tmp = NULL;
+       struct property *p;
+       int len;
+       const char *name;
+
+       if (tmp) {
+               p = tmp;
+               memset(p, 0, sizeof(*p) + 32);
+               tmp = NULL;
+       } else {
+               p = prom_early_alloc(sizeof(struct property) + 32);
+               p->unique_id = unique_id++;
+       }
+
+       p->name = (char *) (p + 1);
+       if (special_name) {
+               strcpy(p->name, special_name);
+               p->length = special_len;
+               p->value = prom_early_alloc(special_len);
+               memcpy(p->value, special_val, special_len);
+       } else {
+               if (prev == NULL) {
+                       name = prom_firstprop(node, NULL);
+               } else {
+                       name = prom_nextprop(node, prev, NULL);
+               }
+               if (strlen(name) == 0) {
+                       tmp = p;
+                       return NULL;
+               }
+               strcpy(p->name, name);
+               p->length = prom_getproplen(node, p->name);
+               if (p->length <= 0) {
+                       p->length = 0;
+               } else {
+                       p->value = prom_early_alloc(p->length + 1);
+                       prom_getproperty(node, p->name, p->value, p->length);
+                       ((unsigned char *)p->value)[p->length] = '\0';
+               }
+       }
+       return p;
+}
+
+static struct property * __init build_prop_list(phandle node)
+{
+       struct property *head, *tail;
+
+       head = tail = build_one_prop(node, NULL,
+                                    ".node", &node, sizeof(node));
+
+       tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
+       tail = tail->next;
+       while(tail) {
+               tail->next = build_one_prop(node, tail->name,
+                                           NULL, NULL, 0);
+               tail = tail->next;
+       }
+
+       return head;
+}
+
+static char * __init get_one_property(phandle node, char *name)
+{
+       char *buf = "<NULL>";
+       int len;
+
+       len = prom_getproplen(node, name);
+       if (len > 0) {
+               buf = prom_early_alloc(len);
+               len = prom_getproperty(node, name, buf, len);
+       }
+
+       return buf;
+}
+
+static struct device_node * __init create_node(phandle node)
+{
+       struct device_node *dp;
+
+       if (!node)
+               return NULL;
+
+       dp = prom_early_alloc(sizeof(*dp));
+       dp->unique_id = unique_id++;
+
+       kref_init(&dp->kref);
+
+       dp->name = get_one_property(node, "name");
+       dp->type = get_one_property(node, "device_type");
+       dp->node = node;
+
+       /* Build interrupts later... */
+
+       dp->properties = build_prop_list(node);
+
+       return dp;
+}
+
+static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
+{
+       struct device_node *dp;
+
+       dp = create_node(node);
+       if (dp) {
+               *(*nextp) = dp;
+               *nextp = &dp->allnext;
+
+               dp->parent = parent;
+               dp->path_component_name = build_path_component(dp);
+               dp->full_name = build_full_name(dp);
+
+               dp->child = build_tree(dp, prom_getchild(node), nextp);
+
+               dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+       }
+
+       return dp;
+}
+
+void __init prom_build_devicetree(void)
+{
+       struct device_node **nextp;
+
+       allnodes = create_node(prom_root_node);
+       allnodes->path_component_name = "";
+       allnodes->full_name = "/";
+
+       nextp = &allnodes->allnext;
+       allnodes->child = build_tree(allnodes,
+                                    prom_getchild(allnodes->node),
+                                    &nextp);
+       printk("PROM: Built device tree with %u bytes of memory.\n",
+              prom_early_allocated);
+}
diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c
new file mode 100644 (file)
index 0000000..54501c1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Implement the sparc iomap interfaces
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       return (void __iomem *) (unsigned long) port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+       /* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (!len || !start)
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM) {
+               if (flags & IORESOURCE_CACHEABLE)
+                       return ioremap(start, len);
+               return ioremap_nocache(start, len);
+       }
+       /* What? */
+       return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+       /* nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c
new file mode 100644 (file)
index 0000000..aef19cc
--- /dev/null
@@ -0,0 +1,66 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_SPARC32_COMPAT
+       extern int sparc32_classify_syscall(unsigned);
+       if (abi == AUDIT_ARCH_SPARC)
+               return sparc32_classify_syscall(syscall);
+#endif
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 0;
+       }
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_SPARC32_COMPAT
+       extern __u32 sparc32_dir_class[];
+       extern __u32 sparc32_write_class[];
+       extern __u32 sparc32_read_class[];
+       extern __u32 sparc32_chattr_class[];
+       audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class);
+       audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class);
+#endif
+       audit_register_class(AUDIT_CLASS_WRITE, write_class);
+       audit_register_class(AUDIT_CLASS_READ, read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+       return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/sparc64/kernel/compat_audit.c b/arch/sparc64/kernel/compat_audit.c
new file mode 100644 (file)
index 0000000..cca96c9
--- /dev/null
@@ -0,0 +1,37 @@
+#include <asm-sparc/unistd.h>
+
+unsigned sparc32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned sparc32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned sparc32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned sparc32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int sparc32_classify_syscall(unsigned syscall)
+{
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 1;
+       }
+}
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
new file mode 100644 (file)
index 0000000..8c7c500
--- /dev/null
@@ -0,0 +1,1032 @@
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+                                       const struct of_device *dev)
+{
+       if (!dev->node)
+               return NULL;
+       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+               int match = 1;
+               if (matches->name[0])
+                       match &= dev->node->name
+                               && !strcmp(matches->name, dev->node->name);
+               if (matches->type[0])
+                       match &= dev->node->type
+                               && !strcmp(matches->type, dev->node->type);
+               if (matches->compatible[0])
+                       match &= of_device_is_compatible(dev->node,
+                                                        matches->compatible);
+               if (match)
+                       return matches;
+               matches++;
+       }
+       return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+       const struct of_device_id * matches = of_drv->match_table;
+
+       if (!matches)
+               return 0;
+
+       return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+       struct device *tmp;
+
+       if (!dev)
+               return NULL;
+       tmp = get_device(&dev->dev);
+       if (tmp)
+               return to_of_device(tmp);
+       else
+               return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+       if (dev)
+               put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+       int error = -ENODEV;
+       struct of_platform_driver *drv;
+       struct of_device *of_dev;
+       const struct of_device_id *match;
+
+       drv = to_of_platform_driver(dev->driver);
+       of_dev = to_of_device(dev);
+
+       if (!drv->probe)
+               return error;
+
+       of_dev_get(of_dev);
+
+       match = of_match_device(drv->match_table, of_dev);
+       if (match)
+               error = drv->probe(of_dev, match);
+       if (error)
+               of_dev_put(of_dev);
+
+       return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+       if (dev->driver && drv->remove)
+               drv->remove(of_dev);
+       return 0;
+}
+
+static int of_device_suspend(struct device *dev, pm_message_t state)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+       int error = 0;
+
+       if (dev->driver && drv->suspend)
+               error = drv->suspend(of_dev, state);
+       return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+       struct of_device * of_dev = to_of_device(dev);
+       struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+       int error = 0;
+
+       if (dev->driver && drv->resume)
+               error = drv->resume(of_dev);
+       return error;
+}
+
+void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name)
+{
+       unsigned long ret = res->start + offset;
+
+       if (!request_region(ret, size, name))
+               ret = 0;
+
+       return (void __iomem *) ret;
+}
+EXPORT_SYMBOL(of_ioremap);
+
+void of_iounmap(void __iomem *base, unsigned long size)
+{
+       release_region((unsigned long) base, size);
+}
+EXPORT_SYMBOL(of_iounmap);
+
+static int node_match(struct device *dev, void *data)
+{
+       struct of_device *op = to_of_device(dev);
+       struct device_node *dp = data;
+
+       return (op->node == dp);
+}
+
+struct of_device *of_find_device_by_node(struct device_node *dp)
+{
+       struct device *dev = bus_find_device(&of_bus_type, NULL,
+                                            dp, node_match);
+
+       if (dev)
+               return to_of_device(dev);
+
+       return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_node);
+
+#ifdef CONFIG_PCI
+struct bus_type isa_bus_type = {
+       .name   = "isa",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(isa_bus_type);
+
+struct bus_type ebus_bus_type = {
+       .name   = "ebus",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(ebus_bus_type);
+#endif
+
+#ifdef CONFIG_SBUS
+struct bus_type sbus_bus_type = {
+       .name   = "sbus",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(sbus_bus_type);
+#endif
+
+struct bus_type of_bus_type = {
+       .name   = "of",
+       .match  = of_platform_bus_match,
+       .probe  = of_device_probe,
+       .remove = of_device_remove,
+       .suspend        = of_device_suspend,
+       .resume = of_device_resume,
+};
+EXPORT_SYMBOL(of_bus_type);
+
+static inline u64 of_read_addr(const u32 *cell, int size)
+{
+       u64 r = 0;
+       while (size--)
+               r = (r << 32) | *(cell++);
+       return r;
+}
+
+static void __init get_cells(struct device_node *dp,
+                            int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = of_n_addr_cells(dp);
+       if (sizec)
+               *sizec = of_n_size_cells(dp);
+}
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS      4
+
+struct of_bus {
+       const char      *name;
+       const char      *addr_prop_name;
+       int             (*match)(struct device_node *parent);
+       void            (*count_cells)(struct device_node *child,
+                                      int *addrc, int *sizec);
+       int             (*map)(u32 *addr, const u32 *range,
+                              int na, int ns, int pna);
+       unsigned int    (*get_flags)(u32 *addr);
+};
+
+/*
+ * Default translator (generic bus)
+ */
+
+static void of_bus_default_count_cells(struct device_node *dev,
+                                      int *addrc, int *sizec)
+{
+       get_cells(dev, addrc, sizec);
+}
+
+/* Make sure the least significant 64-bits are in-range.  Even
+ * for 3 or 4 cell values it is a good enough approximation.
+ */
+static int of_out_of_range(const u32 *addr, const u32 *base,
+                          const u32 *size, int na, int ns)
+{
+       u64 a = of_read_addr(addr, na);
+       u64 b = of_read_addr(base, na);
+
+       if (a < b)
+               return 1;
+
+       b += of_read_addr(size, ns);
+       if (a >= b)
+               return 1;
+
+       return 0;
+}
+
+static int of_bus_default_map(u32 *addr, const u32 *range,
+                             int na, int ns, int pna)
+{
+       u32 result[OF_MAX_ADDR_CELLS];
+       int i;
+
+       if (ns > 2) {
+               printk("of_device: Cannot handle size cells (%d) > 2.", ns);
+               return -EINVAL;
+       }
+
+       if (of_out_of_range(addr, range, range + na + pna, na, ns))
+               return -EINVAL;
+
+       /* Start with the parent range base.  */
+       memcpy(result, range + na, pna * 4);
+
+       /* Add in the child address offset.  */
+       for (i = 0; i < na; i++)
+               result[pna - 1 - i] +=
+                       (addr[na - 1 - i] -
+                        range[na - 1 - i]);
+
+       memcpy(addr, result, pna * 4);
+
+       return 0;
+}
+
+static unsigned int of_bus_default_get_flags(u32 *addr)
+{
+       return IORESOURCE_MEM;
+}
+
+/*
+ * PCI bus specific translator
+ */
+
+static int of_bus_pci_match(struct device_node *np)
+{
+       if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+               /* Do not do PCI specific frobbing if the
+                * PCI bridge lacks a ranges property.  We
+                * want to pass it through up to the next
+                * parent as-is, not with the PCI translate
+                * method which chops off the top address cell.
+                */
+               if (!of_find_property(np, "ranges", NULL))
+                       return 0;
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static void of_bus_pci_count_cells(struct device_node *np,
+                                  int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = 3;
+       if (sizec)
+               *sizec = 2;
+}
+
+static int of_bus_pci_map(u32 *addr, const u32 *range,
+                         int na, int ns, int pna)
+{
+       u32 result[OF_MAX_ADDR_CELLS];
+       int i;
+
+       /* Check address type match */
+       if ((addr[0] ^ range[0]) & 0x03000000)
+               return -EINVAL;
+
+       if (of_out_of_range(addr + 1, range + 1, range + na + pna,
+                           na - 1, ns))
+               return -EINVAL;
+
+       /* Start with the parent range base.  */
+       memcpy(result, range + na, pna * 4);
+
+       /* Add in the child address offset, skipping high cell.  */
+       for (i = 0; i < na - 1; i++)
+               result[pna - 1 - i] +=
+                       (addr[na - 1 - i] -
+                        range[na - 1 - i]);
+
+       memcpy(addr, result, pna * 4);
+
+       return 0;
+}
+
+static unsigned int of_bus_pci_get_flags(u32 *addr)
+{
+       unsigned int flags = 0;
+       u32 w = addr[0];
+
+       switch((w >> 24) & 0x03) {
+       case 0x01:
+               flags |= IORESOURCE_IO;
+       case 0x02: /* 32 bits */
+       case 0x03: /* 64 bits */
+               flags |= IORESOURCE_MEM;
+       }
+       if (w & 0x40000000)
+               flags |= IORESOURCE_PREFETCH;
+       return flags;
+}
+
+/*
+ * SBUS bus specific translator
+ */
+
+static int of_bus_sbus_match(struct device_node *np)
+{
+       return !strcmp(np->name, "sbus") ||
+               !strcmp(np->name, "sbi");
+}
+
+static void of_bus_sbus_count_cells(struct device_node *child,
+                                  int *addrc, int *sizec)
+{
+       if (addrc)
+               *addrc = 2;
+       if (sizec)
+               *sizec = 1;
+}
+
+/*
+ * FHC/Central bus specific translator.
+ *
+ * This is just needed to hard-code the address and size cell
+ * counts.  'fhc' and 'central' nodes lack the #address-cells and
+ * #size-cells properties, and if you walk to the root on such
+ * Enterprise boxes all you'll get is a #size-cells of 2 which is
+ * not what we want to use.
+ */
+static int of_bus_fhc_match(struct device_node *np)
+{
+       return !strcmp(np->name, "fhc") ||
+               !strcmp(np->name, "central");
+}
+
+#define of_bus_fhc_count_cells of_bus_sbus_count_cells
+
+/*
+ * Array of bus specific translators
+ */
+
+static struct of_bus of_busses[] = {
+       /* PCI */
+       {
+               .name = "pci",
+               .addr_prop_name = "assigned-addresses",
+               .match = of_bus_pci_match,
+               .count_cells = of_bus_pci_count_cells,
+               .map = of_bus_pci_map,
+               .get_flags = of_bus_pci_get_flags,
+       },
+       /* SBUS */
+       {
+               .name = "sbus",
+               .addr_prop_name = "reg",
+               .match = of_bus_sbus_match,
+               .count_cells = of_bus_sbus_count_cells,
+               .map = of_bus_default_map,
+               .get_flags = of_bus_default_get_flags,
+       },
+       /* FHC */
+       {
+               .name = "fhc",
+               .addr_prop_name = "reg",
+               .match = of_bus_fhc_match,
+               .count_cells = of_bus_fhc_count_cells,
+               .map = of_bus_default_map,
+               .get_flags = of_bus_default_get_flags,
+       },
+       /* Default */
+       {
+               .name = "default",
+               .addr_prop_name = "reg",
+               .match = NULL,
+               .count_cells = of_bus_default_count_cells,
+               .map = of_bus_default_map,
+               .get_flags = of_bus_default_get_flags,
+       },
+};
+
+static struct of_bus *of_match_bus(struct device_node *np)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(of_busses); i ++)
+               if (!of_busses[i].match || of_busses[i].match(np))
+                       return &of_busses[i];
+       BUG();
+       return NULL;
+}
+
+static int __init build_one_resource(struct device_node *parent,
+                                    struct of_bus *bus,
+                                    struct of_bus *pbus,
+                                    u32 *addr,
+                                    int na, int ns, int pna)
+{
+       u32 *ranges;
+       unsigned int rlen;
+       int rone;
+
+       ranges = of_get_property(parent, "ranges", &rlen);
+       if (ranges == NULL || rlen == 0) {
+               u32 result[OF_MAX_ADDR_CELLS];
+               int i;
+
+               memset(result, 0, pna * 4);
+               for (i = 0; i < na; i++)
+                       result[pna - 1 - i] =
+                               addr[na - 1 - i];
+
+               memcpy(addr, result, pna * 4);
+               return 0;
+       }
+
+       /* Now walk through the ranges */
+       rlen /= 4;
+       rone = na + pna + ns;
+       for (; rlen >= rone; rlen -= rone, ranges += rone) {
+               if (!bus->map(addr, ranges, na, ns, pna))
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int __init use_1to1_mapping(struct device_node *pp)
+{
+       char *model;
+
+       /* If this is on the PMU bus, don't try to translate it even
+        * if a ranges property exists.
+        */
+       if (!strcmp(pp->name, "pmu"))
+               return 1;
+
+       /* If we have a ranges property in the parent, use it.  */
+       if (of_find_property(pp, "ranges", NULL) != NULL)
+               return 0;
+
+       /* If the parent is the dma node of an ISA bus, pass
+        * the translation up to the root.
+        */
+       if (!strcmp(pp->name, "dma"))
+               return 0;
+
+       /* Similarly for Simba PCI bridges.  */
+       model = of_get_property(pp, "model", NULL);
+       if (model && !strcmp(model, "SUNW,simba"))
+               return 0;
+
+       return 1;
+}
+
+static int of_resource_verbose;
+
+static void __init build_device_resources(struct of_device *op,
+                                         struct device *parent)
+{
+       struct of_device *p_op;
+       struct of_bus *bus;
+       int na, ns;
+       int index, num_reg;
+       void *preg;
+
+       if (!parent)
+               return;
+
+       p_op = to_of_device(parent);
+       bus = of_match_bus(p_op->node);
+       bus->count_cells(op->node, &na, &ns);
+
+       preg = of_get_property(op->node, bus->addr_prop_name, &num_reg);
+       if (!preg || num_reg == 0)
+               return;
+
+       /* Convert to num-cells.  */
+       num_reg /= 4;
+
+       /* Convert to num-entries.  */
+       num_reg /= na + ns;
+
+       /* Prevent overruning the op->resources[] array.  */
+       if (num_reg > PROMREG_MAX) {
+               printk(KERN_WARNING "%s: Too many regs (%d), "
+                      "limiting to %d.\n",
+                      op->node->full_name, num_reg, PROMREG_MAX);
+               num_reg = PROMREG_MAX;
+       }
+
+       for (index = 0; index < num_reg; index++) {
+               struct resource *r = &op->resource[index];
+               u32 addr[OF_MAX_ADDR_CELLS];
+               u32 *reg = (preg + (index * ((na + ns) * 4)));
+               struct device_node *dp = op->node;
+               struct device_node *pp = p_op->node;
+               struct of_bus *pbus;
+               u64 size, result = OF_BAD_ADDR;
+               unsigned long flags;
+               int dna, dns;
+               int pna, pns;
+
+               size = of_read_addr(reg + na, ns);
+               flags = bus->get_flags(reg);
+
+               memcpy(addr, reg, na * 4);
+
+               if (use_1to1_mapping(pp)) {
+                       result = of_read_addr(addr, na);
+                       goto build_res;
+               }
+
+               dna = na;
+               dns = ns;
+
+               while (1) {
+                       dp = pp;
+                       pp = dp->parent;
+                       if (!pp) {
+                               result = of_read_addr(addr, dna);
+                               break;
+                       }
+
+                       pbus = of_match_bus(pp);
+                       pbus->count_cells(dp, &pna, &pns);
+
+                       if (build_one_resource(dp, bus, pbus, addr,
+                                              dna, dns, pna))
+                               break;
+
+                       dna = pna;
+                       dns = pns;
+                       bus = pbus;
+               }
+
+       build_res:
+               memset(r, 0, sizeof(*r));
+
+               if (of_resource_verbose)
+                       printk("%s reg[%d] -> %lx\n",
+                              op->node->full_name, index,
+                              result);
+
+               if (result != OF_BAD_ADDR) {
+                       if (tlb_type == hypervisor)
+                               result &= 0x0fffffffffffffffUL;
+
+                       r->start = result;
+                       r->end = result + size - 1;
+                       r->flags = flags;
+               } else {
+                       r->start = ~0UL;
+                       r->end = ~0UL;
+               }
+               r->name = op->node->name;
+       }
+}
+
+static struct device_node * __init
+apply_interrupt_map(struct device_node *dp, struct device_node *pp,
+                   u32 *imap, int imlen, u32 *imask,
+                   unsigned int *irq_p)
+{
+       struct device_node *cp;
+       unsigned int irq = *irq_p;
+       struct of_bus *bus;
+       phandle handle;
+       u32 *reg;
+       int na, num_reg, i;
+
+       bus = of_match_bus(pp);
+       bus->count_cells(dp, &na, NULL);
+
+       reg = of_get_property(dp, "reg", &num_reg);
+       if (!reg || !num_reg)
+               return NULL;
+
+       imlen /= ((na + 3) * 4);
+       handle = 0;
+       for (i = 0; i < imlen; i++) {
+               int j;
+
+               for (j = 0; j < na; j++) {
+                       if ((reg[j] & imask[j]) != imap[j])
+                               goto next;
+               }
+               if (imap[na] == irq) {
+                       handle = imap[na + 1];
+                       irq = imap[na + 2];
+                       break;
+               }
+
+       next:
+               imap += (na + 3);
+       }
+       if (i == imlen) {
+               /* Psycho and Sabre PCI controllers can have 'interrupt-map'
+                * properties that do not include the on-board device
+                * interrupts.  Instead, the device's 'interrupts' property
+                * is already a fully specified INO value.
+                *
+                * Handle this by deciding that, if we didn't get a
+                * match in the parent's 'interrupt-map', and the
+                * parent is an IRQ translater, then use the parent as
+                * our IRQ controller.
+                */
+               if (pp->irq_trans)
+                       return pp;
+
+               return NULL;
+       }
+
+       *irq_p = irq;
+       cp = of_find_node_by_phandle(handle);
+
+       return cp;
+}
+
+static unsigned int __init pci_irq_swizzle(struct device_node *dp,
+                                          struct device_node *pp,
+                                          unsigned int irq)
+{
+       struct linux_prom_pci_registers *regs;
+       unsigned int devfn, slot, ret;
+
+       if (irq < 1 || irq > 4)
+               return irq;
+
+       regs = of_get_property(dp, "reg", NULL);
+       if (!regs)
+               return irq;
+
+       devfn = (regs->phys_hi >> 8) & 0xff;
+       slot = (devfn >> 3) & 0x1f;
+
+       ret = ((irq - 1 + (slot & 3)) & 3) + 1;
+
+       return ret;
+}
+
+static int of_irq_verbose;
+
+static unsigned int __init build_one_device_irq(struct of_device *op,
+                                               struct device *parent,
+                                               unsigned int irq)
+{
+       struct device_node *dp = op->node;
+       struct device_node *pp, *ip;
+       unsigned int orig_irq = irq;
+
+       if (irq == 0xffffffff)
+               return irq;
+
+       if (dp->irq_trans) {
+               irq = dp->irq_trans->irq_build(dp, irq,
+                                              dp->irq_trans->data);
+
+               if (of_irq_verbose)
+                       printk("%s: direct translate %x --> %x\n",
+                              dp->full_name, orig_irq, irq);
+
+               return irq;
+       }
+
+       /* Something more complicated.  Walk up to the root, applying
+        * interrupt-map or bus specific translations, until we hit
+        * an IRQ translator.
+        *
+        * If we hit a bus type or situation we cannot handle, we
+        * stop and assume that the original IRQ number was in a
+        * format which has special meaning to it's immediate parent.
+        */
+       pp = dp->parent;
+       ip = NULL;
+       while (pp) {
+               void *imap, *imsk;
+               int imlen;
+
+               imap = of_get_property(pp, "interrupt-map", &imlen);
+               imsk = of_get_property(pp, "interrupt-map-mask", NULL);
+               if (imap && imsk) {
+                       struct device_node *iret;
+                       int this_orig_irq = irq;
+
+                       iret = apply_interrupt_map(dp, pp,
+                                                  imap, imlen, imsk,
+                                                  &irq);
+
+                       if (of_irq_verbose)
+                               printk("%s: Apply [%s:%x] imap --> [%s:%x]\n",
+                                      op->node->full_name,
+                                      pp->full_name, this_orig_irq,
+                                      (iret ? iret->full_name : "NULL"), irq);
+
+                       if (!iret)
+                               break;
+
+                       if (iret->irq_trans) {
+                               ip = iret;
+                               break;
+                       }
+               } else {
+                       if (!strcmp(pp->type, "pci") ||
+                           !strcmp(pp->type, "pciex")) {
+                               unsigned int this_orig_irq = irq;
+
+                               irq = pci_irq_swizzle(dp, pp, irq);
+                               if (of_irq_verbose)
+                                       printk("%s: PCI swizzle [%s] "
+                                              "%x --> %x\n",
+                                              op->node->full_name,
+                                              pp->full_name, this_orig_irq,
+                                              irq);
+
+                       }
+
+                       if (pp->irq_trans) {
+                               ip = pp;
+                               break;
+                       }
+               }
+               dp = pp;
+               pp = pp->parent;
+       }
+       if (!ip)
+               return orig_irq;
+
+       irq = ip->irq_trans->irq_build(op->node, irq,
+                                      ip->irq_trans->data);
+       if (of_irq_verbose)
+               printk("%s: Apply IRQ trans [%s] %x --> %x\n",
+                      op->node->full_name, ip->full_name, orig_irq, irq);
+
+       return irq;
+}
+
+static struct of_device * __init scan_one_device(struct device_node *dp,
+                                                struct device *parent)
+{
+       struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
+       unsigned int *irq;
+       int len, i;
+
+       if (!op)
+               return NULL;
+
+       op->node = dp;
+
+       op->clock_freq = of_getintprop_default(dp, "clock-frequency",
+                                              (25*1000*1000));
+       op->portid = of_getintprop_default(dp, "upa-portid", -1);
+       if (op->portid == -1)
+               op->portid = of_getintprop_default(dp, "portid", -1);
+
+       irq = of_get_property(dp, "interrupts", &len);
+       if (irq) {
+               memcpy(op->irqs, irq, len);
+               op->num_irqs = len / 4;
+       } else {
+               op->num_irqs = 0;
+       }
+
+       /* Prevent overruning the op->irqs[] array.  */
+       if (op->num_irqs > PROMINTR_MAX) {
+               printk(KERN_WARNING "%s: Too many irqs (%d), "
+                      "limiting to %d.\n",
+                      dp->full_name, op->num_irqs, PROMINTR_MAX);
+               op->num_irqs = PROMINTR_MAX;
+       }
+
+       build_device_resources(op, parent);
+       for (i = 0; i < op->num_irqs; i++)
+               op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
+
+       op->dev.parent = parent;
+       op->dev.bus = &of_bus_type;
+       if (!parent)
+               strcpy(op->dev.bus_id, "root");
+       else
+               strcpy(op->dev.bus_id, dp->path_component_name);
+
+       if (of_device_register(op)) {
+               printk("%s: Could not register of device.\n",
+                      dp->full_name);
+               kfree(op);
+               op = NULL;
+       }
+
+       return op;
+}
+
+static void __init scan_tree(struct device_node *dp, struct device *parent)
+{
+       while (dp) {
+               struct of_device *op = scan_one_device(dp, parent);
+
+               if (op)
+                       scan_tree(dp->child, &op->dev);
+
+               dp = dp->sibling;
+       }
+}
+
+static void __init scan_of_devices(void)
+{
+       struct device_node *root = of_find_node_by_path("/");
+       struct of_device *parent;
+
+       parent = scan_one_device(root, NULL);
+       if (!parent)
+               return;
+
+       scan_tree(root->child, &parent->dev);
+}
+
+static int __init of_bus_driver_init(void)
+{
+       int err;
+
+       err = bus_register(&of_bus_type);
+#ifdef CONFIG_PCI
+       if (!err)
+               err = bus_register(&isa_bus_type);
+       if (!err)
+               err = bus_register(&ebus_bus_type);
+#endif
+#ifdef CONFIG_SBUS
+       if (!err)
+               err = bus_register(&sbus_bus_type);
+#endif
+
+       if (!err)
+               scan_of_devices();
+
+       return err;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+static int __init of_debug(char *str)
+{
+       int val = 0;
+
+       get_option(&str, &val);
+       if (val & 1)
+               of_resource_verbose = 1;
+       if (val & 2)
+               of_irq_verbose = 1;
+       return 1;
+}
+
+__setup("of_debug=", of_debug);
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+       /* initialize common driver fields */
+       drv->driver.name = drv->name;
+       drv->driver.bus = bus;
+
+       /* register with core */
+       return driver_register(&drv->driver);
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct of_device *ofdev;
+
+       ofdev = to_of_device(dev);
+       return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+       struct of_device *ofdev;
+
+        ofdev = to_of_device(dev);
+
+       kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+       int rc;
+
+       BUG_ON(ofdev->node == NULL);
+
+       rc = device_register(&ofdev->dev);
+       if (rc)
+               return rc;
+
+       rc = device_create_file(&ofdev->dev, &dev_attr_devspec);
+       if (rc)
+               device_unregister(&ofdev->dev);
+
+       return rc;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+       device_remove_file(&ofdev->dev, &dev_attr_devspec);
+       device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+                                           const char *bus_id,
+                                           struct device *parent,
+                                           struct bus_type *bus)
+{
+       struct of_device *dev;
+
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+       memset(dev, 0, sizeof(*dev));
+
+       dev->dev.parent = parent;
+       dev->dev.bus = bus;
+       dev->dev.release = of_release_dev;
+
+       strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+       if (of_device_register(dev) != 0) {
+               kfree(dev);
+               return NULL;
+       }
+
+       return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
new file mode 100644 (file)
index 0000000..c60efb3
--- /dev/null
@@ -0,0 +1,1577 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras      August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc64 by David S. Miller davem@davemloft.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/oplib.h>
+#include <asm/irq.h>
+#include <asm/asi.h>
+#include <asm/upa.h>
+
+static struct device_node *allnodes;
+
+/* use when traversing tree through the allnext, child, sibling,
+ * or parent members of struct device_node.
+ */
+static DEFINE_RWLOCK(devtree_lock);
+
+int of_device_is_compatible(struct device_node *device, const char *compat)
+{
+       const char* cp;
+       int cplen, l;
+
+       cp = (char *) of_get_property(device, "compatible", &cplen);
+       if (cp == NULL)
+               return 0;
+       while (cplen > 0) {
+               if (strncmp(cp, compat, strlen(compat)) == 0)
+                       return 1;
+               l = strlen(cp) + 1;
+               cp += l;
+               cplen -= l;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(of_device_is_compatible);
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+       struct device_node *np;
+
+       if (!node)
+               return NULL;
+
+       np = node->parent;
+
+       return np;
+}
+EXPORT_SYMBOL(of_get_parent);
+
+struct device_node *of_get_next_child(const struct device_node *node,
+       struct device_node *prev)
+{
+       struct device_node *next;
+
+       next = prev ? prev->sibling : node->child;
+       for (; next != 0; next = next->sibling) {
+               break;
+       }
+
+       return next;
+}
+EXPORT_SYMBOL(of_get_next_child);
+
+struct device_node *of_find_node_by_path(const char *path)
+{
+       struct device_node *np = allnodes;
+
+       for (; np != 0; np = np->allnext) {
+               if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
+                       break;
+       }
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_path);
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+       struct device_node *np;
+
+       for (np = allnodes; np != 0; np = np->allnext)
+               if (np->node == handle)
+                       break;
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+struct device_node *of_find_node_by_name(struct device_node *from,
+       const char *name)
+{
+       struct device_node *np;
+
+       np = from ? from->allnext : allnodes;
+       for (; np != NULL; np = np->allnext)
+               if (np->name != NULL && strcmp(np->name, name) == 0)
+                       break;
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_name);
+
+struct device_node *of_find_node_by_type(struct device_node *from,
+       const char *type)
+{
+       struct device_node *np;
+
+       np = from ? from->allnext : allnodes;
+       for (; np != 0; np = np->allnext)
+               if (np->type != 0 && strcmp(np->type, type) == 0)
+                       break;
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_type);
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+       const char *type, const char *compatible)
+{
+       struct device_node *np;
+
+       np = from ? from->allnext : allnodes;
+       for (; np != 0; np = np->allnext) {
+               if (type != NULL
+                   && !(np->type != 0 && strcmp(np->type, type) == 0))
+                       continue;
+               if (of_device_is_compatible(np, compatible))
+                       break;
+       }
+
+       return np;
+}
+EXPORT_SYMBOL(of_find_compatible_node);
+
+struct property *of_find_property(struct device_node *np, const char *name,
+                                 int *lenp)
+{
+       struct property *pp;
+
+       for (pp = np->properties; pp != 0; pp = pp->next) {
+               if (strcmp(pp->name, name) == 0) {
+                       if (lenp != 0)
+                               *lenp = pp->length;
+                       break;
+               }
+       }
+       return pp;
+}
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+       struct property *pp = of_find_property(np,name,lenp);
+       return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+       struct property *prop;
+       int len;
+
+       prop = of_find_property(np, name, &len);
+       if (!prop || len != 4)
+               return def;
+
+       return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+int of_n_addr_cells(struct device_node *np)
+{
+       int* ip;
+       do {
+               if (np->parent)
+                       np = np->parent;
+               ip = of_get_property(np, "#address-cells", NULL);
+               if (ip != NULL)
+                       return *ip;
+       } while (np->parent);
+       /* No #address-cells property for the root node, default to 2 */
+       return 2;
+}
+EXPORT_SYMBOL(of_n_addr_cells);
+
+int of_n_size_cells(struct device_node *np)
+{
+       int* ip;
+       do {
+               if (np->parent)
+                       np = np->parent;
+               ip = of_get_property(np, "#size-cells", NULL);
+               if (ip != NULL)
+                       return *ip;
+       } while (np->parent);
+       /* No #size-cells property for the root node, default to 1 */
+       return 1;
+}
+EXPORT_SYMBOL(of_n_size_cells);
+
+int of_set_property(struct device_node *dp, const char *name, void *val, int len)
+{
+       struct property **prevp;
+       void *new_val;
+       int err;
+
+       new_val = kmalloc(len, GFP_KERNEL);
+       if (!new_val)
+               return -ENOMEM;
+
+       memcpy(new_val, val, len);
+
+       err = -ENODEV;
+
+       write_lock(&devtree_lock);
+       prevp = &dp->properties;
+       while (*prevp) {
+               struct property *prop = *prevp;
+
+               if (!strcmp(prop->name, name)) {
+                       void *old_val = prop->value;
+                       int ret;
+
+                       ret = prom_setprop(dp->node, name, val, len);
+                       err = -EINVAL;
+                       if (ret >= 0) {
+                               prop->value = new_val;
+                               prop->length = len;
+
+                               if (OF_IS_DYNAMIC(prop))
+                                       kfree(old_val);
+
+                               OF_MARK_DYNAMIC(prop);
+
+                               err = 0;
+                       }
+                       break;
+               }
+               prevp = &(*prevp)->next;
+       }
+       write_unlock(&devtree_lock);
+
+       /* XXX Upate procfs if necessary... */
+
+       return err;
+}
+EXPORT_SYMBOL(of_set_property);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+       void *ret;
+
+       ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+       if (ret != NULL)
+               memset(ret, 0, size);
+
+       prom_early_allocated += size;
+
+       return ret;
+}
+
+#ifdef CONFIG_PCI
+/* PSYCHO interrupt mapping support. */
+#define PSYCHO_IMAP_A_SLOT0    0x0c00UL
+#define PSYCHO_IMAP_B_SLOT0    0x0c20UL
+static unsigned long psycho_pcislot_imap_offset(unsigned long ino)
+{
+       unsigned int bus =  (ino & 0x10) >> 4;
+       unsigned int slot = (ino & 0x0c) >> 2;
+
+       if (bus == 0)
+               return PSYCHO_IMAP_A_SLOT0 + (slot * 8);
+       else
+               return PSYCHO_IMAP_B_SLOT0 + (slot * 8);
+}
+
+#define PSYCHO_IMAP_SCSI       0x1000UL
+#define PSYCHO_IMAP_ETH                0x1008UL
+#define PSYCHO_IMAP_BPP                0x1010UL
+#define PSYCHO_IMAP_AU_REC     0x1018UL
+#define PSYCHO_IMAP_AU_PLAY    0x1020UL
+#define PSYCHO_IMAP_PFAIL      0x1028UL
+#define PSYCHO_IMAP_KMS                0x1030UL
+#define PSYCHO_IMAP_FLPY       0x1038UL
+#define PSYCHO_IMAP_SHW                0x1040UL
+#define PSYCHO_IMAP_KBD                0x1048UL
+#define PSYCHO_IMAP_MS         0x1050UL
+#define PSYCHO_IMAP_SER                0x1058UL
+#define PSYCHO_IMAP_TIM0       0x1060UL
+#define PSYCHO_IMAP_TIM1       0x1068UL
+#define PSYCHO_IMAP_UE         0x1070UL
+#define PSYCHO_IMAP_CE         0x1078UL
+#define PSYCHO_IMAP_A_ERR      0x1080UL
+#define PSYCHO_IMAP_B_ERR      0x1088UL
+#define PSYCHO_IMAP_PMGMT      0x1090UL
+#define PSYCHO_IMAP_GFX                0x1098UL
+#define PSYCHO_IMAP_EUPA       0x10a0UL
+
+static unsigned long __psycho_onboard_imap_off[] = {
+/*0x20*/       PSYCHO_IMAP_SCSI,
+/*0x21*/       PSYCHO_IMAP_ETH,
+/*0x22*/       PSYCHO_IMAP_BPP,
+/*0x23*/       PSYCHO_IMAP_AU_REC,
+/*0x24*/       PSYCHO_IMAP_AU_PLAY,
+/*0x25*/       PSYCHO_IMAP_PFAIL,
+/*0x26*/       PSYCHO_IMAP_KMS,
+/*0x27*/       PSYCHO_IMAP_FLPY,
+/*0x28*/       PSYCHO_IMAP_SHW,
+/*0x29*/       PSYCHO_IMAP_KBD,
+/*0x2a*/       PSYCHO_IMAP_MS,
+/*0x2b*/       PSYCHO_IMAP_SER,
+/*0x2c*/       PSYCHO_IMAP_TIM0,
+/*0x2d*/       PSYCHO_IMAP_TIM1,
+/*0x2e*/       PSYCHO_IMAP_UE,
+/*0x2f*/       PSYCHO_IMAP_CE,
+/*0x30*/       PSYCHO_IMAP_A_ERR,
+/*0x31*/       PSYCHO_IMAP_B_ERR,
+/*0x32*/       PSYCHO_IMAP_PMGMT,
+/*0x33*/       PSYCHO_IMAP_GFX,
+/*0x34*/       PSYCHO_IMAP_EUPA,
+};
+#define PSYCHO_ONBOARD_IRQ_BASE                0x20
+#define PSYCHO_ONBOARD_IRQ_LAST                0x34
+#define psycho_onboard_imap_offset(__ino) \
+       __psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]
+
+#define PSYCHO_ICLR_A_SLOT0    0x1400UL
+#define PSYCHO_ICLR_SCSI       0x1800UL
+
+#define psycho_iclr_offset(ino)                                              \
+       ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
+                       (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
+
+static unsigned int psycho_irq_build(struct device_node *dp,
+                                    unsigned int ino,
+                                    void *_data)
+{
+       unsigned long controller_regs = (unsigned long) _data;
+       unsigned long imap, iclr;
+       unsigned long imap_off, iclr_off;
+       int inofixup = 0;
+
+       ino &= 0x3f;
+       if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
+               /* PCI slot */
+               imap_off = psycho_pcislot_imap_offset(ino);
+       } else {
+               /* Onboard device */
+               if (ino > PSYCHO_ONBOARD_IRQ_LAST) {
+                       prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino);
+                       prom_halt();
+               }
+               imap_off = psycho_onboard_imap_offset(ino);
+       }
+
+       /* Now build the IRQ bucket. */
+       imap = controller_regs + imap_off;
+       imap += 4;
+
+       iclr_off = psycho_iclr_offset(ino);
+       iclr = controller_regs + iclr_off;
+       iclr += 4;
+
+       if ((ino & 0x20) == 0)
+               inofixup = ino & 0x03;
+
+       return build_irq(inofixup, iclr, imap);
+}
+
+static void psycho_irq_trans_init(struct device_node *dp)
+{
+       struct linux_prom64_registers *regs;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = psycho_irq_build;
+
+       regs = of_get_property(dp, "reg", NULL);
+       dp->irq_trans->data = (void *) regs[2].phys_addr;
+}
+
+#define sabre_read(__reg) \
+({     u64 __ret; \
+       __asm__ __volatile__("ldxa [%1] %2, %0" \
+                            : "=r" (__ret) \
+                            : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+                            : "memory"); \
+       __ret; \
+})
+
+struct sabre_irq_data {
+       unsigned long controller_regs;
+       unsigned int pci_first_busno;
+};
+#define SABRE_CONFIGSPACE      0x001000000UL
+#define SABRE_WRSYNC           0x1c20UL
+
+#define SABRE_CONFIG_BASE(CONFIG_SPACE)        \
+       (CONFIG_SPACE | (1UL << 24))
+#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG)   \
+       (((unsigned long)(BUS)   << 16) |       \
+        ((unsigned long)(DEVFN) << 8)  |       \
+        ((unsigned long)(REG)))
+
+/* When a device lives behind a bridge deeper in the PCI bus topology
+ * than APB, a special sequence must run to make sure all pending DMA
+ * transfers at the time of IRQ delivery are visible in the coherency
+ * domain by the cpu.  This sequence is to perform a read on the far
+ * side of the non-APB bridge, then perform a read of Sabre's DMA
+ * write-sync register.
+ */
+static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
+{
+       unsigned int phys_hi = (unsigned int) (unsigned long) _arg1;
+       struct sabre_irq_data *irq_data = _arg2;
+       unsigned long controller_regs = irq_data->controller_regs;
+       unsigned long sync_reg = controller_regs + SABRE_WRSYNC;
+       unsigned long config_space = controller_regs + SABRE_CONFIGSPACE;
+       unsigned int bus, devfn;
+       u16 _unused;
+
+       config_space = SABRE_CONFIG_BASE(config_space);
+
+       bus = (phys_hi >> 16) & 0xff;
+       devfn = (phys_hi >> 8) & 0xff;
+
+       config_space |= SABRE_CONFIG_ENCODE(bus, devfn, 0x00);
+
+       __asm__ __volatile__("membar #Sync\n\t"
+                            "lduha [%1] %2, %0\n\t"
+                            "membar #Sync"
+                            : "=r" (_unused)
+                            : "r" ((u16 *) config_space),
+                              "i" (ASI_PHYS_BYPASS_EC_E_L)
+                            : "memory");
+
+       sabre_read(sync_reg);
+}
+
+#define SABRE_IMAP_A_SLOT0     0x0c00UL
+#define SABRE_IMAP_B_SLOT0     0x0c20UL
+#define SABRE_IMAP_SCSI                0x1000UL
+#define SABRE_IMAP_ETH         0x1008UL
+#define SABRE_IMAP_BPP         0x1010UL
+#define SABRE_IMAP_AU_REC      0x1018UL
+#define SABRE_IMAP_AU_PLAY     0x1020UL
+#define SABRE_IMAP_PFAIL       0x1028UL
+#define SABRE_IMAP_KMS         0x1030UL
+#define SABRE_IMAP_FLPY                0x1038UL
+#define SABRE_IMAP_SHW         0x1040UL
+#define SABRE_IMAP_KBD         0x1048UL
+#define SABRE_IMAP_MS          0x1050UL
+#define SABRE_IMAP_SER         0x1058UL
+#define SABRE_IMAP_UE          0x1070UL
+#define SABRE_IMAP_CE          0x1078UL
+#define SABRE_IMAP_PCIERR      0x1080UL
+#define SABRE_IMAP_GFX         0x1098UL
+#define SABRE_IMAP_EUPA                0x10a0UL
+#define SABRE_ICLR_A_SLOT0     0x1400UL
+#define SABRE_ICLR_B_SLOT0     0x1480UL
+#define SABRE_ICLR_SCSI                0x1800UL
+#define SABRE_ICLR_ETH         0x1808UL
+#define SABRE_ICLR_BPP         0x1810UL
+#define SABRE_ICLR_AU_REC      0x1818UL
+#define SABRE_ICLR_AU_PLAY     0x1820UL
+#define SABRE_ICLR_PFAIL       0x1828UL
+#define SABRE_ICLR_KMS         0x1830UL
+#define SABRE_ICLR_FLPY                0x1838UL
+#define SABRE_ICLR_SHW         0x1840UL
+#define SABRE_ICLR_KBD         0x1848UL
+#define SABRE_ICLR_MS          0x1850UL
+#define SABRE_ICLR_SER         0x1858UL
+#define SABRE_ICLR_UE          0x1870UL
+#define SABRE_ICLR_CE          0x1878UL
+#define SABRE_ICLR_PCIERR      0x1880UL
+
+static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
+{
+       unsigned int bus =  (ino & 0x10) >> 4;
+       unsigned int slot = (ino & 0x0c) >> 2;
+
+       if (bus == 0)
+               return SABRE_IMAP_A_SLOT0 + (slot * 8);
+       else
+               return SABRE_IMAP_B_SLOT0 + (slot * 8);
+}
+
+static unsigned long __sabre_onboard_imap_off[] = {
+/*0x20*/       SABRE_IMAP_SCSI,
+/*0x21*/       SABRE_IMAP_ETH,
+/*0x22*/       SABRE_IMAP_BPP,
+/*0x23*/       SABRE_IMAP_AU_REC,
+/*0x24*/       SABRE_IMAP_AU_PLAY,
+/*0x25*/       SABRE_IMAP_PFAIL,
+/*0x26*/       SABRE_IMAP_KMS,
+/*0x27*/       SABRE_IMAP_FLPY,
+/*0x28*/       SABRE_IMAP_SHW,
+/*0x29*/       SABRE_IMAP_KBD,
+/*0x2a*/       SABRE_IMAP_MS,
+/*0x2b*/       SABRE_IMAP_SER,
+/*0x2c*/       0 /* reserved */,
+/*0x2d*/       0 /* reserved */,
+/*0x2e*/       SABRE_IMAP_UE,
+/*0x2f*/       SABRE_IMAP_CE,
+/*0x30*/       SABRE_IMAP_PCIERR,
+/*0x31*/       0 /* reserved */,
+/*0x32*/       0 /* reserved */,
+/*0x33*/       SABRE_IMAP_GFX,
+/*0x34*/       SABRE_IMAP_EUPA,
+};
+#define SABRE_ONBOARD_IRQ_BASE         0x20
+#define SABRE_ONBOARD_IRQ_LAST         0x30
+#define sabre_onboard_imap_offset(__ino) \
+       __sabre_onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE]
+
+#define sabre_iclr_offset(ino)                                       \
+       ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
+                       (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
+
+static int sabre_device_needs_wsync(struct device_node *dp)
+{
+       struct device_node *parent = dp->parent;
+       char *parent_model, *parent_compat;
+
+       /* This traversal up towards the root is meant to
+        * handle two cases:
+        *
+        * 1) non-PCI bus sitting under PCI, such as 'ebus'
+        * 2) the PCI controller interrupts themselves, which
+        *    will use the sabre_irq_build but do not need
+        *    the DMA synchronization handling
+        */
+       while (parent) {
+               if (!strcmp(parent->type, "pci"))
+                       break;
+               parent = parent->parent;
+       }
+
+       if (!parent)
+               return 0;
+
+       parent_model = of_get_property(parent,
+                                      "model", NULL);
+       if (parent_model &&
+           (!strcmp(parent_model, "SUNW,sabre") ||
+            !strcmp(parent_model, "SUNW,simba")))
+               return 0;
+
+       parent_compat = of_get_property(parent,
+                                       "compatible", NULL);
+       if (parent_compat &&
+           (!strcmp(parent_compat, "pci108e,a000") ||
+            !strcmp(parent_compat, "pci108e,a001")))
+               return 0;
+
+       return 1;
+}
+
+static unsigned int sabre_irq_build(struct device_node *dp,
+                                   unsigned int ino,
+                                   void *_data)
+{
+       struct sabre_irq_data *irq_data = _data;
+       unsigned long controller_regs = irq_data->controller_regs;
+       struct linux_prom_pci_registers *regs;
+       unsigned long imap, iclr;
+       unsigned long imap_off, iclr_off;
+       int inofixup = 0;
+       int virt_irq;
+
+       ino &= 0x3f;
+       if (ino < SABRE_ONBOARD_IRQ_BASE) {
+               /* PCI slot */
+               imap_off = sabre_pcislot_imap_offset(ino);
+       } else {
+               /* onboard device */
+               if (ino > SABRE_ONBOARD_IRQ_LAST) {
+                       prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino);
+                       prom_halt();
+               }
+               imap_off = sabre_onboard_imap_offset(ino);
+       }
+
+       /* Now build the IRQ bucket. */
+       imap = controller_regs + imap_off;
+       imap += 4;
+
+       iclr_off = sabre_iclr_offset(ino);
+       iclr = controller_regs + iclr_off;
+       iclr += 4;
+
+       if ((ino & 0x20) == 0)
+               inofixup = ino & 0x03;
+
+       virt_irq = build_irq(inofixup, iclr, imap);
+
+       /* If the parent device is a PCI<->PCI bridge other than
+        * APB, we have to install a pre-handler to ensure that
+        * all pending DMA is drained before the interrupt handler
+        * is run.
+        */
+       regs = of_get_property(dp, "reg", NULL);
+       if (regs && sabre_device_needs_wsync(dp)) {
+               irq_install_pre_handler(virt_irq,
+                                       sabre_wsync_handler,
+                                       (void *) (long) regs->phys_hi,
+                                       (void *) irq_data);
+       }
+
+       return virt_irq;
+}
+
+static void sabre_irq_trans_init(struct device_node *dp)
+{
+       struct linux_prom64_registers *regs;
+       struct sabre_irq_data *irq_data;
+       u32 *busrange;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = sabre_irq_build;
+
+       irq_data = prom_early_alloc(sizeof(struct sabre_irq_data));
+
+       regs = of_get_property(dp, "reg", NULL);
+       irq_data->controller_regs = regs[0].phys_addr;
+
+       busrange = of_get_property(dp, "bus-range", NULL);
+       irq_data->pci_first_busno = busrange[0];
+
+       dp->irq_trans->data = irq_data;
+}
+
+/* SCHIZO interrupt mapping support.  Unlike Psycho, for this controller the
+ * imap/iclr registers are per-PBM.
+ */
+#define SCHIZO_IMAP_BASE       0x1000UL
+#define SCHIZO_ICLR_BASE       0x1400UL
+
+static unsigned long schizo_imap_offset(unsigned long ino)
+{
+       return SCHIZO_IMAP_BASE + (ino * 8UL);
+}
+
+static unsigned long schizo_iclr_offset(unsigned long ino)
+{
+       return SCHIZO_ICLR_BASE + (ino * 8UL);
+}
+
+static unsigned long schizo_ino_to_iclr(unsigned long pbm_regs,
+                                       unsigned int ino)
+{
+       return pbm_regs + schizo_iclr_offset(ino) + 4;
+}
+
+static unsigned long schizo_ino_to_imap(unsigned long pbm_regs,
+                                       unsigned int ino)
+{
+       return pbm_regs + schizo_imap_offset(ino) + 4;
+}
+
+#define schizo_read(__reg) \
+({     u64 __ret; \
+       __asm__ __volatile__("ldxa [%1] %2, %0" \
+                            : "=r" (__ret) \
+                            : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+                            : "memory"); \
+       __ret; \
+})
+#define schizo_write(__reg, __val) \
+       __asm__ __volatile__("stxa %0, [%1] %2" \
+                            : /* no outputs */ \
+                            : "r" (__val), "r" (__reg), \
+                              "i" (ASI_PHYS_BYPASS_EC_E) \
+                            : "memory")
+
+static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
+{
+       unsigned long sync_reg = (unsigned long) _arg2;
+       u64 mask = 1UL << (ino & IMAP_INO);
+       u64 val;
+       int limit;
+
+       schizo_write(sync_reg, mask);
+
+       limit = 100000;
+       val = 0;
+       while (--limit) {
+               val = schizo_read(sync_reg);
+               if (!(val & mask))
+                       break;
+       }
+       if (limit <= 0) {
+               printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n",
+                      val, mask);
+       }
+
+       if (_arg1) {
+               static unsigned char cacheline[64]
+                       __attribute__ ((aligned (64)));
+
+               __asm__ __volatile__("rd %%fprs, %0\n\t"
+                                    "or %0, %4, %1\n\t"
+                                    "wr %1, 0x0, %%fprs\n\t"
+                                    "stda %%f0, [%5] %6\n\t"
+                                    "wr %0, 0x0, %%fprs\n\t"
+                                    "membar #Sync"
+                                    : "=&r" (mask), "=&r" (val)
+                                    : "0" (mask), "1" (val),
+                                    "i" (FPRS_FEF), "r" (&cacheline[0]),
+                                    "i" (ASI_BLK_COMMIT_P));
+       }
+}
+
+struct schizo_irq_data {
+       unsigned long pbm_regs;
+       unsigned long sync_reg;
+       u32 portid;
+       int chip_version;
+};
+
+static unsigned int schizo_irq_build(struct device_node *dp,
+                                    unsigned int ino,
+                                    void *_data)
+{
+       struct schizo_irq_data *irq_data = _data;
+       unsigned long pbm_regs = irq_data->pbm_regs;
+       unsigned long imap, iclr;
+       int ign_fixup;
+       int virt_irq;
+       int is_tomatillo;
+
+       ino &= 0x3f;
+
+       /* Now build the IRQ bucket. */
+       imap = schizo_ino_to_imap(pbm_regs, ino);
+       iclr = schizo_ino_to_iclr(pbm_regs, ino);
+
+       /* On Schizo, no inofixup occurs.  This is because each
+        * INO has it's own IMAP register.  On Psycho and Sabre
+        * there is only one IMAP register for each PCI slot even
+        * though four different INOs can be generated by each
+        * PCI slot.
+        *
+        * But, for JBUS variants (essentially, Tomatillo), we have
+        * to fixup the lowest bit of the interrupt group number.
+        */
+       ign_fixup = 0;
+
+       is_tomatillo = (irq_data->sync_reg != 0UL);
+
+       if (is_tomatillo) {
+               if (irq_data->portid & 1)
+                       ign_fixup = (1 << 6);
+       }
+
+       virt_irq = build_irq(ign_fixup, iclr, imap);
+
+       if (is_tomatillo) {
+               irq_install_pre_handler(virt_irq,
+                                       tomatillo_wsync_handler,
+                                       ((irq_data->chip_version <= 4) ?
+                                        (void *) 1 : (void *) 0),
+                                       (void *) irq_data->sync_reg);
+       }
+
+       return virt_irq;
+}
+
+static void schizo_irq_trans_init(struct device_node *dp)
+{
+       struct linux_prom64_registers *regs;
+       struct schizo_irq_data *irq_data;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = schizo_irq_build;
+
+       irq_data = prom_early_alloc(sizeof(struct schizo_irq_data));
+
+       regs = of_get_property(dp, "reg", NULL);
+       dp->irq_trans->data = irq_data;
+
+       irq_data->pbm_regs = regs[0].phys_addr;
+       irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL;
+       irq_data->portid = of_getintprop_default(dp, "portid", 0);
+       irq_data->chip_version = of_getintprop_default(dp, "version#", 0);
+}
+
+static unsigned int pci_sun4v_irq_build(struct device_node *dp,
+                                       unsigned int devino,
+                                       void *_data)
+{
+       u32 devhandle = (u32) (unsigned long) _data;
+
+       return sun4v_build_irq(devhandle, devino);
+}
+
+static void pci_sun4v_irq_trans_init(struct device_node *dp)
+{
+       struct linux_prom64_registers *regs;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = pci_sun4v_irq_build;
+
+       regs = of_get_property(dp, "reg", NULL);
+       dp->irq_trans->data = (void *) (unsigned long)
+               ((regs->phys_addr >> 32UL) & 0x0fffffff);
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_SBUS
+/* INO number to IMAP register offset for SYSIO external IRQ's.
+ * This should conform to both Sunfire/Wildfire server and Fusion
+ * desktop designs.
+ */
+#define SYSIO_IMAP_SLOT0       0x2c04UL
+#define SYSIO_IMAP_SLOT1       0x2c0cUL
+#define SYSIO_IMAP_SLOT2       0x2c14UL
+#define SYSIO_IMAP_SLOT3       0x2c1cUL
+#define SYSIO_IMAP_SCSI                0x3004UL
+#define SYSIO_IMAP_ETH         0x300cUL
+#define SYSIO_IMAP_BPP         0x3014UL
+#define SYSIO_IMAP_AUDIO       0x301cUL
+#define SYSIO_IMAP_PFAIL       0x3024UL
+#define SYSIO_IMAP_KMS         0x302cUL
+#define SYSIO_IMAP_FLPY                0x3034UL
+#define SYSIO_IMAP_SHW         0x303cUL
+#define SYSIO_IMAP_KBD         0x3044UL
+#define SYSIO_IMAP_MS          0x304cUL
+#define SYSIO_IMAP_SER         0x3054UL
+#define SYSIO_IMAP_TIM0                0x3064UL
+#define SYSIO_IMAP_TIM1                0x306cUL
+#define SYSIO_IMAP_UE          0x3074UL
+#define SYSIO_IMAP_CE          0x307cUL
+#define SYSIO_IMAP_SBERR       0x3084UL
+#define SYSIO_IMAP_PMGMT       0x308cUL
+#define SYSIO_IMAP_GFX         0x3094UL
+#define SYSIO_IMAP_EUPA                0x309cUL
+
+#define bogon     ((unsigned long) -1)
+static unsigned long sysio_irq_offsets[] = {
+       /* SBUS Slot 0 --> 3, level 1 --> 7 */
+       SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
+       SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
+       SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
+       SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
+       SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
+       SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
+       SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
+       SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
+
+       /* Onboard devices (not relevant/used on SunFire). */
+       SYSIO_IMAP_SCSI,
+       SYSIO_IMAP_ETH,
+       SYSIO_IMAP_BPP,
+       bogon,
+       SYSIO_IMAP_AUDIO,
+       SYSIO_IMAP_PFAIL,
+       bogon,
+       bogon,
+       SYSIO_IMAP_KMS,
+       SYSIO_IMAP_FLPY,
+       SYSIO_IMAP_SHW,
+       SYSIO_IMAP_KBD,
+       SYSIO_IMAP_MS,
+       SYSIO_IMAP_SER,
+       bogon,
+       bogon,
+       SYSIO_IMAP_TIM0,
+       SYSIO_IMAP_TIM1,
+       bogon,
+       bogon,
+       SYSIO_IMAP_UE,
+       SYSIO_IMAP_CE,
+       SYSIO_IMAP_SBERR,
+       SYSIO_IMAP_PMGMT,
+       SYSIO_IMAP_GFX,
+       SYSIO_IMAP_EUPA,
+};
+
+#undef bogon
+
+#define NUM_SYSIO_OFFSETS ARRAY_SIZE(sysio_irq_offsets)
+
+/* Convert Interrupt Mapping register pointer to associated
+ * Interrupt Clear register pointer, SYSIO specific version.
+ */
+#define SYSIO_ICLR_UNUSED0     0x3400UL
+#define SYSIO_ICLR_SLOT0       0x340cUL
+#define SYSIO_ICLR_SLOT1       0x344cUL
+#define SYSIO_ICLR_SLOT2       0x348cUL
+#define SYSIO_ICLR_SLOT3       0x34ccUL
+static unsigned long sysio_imap_to_iclr(unsigned long imap)
+{
+       unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
+       return imap + diff;
+}
+
+static unsigned int sbus_of_build_irq(struct device_node *dp,
+                                     unsigned int ino,
+                                     void *_data)
+{
+       unsigned long reg_base = (unsigned long) _data;
+       struct linux_prom_registers *regs;
+       unsigned long imap, iclr;
+       int sbus_slot = 0;
+       int sbus_level = 0;
+
+       ino &= 0x3f;
+
+       regs = of_get_property(dp, "reg", NULL);
+       if (regs)
+               sbus_slot = regs->which_io;
+
+       if (ino < 0x20)
+               ino += (sbus_slot * 8);
+
+       imap = sysio_irq_offsets[ino];
+       if (imap == ((unsigned long)-1)) {
+               prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n",
+                           ino);
+               prom_halt();
+       }
+       imap += reg_base;
+
+       /* SYSIO inconsistency.  For external SLOTS, we have to select
+        * the right ICLR register based upon the lower SBUS irq level
+        * bits.
+        */
+       if (ino >= 0x20) {
+               iclr = sysio_imap_to_iclr(imap);
+       } else {
+               sbus_level = ino & 0x7;
+
+               switch(sbus_slot) {
+               case 0:
+                       iclr = reg_base + SYSIO_ICLR_SLOT0;
+                       break;
+               case 1:
+                       iclr = reg_base + SYSIO_ICLR_SLOT1;
+                       break;
+               case 2:
+                       iclr = reg_base + SYSIO_ICLR_SLOT2;
+                       break;
+               default:
+               case 3:
+                       iclr = reg_base + SYSIO_ICLR_SLOT3;
+                       break;
+               };
+
+               iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
+       }
+       return build_irq(sbus_level, iclr, imap);
+}
+
+static void sbus_irq_trans_init(struct device_node *dp)
+{
+       struct linux_prom64_registers *regs;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = sbus_of_build_irq;
+
+       regs = of_get_property(dp, "reg", NULL);
+       dp->irq_trans->data = (void *) (unsigned long) regs->phys_addr;
+}
+#endif /* CONFIG_SBUS */
+
+
+static unsigned int central_build_irq(struct device_node *dp,
+                                     unsigned int ino,
+                                     void *_data)
+{
+       struct device_node *central_dp = _data;
+       struct of_device *central_op = of_find_device_by_node(central_dp);
+       struct resource *res;
+       unsigned long imap, iclr;
+       u32 tmp;
+
+       if (!strcmp(dp->name, "eeprom")) {
+               res = &central_op->resource[5];
+       } else if (!strcmp(dp->name, "zs")) {
+               res = &central_op->resource[4];
+       } else if (!strcmp(dp->name, "clock-board")) {
+               res = &central_op->resource[3];
+       } else {
+               return ino;
+       }
+
+       imap = res->start + 0x00UL;
+       iclr = res->start + 0x10UL;
+
+       /* Set the INO state to idle, and disable.  */
+       upa_writel(0, iclr);
+       upa_readl(iclr);
+
+       tmp = upa_readl(imap);
+       tmp &= ~0x80000000;
+       upa_writel(tmp, imap);
+
+       return build_irq(0, iclr, imap);
+}
+
+static void central_irq_trans_init(struct device_node *dp)
+{
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = central_build_irq;
+
+       dp->irq_trans->data = dp;
+}
+
+struct irq_trans {
+       const char *name;
+       void (*init)(struct device_node *);
+};
+
+#ifdef CONFIG_PCI
+static struct irq_trans pci_irq_trans_table[] = {
+       { "SUNW,sabre", sabre_irq_trans_init },
+       { "pci108e,a000", sabre_irq_trans_init },
+       { "pci108e,a001", sabre_irq_trans_init },
+       { "SUNW,psycho", psycho_irq_trans_init },
+       { "pci108e,8000", psycho_irq_trans_init },
+       { "SUNW,schizo", schizo_irq_trans_init },
+       { "pci108e,8001", schizo_irq_trans_init },
+       { "SUNW,schizo+", schizo_irq_trans_init },
+       { "pci108e,8002", schizo_irq_trans_init },
+       { "SUNW,tomatillo", schizo_irq_trans_init },
+       { "pci108e,a801", schizo_irq_trans_init },
+       { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init },
+};
+#endif
+
+static unsigned int sun4v_vdev_irq_build(struct device_node *dp,
+                                        unsigned int devino,
+                                        void *_data)
+{
+       u32 devhandle = (u32) (unsigned long) _data;
+
+       return sun4v_build_irq(devhandle, devino);
+}
+
+static void sun4v_vdev_irq_trans_init(struct device_node *dp)
+{
+       struct linux_prom64_registers *regs;
+
+       dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
+       dp->irq_trans->irq_build = sun4v_vdev_irq_build;
+
+       regs = of_get_property(dp, "reg", NULL);
+       dp->irq_trans->data = (void *) (unsigned long)
+               ((regs->phys_addr >> 32UL) & 0x0fffffff);
+}
+
+static void irq_trans_init(struct device_node *dp)
+{
+#ifdef CONFIG_PCI
+       const char *model;
+       int i;
+#endif
+
+#ifdef CONFIG_PCI
+       model = of_get_property(dp, "model", NULL);
+       if (!model)
+               model = of_get_property(dp, "compatible", NULL);
+       if (model) {
+               for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) {
+                       struct irq_trans *t = &pci_irq_trans_table[i];
+
+                       if (!strcmp(model, t->name))
+                               return t->init(dp);
+               }
+       }
+#endif
+#ifdef CONFIG_SBUS
+       if (!strcmp(dp->name, "sbus") ||
+           !strcmp(dp->name, "sbi"))
+               return sbus_irq_trans_init(dp);
+#endif
+       if (!strcmp(dp->name, "fhc") &&
+           !strcmp(dp->parent->name, "central"))
+               return central_irq_trans_init(dp);
+       if (!strcmp(dp->name, "virtual-devices"))
+               return sun4v_vdev_irq_trans_init(dp);
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+       if (!dp)
+               return 0;
+
+       return (dp->parent == NULL);
+}
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ *
+ * As an example, the boot device on my workstation has a full path:
+ *
+ *     /pci@1e,600000/ide@d/disk@0,0:c
+ */
+static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom64_registers *regs;
+       struct property *rprop;
+       u32 high_bits, low_bits, type;
+
+       rprop = of_find_property(dp, "reg", NULL);
+       if (!rprop)
+               return;
+
+       regs = rprop->value;
+       if (!is_root_node(dp->parent)) {
+               sprintf(tmp_buf, "%s@%x,%x",
+                       dp->name,
+                       (unsigned int) (regs->phys_addr >> 32UL),
+                       (unsigned int) (regs->phys_addr & 0xffffffffUL));
+               return;
+       }
+
+       type = regs->phys_addr >> 60UL;
+       high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL;
+       low_bits = (regs->phys_addr & 0xffffffffUL);
+
+       if (type == 0 || type == 8) {
+               const char *prefix = (type == 0) ? "m" : "i";
+
+               if (low_bits)
+                       sprintf(tmp_buf, "%s@%s%x,%x",
+                               dp->name, prefix,
+                               high_bits, low_bits);
+               else
+                       sprintf(tmp_buf, "%s@%s%x",
+                               dp->name,
+                               prefix,
+                               high_bits);
+       } else if (type == 12) {
+               sprintf(tmp_buf, "%s@%x",
+                       dp->name, high_bits);
+       }
+}
+
+static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom64_registers *regs;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+       if (!is_root_node(dp->parent)) {
+               sprintf(tmp_buf, "%s@%x,%x",
+                       dp->name,
+                       (unsigned int) (regs->phys_addr >> 32UL),
+                       (unsigned int) (regs->phys_addr & 0xffffffffUL));
+               return;
+       }
+
+       prop = of_find_property(dp, "upa-portid", NULL);
+       if (!prop)
+               prop = of_find_property(dp, "portid", NULL);
+       if (prop) {
+               unsigned long mask = 0xffffffffUL;
+
+               if (tlb_type >= cheetah)
+                       mask = 0x7fffff;
+
+               sprintf(tmp_buf, "%s@%x,%x",
+                       dp->name,
+                       *(u32 *)prop->value,
+                       (unsigned int) (regs->phys_addr & mask));
+       }
+}
+
+/* "name@slot,offset"  */
+static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom_registers *regs;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name,
+               regs->which_io,
+               regs->phys_addr);
+}
+
+/* "name@devnum[,func]" */
+static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom_pci_registers *regs;
+       struct property *prop;
+       unsigned int devfn;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+       devfn = (regs->phys_hi >> 8) & 0xff;
+       if (devfn & 0x07) {
+               sprintf(tmp_buf, "%s@%x,%x",
+                       dp->name,
+                       devfn >> 3,
+                       devfn & 0x07);
+       } else {
+               sprintf(tmp_buf, "%s@%x",
+                       dp->name,
+                       devfn >> 3);
+       }
+}
+
+/* "name@UPA_PORTID,offset" */
+static void __init upa_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom64_registers *regs;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       prop = of_find_property(dp, "upa-portid", NULL);
+       if (!prop)
+               return;
+
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name,
+               *(u32 *) prop->value,
+               (unsigned int) (regs->phys_addr & 0xffffffffUL));
+}
+
+/* "name@reg" */
+static void __init vdev_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct property *prop;
+       u32 *regs;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       sprintf(tmp_buf, "%s@%x", dp->name, *regs);
+}
+
+/* "name@addrhi,addrlo" */
+static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct linux_prom64_registers *regs;
+       struct property *prop;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name,
+               (unsigned int) (regs->phys_addr >> 32UL),
+               (unsigned int) (regs->phys_addr & 0xffffffffUL));
+}
+
+/* "name@bus,addr" */
+static void __init i2c_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct property *prop;
+       u32 *regs;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       /* This actually isn't right... should look at the #address-cells
+        * property of the i2c bus node etc. etc.
+        */
+       sprintf(tmp_buf, "%s@%x,%x",
+               dp->name, regs[0], regs[1]);
+}
+
+/* "name@reg0[,reg1]" */
+static void __init usb_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct property *prop;
+       u32 *regs;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       if (prop->length == sizeof(u32) || regs[1] == 1) {
+               sprintf(tmp_buf, "%s@%x",
+                       dp->name, regs[0]);
+       } else {
+               sprintf(tmp_buf, "%s@%x,%x",
+                       dp->name, regs[0], regs[1]);
+       }
+}
+
+/* "name@reg0reg1[,reg2reg3]" */
+static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct property *prop;
+       u32 *regs;
+
+       prop = of_find_property(dp, "reg", NULL);
+       if (!prop)
+               return;
+
+       regs = prop->value;
+
+       if (regs[2] || regs[3]) {
+               sprintf(tmp_buf, "%s@%08x%08x,%04x%08x",
+                       dp->name, regs[0], regs[1], regs[2], regs[3]);
+       } else {
+               sprintf(tmp_buf, "%s@%08x%08x",
+                       dp->name, regs[0], regs[1]);
+       }
+}
+
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+       struct device_node *parent = dp->parent;
+
+       if (parent != NULL) {
+               if (!strcmp(parent->type, "pci") ||
+                   !strcmp(parent->type, "pciex"))
+                       return pci_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "sbus"))
+                       return sbus_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "upa"))
+                       return upa_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "ebus"))
+                       return ebus_path_component(dp, tmp_buf);
+               if (!strcmp(parent->name, "usb") ||
+                   !strcmp(parent->name, "hub"))
+                       return usb_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "i2c"))
+                       return i2c_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "firewire"))
+                       return ieee1394_path_component(dp, tmp_buf);
+               if (!strcmp(parent->type, "virtual-devices"))
+                       return vdev_path_component(dp, tmp_buf);
+
+               /* "isa" is handled with platform naming */
+       }
+
+       /* Use platform naming convention.  */
+       if (tlb_type == hypervisor)
+               return sun4v_path_component(dp, tmp_buf);
+       else
+               return sun4u_path_component(dp, tmp_buf);
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+       char tmp_buf[64], *n;
+
+       tmp_buf[0] = '\0';
+       __build_path_component(dp, tmp_buf);
+       if (tmp_buf[0] == '\0')
+               strcpy(tmp_buf, dp->name);
+
+       n = prom_early_alloc(strlen(tmp_buf) + 1);
+       strcpy(n, tmp_buf);
+
+       return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+       int len, ourlen, plen;
+       char *n;
+
+       plen = strlen(dp->parent->full_name);
+       ourlen = strlen(dp->path_component_name);
+       len = ourlen + plen + 2;
+
+       n = prom_early_alloc(len);
+       strcpy(n, dp->parent->full_name);
+       if (!is_root_node(dp->parent)) {
+               strcpy(n + plen, "/");
+               plen++;
+       }
+       strcpy(n + plen, dp->path_component_name);
+
+       return n;
+}
+
+static unsigned int unique_id;
+
+static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
+{
+       static struct property *tmp = NULL;
+       struct property *p;
+
+       if (tmp) {
+               p = tmp;
+               memset(p, 0, sizeof(*p) + 32);
+               tmp = NULL;
+       } else {
+               p = prom_early_alloc(sizeof(struct property) + 32);
+               p->unique_id = unique_id++;
+       }
+
+       p->name = (char *) (p + 1);
+       if (special_name) {
+               strcpy(p->name, special_name);
+               p->length = special_len;
+               p->value = prom_early_alloc(special_len);
+               memcpy(p->value, special_val, special_len);
+       } else {
+               if (prev == NULL) {
+                       prom_firstprop(node, p->name);
+               } else {
+                       prom_nextprop(node, prev, p->name);
+               }
+               if (strlen(p->name) == 0) {
+                       tmp = p;
+                       return NULL;
+               }
+               p->length = prom_getproplen(node, p->name);
+               if (p->length <= 0) {
+                       p->length = 0;
+               } else {
+                       p->value = prom_early_alloc(p->length + 1);
+                       prom_getproperty(node, p->name, p->value, p->length);
+                       ((unsigned char *)p->value)[p->length] = '\0';
+               }
+       }
+       return p;
+}
+
+static struct property * __init build_prop_list(phandle node)
+{
+       struct property *head, *tail;
+
+       head = tail = build_one_prop(node, NULL,
+                                    ".node", &node, sizeof(node));
+
+       tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
+       tail = tail->next;
+       while(tail) {
+               tail->next = build_one_prop(node, tail->name,
+                                           NULL, NULL, 0);
+               tail = tail->next;
+       }
+
+       return head;
+}
+
+static char * __init get_one_property(phandle node, const char *name)
+{
+       char *buf = "<NULL>";
+       int len;
+
+       len = prom_getproplen(node, name);
+       if (len > 0) {
+               buf = prom_early_alloc(len);
+               prom_getproperty(node, name, buf, len);
+       }
+
+       return buf;
+}
+
+static struct device_node * __init create_node(phandle node, struct device_node *parent)
+{
+       struct device_node *dp;
+
+       if (!node)
+               return NULL;
+
+       dp = prom_early_alloc(sizeof(*dp));
+       dp->unique_id = unique_id++;
+       dp->parent = parent;
+
+       kref_init(&dp->kref);
+
+       dp->name = get_one_property(node, "name");
+       dp->type = get_one_property(node, "device_type");
+       dp->node = node;
+
+       dp->properties = build_prop_list(node);
+
+       irq_trans_init(dp);
+
+       return dp;
+}
+
+static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
+{
+       struct device_node *dp;
+
+       dp = create_node(node, parent);
+       if (dp) {
+               *(*nextp) = dp;
+               *nextp = &dp->allnext;
+
+               dp->path_component_name = build_path_component(dp);
+               dp->full_name = build_full_name(dp);
+
+               dp->child = build_tree(dp, prom_getchild(node), nextp);
+
+               dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+       }
+
+       return dp;
+}
+
+void __init prom_build_devicetree(void)
+{
+       struct device_node **nextp;
+
+       allnodes = create_node(prom_root_node, NULL);
+       allnodes->path_component_name = "";
+       allnodes->full_name = "/";
+
+       nextp = &allnodes->allnext;
+       allnodes->child = build_tree(allnodes,
+                                    prom_getchild(allnodes->node),
+                                    &nextp);
+       printk("PROM: Built device tree with %u bytes of memory.\n",
+              prom_early_allocated);
+}
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
new file mode 100644 (file)
index 0000000..fc38a6d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/slab.h"
+#include "linux/smp_lock.h"
+#include "linux/ptrace.h"
+#include "asm/ptrace.h"
+#include "asm/pgtable.h"
+#include "asm/tlbflush.h"
+#include "asm/uaccess.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "mem_user.h"
+#include "kern.h"
+#include "irq_user.h"
+#include "tlb.h"
+#include "os.h"
+#include "choose-mode.h"
+#include "mode_kern.h"
+
+void flush_thread(void)
+{
+       arch_flush_thread(&current->thread.arch);
+       CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
+}
+
+void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
+{
+       CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, 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
+       task_lock(current);
+       log_exec(argv, current->signal->tty);
+       task_unlock(current);
+#endif
+        error = do_execve(file, argv, env, &current->thread.regs);
+        if (error == 0){
+               task_lock(current);
+                current->ptrace &= ~PT_DTRACE;
+#ifdef SUBARCH_EXECVE1
+               SUBARCH_EXECVE1(&current->thread.regs.regs);
+#endif
+               task_unlock(current);
+                set_cmdline(current_cmd());
+        }
+        return(error);
+}
+
+long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
+{
+       long err;
+
+       err = execve1(file, argv, env);
+       if(!err)
+               do_longjmp(current->thread.exec_buf, 1);
+       return(err);
+}
+
+long sys_execve(char __user *file, char __user *__user *argv,
+               char __user *__user *env)
+{
+       long error;
+       char *filename;
+
+       lock_kernel();
+       filename = getname(file);
+       error = PTR_ERR(filename);
+       if (IS_ERR(filename)) goto out;
+       error = execve1(filename, argv, env);
+       putname(filename);
+ out:
+       unlock_kernel();
+       return(error);
+}
diff --git a/arch/um/kernel/irq.c.orig b/arch/um/kernel/irq.c.orig
new file mode 100644 (file)
index 0000000..f386d21
--- /dev/null
@@ -0,0 +1,474 @@
+/* 
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
+ *     Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ */
+
+#include "linux/kernel.h"
+#include "linux/module.h"
+#include "linux/smp.h"
+#include "linux/kernel_stat.h"
+#include "linux/interrupt.h"
+#include "linux/random.h"
+#include "linux/slab.h"
+#include "linux/file.h"
+#include "linux/proc_fs.h"
+#include "linux/init.h"
+#include "linux/seq_file.h"
+#include "linux/profile.h"
+#include "linux/hardirq.h"
+#include "linux/vs_context.h"
+#include "asm/irq.h"
+#include "asm/hw_irq.h"
+#include "asm/atomic.h"
+#include "asm/signal.h"
+#include "asm/system.h"
+#include "asm/errno.h"
+#include "asm/uaccess.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "irq_user.h"
+#include "irq_kern.h"
+#include "os.h"
+#include "sigio.h"
+#include "misc_constants.h"
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+       int i = *(loff_t *) v, j;
+       struct irqaction * action;
+       unsigned long flags;
+
+       if (i == 0) {
+               seq_printf(p, "           ");
+               for_each_online_cpu(j)
+                       seq_printf(p, "CPU%d       ",j);
+               seq_putc(p, '\n');
+       }
+
+       if (i < NR_IRQS) {
+               spin_lock_irqsave(&irq_desc[i].lock, flags);
+               action = irq_desc[i].action;
+               if (!action) 
+                       goto skip;
+               seq_printf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+               seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+               for_each_online_cpu(j)
+                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+               seq_printf(p, " %14s", irq_desc[i].chip->typename);
+               seq_printf(p, "  %s", action->name);
+
+               for (action=action->next; action; action = action->next)
+                       seq_printf(p, ", %s", action->name);
+
+               seq_putc(p, '\n');
+skip:
+               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+       } else if (i == NR_IRQS) {
+               seq_putc(p, '\n');
+       }
+
+       return 0;
+}
+
+struct irq_fd *active_fds = NULL;
+static struct irq_fd **last_irq_ptr = &active_fds;
+
+extern void free_irqs(void);
+
+void sigio_handler(int sig, union uml_pt_regs *regs)
+{
+       struct irq_fd *irq_fd;
+       int n;
+
+       if (smp_sigio_handler())
+               return;
+
+       while (1) {
+               n = os_waiting_for_events(active_fds);
+               if (n <= 0) {
+                       if(n == -EINTR) continue;
+                       else break;
+               }
+
+               for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+                       if (irq_fd->current_events != 0) {
+                               irq_fd->current_events = 0;
+                               do_IRQ(irq_fd->irq, regs);
+                       }
+               }
+       }
+
+       free_irqs();
+}
+
+static DEFINE_SPINLOCK(irq_lock);
+
+int activate_fd(int irq, int fd, int type, void *dev_id)
+{
+       struct pollfd *tmp_pfd;
+       struct irq_fd *new_fd, *irq_fd;
+       unsigned long flags;
+       int pid, events, err, n;
+
+       pid = os_getpid();
+       err = os_set_fd_async(fd, pid);
+       if (err < 0)
+               goto out;
+
+       new_fd = um_kmalloc(sizeof(*new_fd));
+       err = -ENOMEM;
+       if (new_fd == NULL)
+               goto out;
+
+       if (type == IRQ_READ)
+               events = UM_POLLIN | UM_POLLPRI;
+       else
+               events = UM_POLLOUT;
+       *new_fd = ((struct irq_fd) { .next              = NULL,
+                                    .id                = dev_id,
+                                    .fd                = fd,
+                                    .type              = type,
+                                    .irq               = irq,
+                                    .pid               = pid,
+                                    .events            = events,
+                                    .current_events    = 0 } );
+
+       /* Critical section - locked by a spinlock because this stuff can
+        * be changed from interrupt handlers.  The stuff above is done
+        * outside the lock because it allocates memory.
+        */
+
+       /* Actually, it only looks like it can be called from interrupt
+        * context.  The culprit is reactivate_fd, which calls
+        * maybe_sigio_broken, which calls write_sigio_workaround,
+        * which calls activate_fd.  However, write_sigio_workaround should
+        * only be called once, at boot time.  That would make it clear that
+        * this is called only from process context, and can be locked with
+        * a semaphore.
+        */
+       spin_lock_irqsave(&irq_lock, flags);
+       for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+               if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
+                       printk("Registering fd %d twice\n", fd);
+                       printk("Irqs : %d, %d\n", irq_fd->irq, irq);
+                       printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
+                       goto out_unlock;
+               }
+       }
+
+       /*-------------*/
+       if (type == IRQ_WRITE)
+               fd = -1;
+
+       tmp_pfd = NULL;
+       n = 0;
+
+       while (1) {
+               n = os_create_pollfd(fd, events, tmp_pfd, n);
+               if (n == 0)
+                       break;
+
+               /* n > 0
+                * It means we couldn't put new pollfd to current pollfds
+                * and tmp_fds is NULL or too small for new pollfds array.
+                * Needed size is equal to n as minimum.
+                *
+                * Here we have to drop the lock in order to call
+                * kmalloc, which might sleep.
+                * If something else came in and changed the pollfds array
+                * so we will not be able to put new pollfd struct to pollfds
+                * then we free the buffer tmp_fds and try again.
+                */
+               spin_unlock_irqrestore(&irq_lock, flags);
+               kfree(tmp_pfd);
+               tmp_pfd = NULL;
+
+               tmp_pfd = um_kmalloc(n);
+               if (tmp_pfd == NULL)
+                       goto out_kfree;
+
+               spin_lock_irqsave(&irq_lock, flags);
+       }
+       /*-------------*/
+
+       *last_irq_ptr = new_fd;
+       last_irq_ptr = &new_fd->next;
+
+       spin_unlock_irqrestore(&irq_lock, flags);
+
+       /* This calls activate_fd, so it has to be outside the critical
+        * section.
+        */
+       maybe_sigio_broken(fd, (type == IRQ_READ));
+
+       return(0);
+
+ out_unlock:
+       spin_unlock_irqrestore(&irq_lock, flags);
+ out_kfree:
+       kfree(new_fd);
+ out:
+       return(err);
+}
+
+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&irq_lock, flags);
+       os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr);
+       spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+struct irq_and_dev {
+       int irq;
+       void *dev;
+};
+
+static int same_irq_and_dev(struct irq_fd *irq, void *d)
+{
+       struct irq_and_dev *data = d;
+
+       return ((irq->irq == data->irq) && (irq->id == data->dev));
+}
+
+void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
+{
+       struct irq_and_dev data = ((struct irq_and_dev) { .irq  = irq,
+                                                         .dev  = dev });
+
+       free_irq_by_cb(same_irq_and_dev, &data);
+}
+
+static int same_fd(struct irq_fd *irq, void *fd)
+{
+       return (irq->fd == *((int *)fd));
+}
+
+void free_irq_by_fd(int fd)
+{
+       free_irq_by_cb(same_fd, &fd);
+}
+
+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
+{
+       struct irq_fd *irq;
+       int i = 0;
+       int fdi;
+
+       for (irq = active_fds; irq != NULL; irq = irq->next) {
+               if ((irq->fd == fd) && (irq->irq == irqnum))
+                       break;
+               i++;
+       }
+       if (irq == NULL) {
+               printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
+               goto out;
+       }
+       fdi = os_get_pollfd(i);
+       if ((fdi != -1) && (fdi != fd)) {
+               printk("find_irq_by_fd - mismatch between active_fds and "
+                      "pollfds, fd %d vs %d, need %d\n", irq->fd,
+                      fdi, fd);
+               irq = NULL;
+               goto out;
+       }
+       *index_out = i;
+ out:
+       return irq;
+}
+
+void reactivate_fd(int fd, int irqnum)
+{
+       struct irq_fd *irq;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&irq_lock, flags);
+       irq = find_irq_by_fd(fd, irqnum, &i);
+       if (irq == NULL) {
+               spin_unlock_irqrestore(&irq_lock, flags);
+               return;
+       }
+       os_set_pollfd(i, irq->fd);
+       spin_unlock_irqrestore(&irq_lock, flags);
+
+       /* This calls activate_fd, so it has to be outside the critical
+        * section.
+        */
+       maybe_sigio_broken(fd, (irq->type == IRQ_READ));
+}
+
+void deactivate_fd(int fd, int irqnum)
+{
+       struct irq_fd *irq;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&irq_lock, flags);
+       irq = find_irq_by_fd(fd, irqnum, &i);
+       if (irq == NULL)
+               goto out;
+       os_set_pollfd(i, -1);
+ out:
+       spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+int deactivate_all_fds(void)
+{
+       struct irq_fd *irq;
+       int err;
+
+       for (irq = active_fds; irq != NULL; irq = irq->next) {
+               err = os_clear_fd_async(irq->fd);
+               if (err)
+                       return err;
+       }
+       /* If there is a signal already queued, after unblocking ignore it */
+       os_set_ioignore();
+
+       return 0;
+}
+
+#ifdef CONFIG_MODE_TT
+void forward_interrupts(int pid)
+{
+       struct irq_fd *irq;
+       unsigned long flags;
+       int err;
+
+       spin_lock_irqsave(&irq_lock, flags);
+       for (irq = active_fds; irq != NULL; irq = irq->next) {
+               err = os_set_owner(irq->fd, pid);
+               if (err < 0) {
+                       /* XXX Just remove the irq rather than
+                        * print out an infinite stream of these
+                        */
+                       printk("Failed to forward %d to pid %d, err = %d\n",
+                              irq->fd, pid, -err);
+               }
+
+               irq->pid = pid;
+       }
+       spin_unlock_irqrestore(&irq_lock, flags);
+}
+#endif
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
+{
+       struct vx_info_save vxis;
+
+       irq_enter();
+
+       __enter_vx_admin(&vxis);
+       __do_IRQ(irq, (struct pt_regs *)regs);
+       __leave_vx_admin(&vxis);
+       irq_exit();
+       return 1;
+}
+
+int um_request_irq(unsigned int irq, int fd, int type,
+                  irqreturn_t (*handler)(int, void *, struct pt_regs *),
+                  unsigned long irqflags, const char * devname,
+                  void *dev_id)
+{
+       int err;
+
+       err = request_irq(irq, handler, irqflags, devname, dev_id);
+       if (err)
+               return err;
+
+       if (fd != -1)
+               err = activate_fd(irq, fd, type, dev_id);
+       return err;
+}
+EXPORT_SYMBOL(um_request_irq);
+EXPORT_SYMBOL(reactivate_fd);
+
+/* hw_interrupt_type must define (startup || enable) &&
+ * (shutdown || disable) && end */
+static void dummy(unsigned int irq)
+{
+}
+
+/* This is used for everything else than the timer. */
+static struct hw_interrupt_type normal_irq_type = {
+       .typename = "SIGIO",
+       .release = free_irq_by_irq_and_dev,
+       .disable = dummy,
+       .enable = dummy,
+       .ack = dummy,
+       .end = dummy
+};
+
+static struct hw_interrupt_type SIGVTALRM_irq_type = {
+       .typename = "SIGVTALRM",
+       .release = free_irq_by_irq_and_dev,
+       .shutdown = dummy, /* never called */
+       .disable = dummy,
+       .enable = dummy,
+       .ack = dummy,
+       .end = dummy
+};
+
+void __init init_IRQ(void)
+{
+       int i;
+
+       irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
+       irq_desc[TIMER_IRQ].action = NULL;
+       irq_desc[TIMER_IRQ].depth = 1;
+       irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type;
+       enable_irq(TIMER_IRQ);
+       for (i = 1; i < NR_IRQS; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 1;
+               irq_desc[i].chip = &normal_irq_type;
+               enable_irq(i);
+       }
+}
+
+int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
+                                                            struct pt_regs *))
+{
+       int fds[2], err;
+
+       err = os_pipe(fds, 1, 1);
+       if (err) {
+               printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
+               goto out;
+       }
+
+       err = um_request_irq(irq, fds[0], IRQ_READ, handler,
+                            IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name,
+                            (void *) (long) fds[0]);
+       if (err) {
+               printk("init_aio_irq - : um_request_irq failed, err = %d\n",
+                      err);
+               goto out_close;
+       }
+
+       err = fds[1];
+       goto out;
+
+ out_close:
+       os_close_file(fds[0]);
+       os_close_file(fds[1]);
+ out:
+       return err;
+}
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
new file mode 100644 (file)
index 0000000..0ad755c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/list.h"
+#include "linux/slab.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
+#include "init.h"
+#include "sigio.h"
+#include "irq_user.h"
+#include "irq_kern.h"
+#include "os.h"
+
+/* Protected by sigio_lock() called from write_sigio_workaround */
+static int sigio_irq_fd = -1;
+
+static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+{
+       char c;
+
+       os_read_file(sigio_irq_fd, &c, sizeof(c));
+       reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
+       return(IRQ_HANDLED);
+}
+
+int write_sigio_irq(int fd)
+{
+       int err;
+
+       err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
+                            IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
+                            NULL);
+       if(err){
+               printk("write_sigio_irq : um_request_irq failed, err = %d\n",
+                      err);
+               return(-1);
+       }
+       sigio_irq_fd = fd;
+       return(0);
+}
+
+static DEFINE_SPINLOCK(sigio_spinlock);
+
+void sigio_lock(void)
+{
+       spin_lock(&sigio_spinlock);
+}
+
+void sigio_unlock(void)
+{
+       spin_unlock(&sigio_spinlock);
+}
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
new file mode 100644 (file)
index 0000000..2a32e5e
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/sys.h"
+#include "linux/sched.h"
+#include "linux/wait.h"
+#include "linux/kernel.h"
+#include "linux/smp_lock.h"
+#include "linux/module.h"
+#include "linux/slab.h"
+#include "linux/tty.h"
+#include "linux/binfmts.h"
+#include "linux/ptrace.h"
+#include "asm/signal.h"
+#include "asm/uaccess.h"
+#include "asm/unistd.h"
+#include "user_util.h"
+#include "asm/ucontext.h"
+#include "kern_util.h"
+#include "signal_kern.h"
+#include "kern.h"
+#include "frame_kern.h"
+#include "sigcontext.h"
+#include "mode.h"
+
+EXPORT_SYMBOL(block_signals);
+EXPORT_SYMBOL(unblock_signals);
+
+#define _S(nr) (1<<((nr)-1))
+
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+/*
+ * OK, we're invoking a handler
+ */
+static int handle_signal(struct pt_regs *regs, unsigned long signr,
+                        struct k_sigaction *ka, siginfo_t *info,
+                        sigset_t *oldset)
+{
+       unsigned long sp;
+       int err;
+
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+       /* Did we come from a system call? */
+       if(PT_REGS_SYSCALL_NR(regs) >= 0){
+               /* If so, check system call restarting.. */
+               switch(PT_REGS_SYSCALL_RET(regs)){
+               case -ERESTART_RESTARTBLOCK:
+               case -ERESTARTNOHAND:
+                       PT_REGS_SYSCALL_RET(regs) = -EINTR;
+                       break;
+
+               case -ERESTARTSYS:
+                       if (!(ka->sa.sa_flags & SA_RESTART)) {
+                               PT_REGS_SYSCALL_RET(regs) = -EINTR;
+                               break;
+                       }
+               /* fallthrough */
+               case -ERESTARTNOINTR:
+                       PT_REGS_RESTART_SYSCALL(regs);
+                       PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
+                       break;
+               }
+       }
+
+       sp = PT_REGS_SP(regs);
+       if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+               sp = current->sas_ss_sp + current->sas_ss_size;
+
+#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
+       if(!(ka->sa.sa_flags & SA_SIGINFO))
+               err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
+       else
+#endif
+               err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
+
+       if(err){
+               spin_lock_irq(&current->sighand->siglock);
+               current->blocked = *oldset;
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+               force_sigsegv(signr, current);
+       } else {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked, &current->blocked,
+                         &ka->sa.sa_mask);
+                if(!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked, signr);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
+
+       return err;
+}
+
+static int kern_do_signal(struct pt_regs *regs)
+{
+       struct k_sigaction ka_copy;
+       siginfo_t info;
+       sigset_t *oldset;
+       int sig, handled_sig = 0;
+
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
+               oldset = &current->blocked;
+
+       while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
+               handled_sig = 1;
+               /* Whee!  Actually deliver the signal.  */
+               if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       break;
+               }
+       }
+
+       /* Did we come from a system call? */
+       if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
+               /* Restart the system call - no handlers present */
+               switch(PT_REGS_SYSCALL_RET(regs)){
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
+                       PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
+                       PT_REGS_RESTART_SYSCALL(regs);
+                       break;
+               case -ERESTART_RESTARTBLOCK:
+                       PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall;
+                       PT_REGS_RESTART_SYSCALL(regs);
+                       break;
+               }
+       }
+
+       /* This closes a way to execute a system call on the host.  If
+        * you set a breakpoint on a system call instruction and singlestep
+        * from it, the tracing thread used to PTRACE_SINGLESTEP the process
+        * rather than PTRACE_SYSCALL it, allowing the system call to execute
+        * on the host.  The tracing thread will check this flag and
+        * PTRACE_SYSCALL if necessary.
+        */
+       if(current->ptrace & PT_DTRACE)
+               current->thread.singlestep_syscall =
+                       is_syscall(PT_REGS_IP(&current->thread.regs));
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back */
+       if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+       return(handled_sig);
+}
+
+int do_signal(void)
+{
+       return(kern_do_signal(&current->thread.regs));
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+{
+       mask &= _BLOCKABLE;
+       spin_lock_irq(&current->sighand->siglock);
+       current->saved_sigmask = current->blocked;
+       siginitset(&current->blocked, mask);
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
+}
+
+long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+       return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
+}
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
new file mode 100644 (file)
index 0000000..8c90a63
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "asm/errno.h"
+#include "linux/sched.h"
+#include "linux/mm.h"
+#include "linux/spinlock.h"
+#include "linux/init.h"
+#include "linux/ptrace.h"
+#include "asm/semaphore.h"
+#include "asm/pgtable.h"
+#include "asm/pgalloc.h"
+#include "asm/tlbflush.h"
+#include "asm/a.out.h"
+#include "asm/current.h"
+#include "asm/irq.h"
+#include "sysdep/sigcontext.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "kern.h"
+#include "chan_kern.h"
+#include "mconsole_kern.h"
+#include "mem.h"
+#include "mem_kern.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/ptrace.h"
+#include "os.h"
+#ifdef CONFIG_MODE_SKAS
+#include "skas.h"
+#endif
+#include "os.h"
+
+/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
+int handle_page_fault(unsigned long address, unsigned long ip,
+                     int is_write, int is_user, int *code_out)
+{
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       int err = -EFAULT;
+
+       *code_out = SEGV_MAPERR;
+
+       /* If the fault was during atomic operation, don't take the fault, just
+        * fail. */
+       if (in_atomic())
+               goto out_nosemaphore;
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, address);
+       if(!vma)
+               goto out;
+       else if(vma->vm_start <= address)
+               goto good_area;
+       else if(!(vma->vm_flags & VM_GROWSDOWN))
+               goto out;
+       else if(is_user && !ARCH_IS_STACKGROW(address))
+               goto out;
+       else if(expand_stack(vma, address))
+               goto out;
+
+good_area:
+       *code_out = SEGV_ACCERR;
+       if(is_write && !(vma->vm_flags & VM_WRITE))
+               goto out;
+
+       /* Don't require VM_READ|VM_EXEC for write faults! */
+        if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
+                goto out;
+
+       do {
+survive:
+               switch (handle_mm_fault(mm, vma, address, is_write)){
+               case VM_FAULT_MINOR:
+                       current->min_flt++;
+                       break;
+               case VM_FAULT_MAJOR:
+                       current->maj_flt++;
+                       break;
+               case VM_FAULT_SIGBUS:
+                       err = -EACCES;
+                       goto out;
+               case VM_FAULT_OOM:
+                       err = -ENOMEM;
+                       goto out_of_memory;
+               default:
+                       BUG();
+               }
+               pgd = pgd_offset(mm, address);
+               pud = pud_offset(pgd, address);
+               pmd = pmd_offset(pud, address);
+               pte = pte_offset_kernel(pmd, address);
+       } while(!pte_present(*pte));
+       err = 0;
+       /* The below warning was added in place of
+        *      pte_mkyoung(); if (is_write) pte_mkdirty();
+        * If it's triggered, we'd see normally a hang here (a clean pte is
+        * marked read-only to emulate the dirty bit).
+        * However, the generic code can mark a PTE writable but clean on a
+        * concurrent read fault, triggering this harmlessly. So comment it out.
+        */
+#if 0
+       WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
+#endif
+       flush_tlb_page(vma, address);
+out:
+       up_read(&mm->mmap_sem);
+out_nosemaphore:
+       return(err);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+       if (current->pid == 1) {
+               up_read(&mm->mmap_sem);
+               yield();
+               down_read(&mm->mmap_sem);
+               goto survive;
+       }
+       goto out;
+}
+
+void segv_handler(int sig, union uml_pt_regs *regs)
+{
+       struct faultinfo * fi = UPT_FAULTINFO(regs);
+
+       if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
+               bad_segv(*fi, UPT_IP(regs));
+               return;
+       }
+       segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
+}
+
+struct kern_handlers handlinfo_kern = {
+       .relay_signal = relay_signal,
+       .winch = winch,
+       .bus_handler = relay_signal,
+       .page_fault = segv_handler,
+       .sigio_handler = sigio_handler,
+       .timer_handler = timer_handler
+};
+/*
+ * We give a *copy* of the faultinfo in the regs to segv.
+ * This must be done, since nesting SEGVs could overwrite
+ * the info in the regs. A pointer to the info then would
+ * give us bad data!
+ */
+unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
+{
+       struct siginfo si;
+       void *catcher;
+       int err;
+        int is_write = FAULT_WRITE(fi);
+        unsigned long address = FAULT_ADDRESS(fi);
+
+        if(!is_user && (address >= start_vm) && (address < end_vm)){
+                flush_tlb_kernel_vm();
+                return(0);
+        }
+       else if(current->mm == NULL)
+               panic("Segfault with no mm");
+
+       if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
+               err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
+       else {
+               err = -EFAULT;
+               /* A thread accessed NULL, we get a fault, but CR2 is invalid.
+                * This code is used in __do_copy_from_user() of TT mode. */
+               address = 0;
+       }
+
+       catcher = current->thread.fault_catcher;
+       if(!err)
+               return(0);
+       else if(catcher != NULL){
+               current->thread.fault_addr = (void *) address;
+               do_longjmp(catcher, 1);
+       }
+       else if(current->thread.fault_addr != NULL)
+               panic("fault_addr set but no fault catcher");
+        else if(!is_user && arch_fixup(ip, sc))
+               return(0);
+
+       if(!is_user)
+               panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
+                     address, ip);
+
+       if (err == -EACCES) {
+               si.si_signo = SIGBUS;
+               si.si_errno = 0;
+               si.si_code = BUS_ADRERR;
+               si.si_addr = (void __user *)address;
+                current->thread.arch.faultinfo = fi;
+               force_sig_info(SIGBUS, &si, current);
+       } else if (err == -ENOMEM) {
+               printk("VM: killing process %s\n", current->comm);
+               do_exit(SIGKILL);
+       } else {
+               BUG_ON(err != -EFAULT);
+               si.si_signo = SIGSEGV;
+               si.si_addr = (void __user *) address;
+                current->thread.arch.faultinfo = fi;
+               force_sig_info(SIGSEGV, &si, current);
+       }
+       return(0);
+}
+
+void bad_segv(struct faultinfo fi, unsigned long ip)
+{
+       struct siginfo si;
+
+       si.si_signo = SIGSEGV;
+       si.si_code = SEGV_ACCERR;
+       si.si_addr = (void __user *) FAULT_ADDRESS(fi);
+       current->thread.arch.faultinfo = fi;
+       force_sig_info(SIGSEGV, &si, current);
+}
+
+void relay_signal(int sig, union uml_pt_regs *regs)
+{
+       if(arch_handle_signal(sig, regs)) return;
+       if(!UPT_IS_USER(regs))
+               panic("Kernel mode signal %d", sig);
+        current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
+       force_sig(sig, current);
+}
+
+void bus_handler(int sig, union uml_pt_regs *regs)
+{
+       if(current->thread.fault_catcher != NULL)
+               do_longjmp(current->thread.fault_catcher, 1);
+       else relay_signal(sig, regs);
+}
+
+void winch(int sig, union uml_pt_regs *regs)
+{
+       do_IRQ(WINCH_IRQ, regs);
+}
+
+void trap_init(void)
+{
+}
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c
new file mode 100644 (file)
index 0000000..92d7d0c
--- /dev/null
@@ -0,0 +1,37 @@
+#include <asm-i386/unistd.h>
+
+unsigned ia32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned ia32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned ia32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned ia32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int ia32_classify_syscall(unsigned syscall)
+{
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_socketcall:
+               return 4;
+       case __NR_execve:
+               return 5;
+       default:
+               return 1;
+       }
+}
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c
new file mode 100644 (file)
index 0000000..21f3338
--- /dev/null
@@ -0,0 +1,64 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_IA32_EMULATION
+       extern int ia32_classify_syscall(unsigned);
+       if (abi == AUDIT_ARCH_I386)
+               return ia32_classify_syscall(syscall);
+#endif
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+       case __NR_openat:
+               return 3;
+       case __NR_execve:
+               return 5;
+       default:
+               return 0;
+       }
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_IA32_EMULATION
+       extern __u32 ia32_dir_class[];
+       extern __u32 ia32_write_class[];
+       extern __u32 ia32_read_class[];
+       extern __u32 ia32_chattr_class[];
+       audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
+       audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+#endif
+       audit_register_class(AUDIT_CLASS_WRITE, write_class);
+       audit_register_class(AUDIT_CLASS_READ, read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+       return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/x86_64/kernel/irqflags-xen.c b/arch/x86_64/kernel/irqflags-xen.c
new file mode 100644 (file)
index 0000000..e3b7ab5
--- /dev/null
@@ -0,0 +1,100 @@
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <asm/irqflags.h>
+#include <asm/hypervisor.h>
+
+/* 
+ * The use of 'barrier' in the following reflects their use as local-lock
+ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+ * critical operations are executed. All critical operations must complete
+ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+ * includes these barriers, for example.
+ */
+
+unsigned long __raw_local_save_flags(void)
+{
+       struct vcpu_info *_vcpu;
+       unsigned long flags;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       flags = _vcpu->evtchn_upcall_mask;
+       preempt_enable();
+
+       return flags;
+}
+EXPORT_SYMBOL(__raw_local_save_flags);
+
+void raw_local_irq_restore(unsigned long flags)
+{
+       struct vcpu_info *_vcpu;
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       if ((_vcpu->evtchn_upcall_mask = flags) == 0) {
+               barrier(); /* unmask then check (avoid races) */
+               if ( unlikely(_vcpu->evtchn_upcall_pending) )
+                       force_evtchn_callback();
+               preempt_enable();
+       } else
+               preempt_enable_no_resched();
+}
+EXPORT_SYMBOL(raw_local_irq_restore);
+
+void raw_local_irq_disable(void)
+{
+       struct vcpu_info *_vcpu;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       _vcpu->evtchn_upcall_mask = 1;
+       preempt_enable_no_resched();
+}
+EXPORT_SYMBOL(raw_local_irq_disable);
+
+void raw_local_irq_enable(void)
+{
+       struct vcpu_info *_vcpu;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       _vcpu->evtchn_upcall_mask = 0;
+       barrier(); /* unmask then check (avoid races) */
+       if ( unlikely(_vcpu->evtchn_upcall_pending) )
+               force_evtchn_callback();
+       preempt_enable();
+}
+EXPORT_SYMBOL(raw_local_irq_enable);
+
+/*
+ * For spinlocks, etc.:
+ */
+
+unsigned long __raw_local_irq_save(void)
+{
+       struct vcpu_info *_vcpu;
+       unsigned long flags;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       flags = _vcpu->evtchn_upcall_mask;
+       _vcpu->evtchn_upcall_mask = 1;
+       preempt_enable_no_resched();
+
+       return flags;
+}
+EXPORT_SYMBOL(__raw_local_irq_save);
+
+/* Cannot use preempt_enable() here as we would recurse in preempt_sched(). */
+int raw_irqs_disabled(void)
+{
+       struct vcpu_info *_vcpu;
+       int disabled;
+
+       preempt_disable();
+       _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id];
+       disabled = (_vcpu->evtchn_upcall_mask != 0);
+       preempt_enable_no_resched();
+
+       return disabled;
+}
+EXPORT_SYMBOL(raw_irqs_disabled);
diff --git a/arch/x86_64/kernel/k8.c b/arch/x86_64/kernel/k8.c
new file mode 100644 (file)
index 0000000..6416682
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Shared support code for AMD K8 northbridges and derivates.
+ * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
+ */
+#include <linux/gfp.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/k8.h>
+
+int num_k8_northbridges;
+EXPORT_SYMBOL(num_k8_northbridges);
+
+static u32 *flush_words;
+
+struct pci_device_id k8_nb_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
+       {}
+};
+EXPORT_SYMBOL(k8_nb_ids);
+
+struct pci_dev **k8_northbridges;
+EXPORT_SYMBOL(k8_northbridges);
+
+static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
+{
+       do {
+               dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+               if (!dev)
+                       break;
+       } while (!pci_match_id(&k8_nb_ids[0], dev));
+       return dev;
+}
+
+int cache_k8_northbridges(void)
+{
+       int i;
+       struct pci_dev *dev;
+       if (num_k8_northbridges)
+               return 0;
+
+       num_k8_northbridges = 0;
+       dev = NULL;
+       while ((dev = next_k8_northbridge(dev)) != NULL)
+               num_k8_northbridges++;
+
+       k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *),
+                                 GFP_KERNEL);
+       if (!k8_northbridges)
+               return -ENOMEM;
+
+       flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
+       if (!flush_words) {
+               kfree(k8_northbridges);
+               return -ENOMEM;
+       }
+
+       dev = NULL;
+       i = 0;
+       while ((dev = next_k8_northbridge(dev)) != NULL) {
+               k8_northbridges[i++] = dev;
+               pci_read_config_dword(dev, 0x9c, &flush_words[i]);
+       }
+       k8_northbridges[i] = NULL;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cache_k8_northbridges);
+
+/* Ignores subdevice/subvendor but as far as I can figure out
+   they're useless anyways */
+int __init early_is_k8_nb(u32 device)
+{
+       struct pci_device_id *id;
+       u32 vendor = device & 0xffff;
+       device >>= 16;
+       for (id = k8_nb_ids; id->vendor; id++)
+               if (vendor == id->vendor && device == id->device)
+                       return 1;
+       return 0;
+}
+
+void k8_flush_garts(void)
+{
+       int flushed, i;
+       unsigned long flags;
+       static DEFINE_SPINLOCK(gart_lock);
+
+       /* Avoid races between AGP and IOMMU. In theory it's not needed
+          but I'm not sure if the hardware won't lose flush requests
+          when another is pending. This whole thing is so expensive anyways
+          that it doesn't matter to serialize more. -AK */
+       spin_lock_irqsave(&gart_lock, flags);
+       flushed = 0;
+       for (i = 0; i < num_k8_northbridges; i++) {
+               pci_write_config_dword(k8_northbridges[i], 0x9c,
+                                      flush_words[i]|1);
+               flushed++;
+       }
+       for (i = 0; i < num_k8_northbridges; i++) {
+               u32 w;
+               /* Make sure the hardware actually executed the flush*/
+               for (;;) {
+                       pci_read_config_dword(k8_northbridges[i],
+                                             0x9c, &w);
+                       if (!(w & 1))
+                               break;
+                       cpu_relax();
+               }
+       }
+       spin_unlock_irqrestore(&gart_lock, flags);
+       if (!flushed)
+               printk("nothing to flush?\n");
+}
+EXPORT_SYMBOL_GPL(k8_flush_garts);
+
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
new file mode 100644 (file)
index 0000000..61ffebb
--- /dev/null
@@ -0,0 +1,1039 @@
+/*
+ * Derived from arch/powerpc/kernel/iommu.c
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Jon Mason <jdmason@us.ibm.com>
+ * Author: Muli Ben-Yehuda <muli@il.ibm.com>
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/proto.h>
+#include <asm/calgary.h>
+#include <asm/tce.h>
+#include <asm/pci-direct.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+
+#define PCI_DEVICE_ID_IBM_CALGARY 0x02a1
+#define PCI_VENDOR_DEVICE_ID_CALGARY \
+       (PCI_VENDOR_ID_IBM | PCI_DEVICE_ID_IBM_CALGARY << 16)
+
+/* we need these for register space address calculation */
+#define START_ADDRESS           0xfe000000
+#define CHASSIS_BASE            0
+#define ONE_BASED_CHASSIS_NUM   1
+
+/* register offsets inside the host bridge space */
+#define PHB_CSR_OFFSET         0x0110
+#define PHB_PLSSR_OFFSET       0x0120
+#define PHB_CONFIG_RW_OFFSET   0x0160
+#define PHB_IOBASE_BAR_LOW     0x0170
+#define PHB_IOBASE_BAR_HIGH    0x0180
+#define PHB_MEM_1_LOW          0x0190
+#define PHB_MEM_1_HIGH         0x01A0
+#define PHB_IO_ADDR_SIZE       0x01B0
+#define PHB_MEM_1_SIZE         0x01C0
+#define PHB_MEM_ST_OFFSET      0x01D0
+#define PHB_AER_OFFSET         0x0200
+#define PHB_CONFIG_0_HIGH      0x0220
+#define PHB_CONFIG_0_LOW       0x0230
+#define PHB_CONFIG_0_END       0x0240
+#define PHB_MEM_2_LOW          0x02B0
+#define PHB_MEM_2_HIGH         0x02C0
+#define PHB_MEM_2_SIZE_HIGH    0x02D0
+#define PHB_MEM_2_SIZE_LOW     0x02E0
+#define PHB_DOSHOLE_OFFSET     0x08E0
+
+/* PHB_CONFIG_RW */
+#define PHB_TCE_ENABLE         0x20000000
+#define PHB_SLOT_DISABLE       0x1C000000
+#define PHB_DAC_DISABLE                0x01000000
+#define PHB_MEM2_ENABLE                0x00400000
+#define PHB_MCSR_ENABLE                0x00100000
+/* TAR (Table Address Register) */
+#define TAR_SW_BITS            0x0000ffffffff800fUL
+#define TAR_VALID              0x0000000000000008UL
+/* CSR (Channel/DMA Status Register) */
+#define CSR_AGENT_MASK         0xffe0ffff
+
+#define MAX_NUM_OF_PHBS                8 /* how many PHBs in total? */
+#define MAX_NUM_CHASSIS                8 /* max number of chassis */
+#define MAX_PHB_BUS_NUM                (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */
+#define PHBS_PER_CALGARY       4
+
+/* register offsets in Calgary's internal register space */
+static const unsigned long tar_offsets[] = {
+       0x0580 /* TAR0 */,
+       0x0588 /* TAR1 */,
+       0x0590 /* TAR2 */,
+       0x0598 /* TAR3 */
+};
+
+static const unsigned long split_queue_offsets[] = {
+       0x4870 /* SPLIT QUEUE 0 */,
+       0x5870 /* SPLIT QUEUE 1 */,
+       0x6870 /* SPLIT QUEUE 2 */,
+       0x7870 /* SPLIT QUEUE 3 */
+};
+
+static const unsigned long phb_offsets[] = {
+       0x8000 /* PHB0 */,
+       0x9000 /* PHB1 */,
+       0xA000 /* PHB2 */,
+       0xB000 /* PHB3 */
+};
+
+static char bus_to_phb[MAX_PHB_BUS_NUM];
+void* tce_table_kva[MAX_PHB_BUS_NUM];
+unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
+static int translate_empty_slots __read_mostly = 0;
+static int calgary_detected __read_mostly = 0;
+
+/*
+ * the bitmap of PHBs the user requested that we disable
+ * translation on.
+ */
+static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM);
+
+static void tce_cache_blast(struct iommu_table *tbl);
+
+/* enable this to stress test the chip's TCE cache */
+#ifdef CONFIG_IOMMU_DEBUG
+static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+{
+       tce_cache_blast(tbl);
+}
+#else
+static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+{
+}
+#endif /* BLAST_TCE_CACHE_ON_UNMAP */
+
+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 translate_phb(struct pci_dev* dev)
+{
+       int disabled = test_bit(dev->bus->number, translation_disabled);
+       return !disabled;
+}
+
+static void iommu_range_reserve(struct iommu_table *tbl,
+        unsigned long start_addr, unsigned int npages)
+{
+       unsigned long index;
+       unsigned long end;
+
+       index = start_addr >> PAGE_SHIFT;
+
+       /* bail out if we're asked to reserve a region we don't cover */
+       if (index >= tbl->it_size)
+               return;
+
+       end = index + npages;
+       if (end > tbl->it_size) /* don't go off the table */
+               end = tbl->it_size;
+
+       while (index < end) {
+               if (test_bit(index, tbl->it_map))
+                       printk(KERN_ERR "Calgary: entry already allocated at "
+                              "0x%lx tbl %p dma 0x%lx npages %u\n",
+                              index, tbl, start_addr, npages);
+               ++index;
+       }
+       set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages);
+}
+
+static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+       unsigned int npages)
+{
+       unsigned long offset;
+
+       BUG_ON(npages == 0);
+
+       offset = find_next_zero_string(tbl->it_map, tbl->it_hint,
+                                      tbl->it_size, npages);
+       if (offset == ~0UL) {
+               tce_cache_blast(tbl);
+               offset = find_next_zero_string(tbl->it_map, 0,
+                                              tbl->it_size, npages);
+               if (offset == ~0UL) {
+                       printk(KERN_WARNING "Calgary: IOMMU full.\n");
+                       if (panic_on_overflow)
+                               panic("Calgary: fix the allocator.\n");
+                       else
+                               return bad_dma_address;
+               }
+       }
+
+       set_bit_string(tbl->it_map, offset, npages);
+       tbl->it_hint = offset + npages;
+       BUG_ON(tbl->it_hint > tbl->it_size);
+
+       return offset;
+}
+
+static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr,
+       unsigned int npages, int direction)
+{
+       unsigned long entry, flags;
+       dma_addr_t ret = bad_dma_address;
+
+       spin_lock_irqsave(&tbl->it_lock, flags);
+
+       entry = iommu_range_alloc(tbl, npages);
+
+       if (unlikely(entry == bad_dma_address))
+               goto error;
+
+       /* set the return dma address */
+       ret = (entry << PAGE_SHIFT) | ((unsigned long)vaddr & ~PAGE_MASK);
+
+       /* put the TCEs in the HW table */
+       tce_build(tbl, entry, npages, (unsigned long)vaddr & PAGE_MASK,
+                 direction);
+
+       spin_unlock_irqrestore(&tbl->it_lock, flags);
+
+       return ret;
+
+error:
+       spin_unlock_irqrestore(&tbl->it_lock, flags);
+       printk(KERN_WARNING "Calgary: failed to allocate %u pages in "
+              "iommu %p\n", npages, tbl);
+       return bad_dma_address;
+}
+
+static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+       unsigned int npages)
+{
+       unsigned long entry;
+       unsigned long i;
+
+       entry = dma_addr >> PAGE_SHIFT;
+
+       BUG_ON(entry + npages > tbl->it_size);
+
+       tce_free(tbl, entry, npages);
+
+       for (i = 0; i < npages; ++i) {
+               if (!test_bit(entry + i, tbl->it_map))
+                       printk(KERN_ERR "Calgary: bit is off at 0x%lx "
+                              "tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
+                              entry + i, tbl, dma_addr, entry, npages);
+       }
+
+       __clear_bit_string(tbl->it_map, entry, npages);
+
+       tce_cache_blast_stress(tbl);
+}
+
+static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+       unsigned int npages)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&tbl->it_lock, flags);
+
+       __iommu_free(tbl, dma_addr, npages);
+
+       spin_unlock_irqrestore(&tbl->it_lock, flags);
+}
+
+static void __calgary_unmap_sg(struct iommu_table *tbl,
+       struct scatterlist *sglist, int nelems, int direction)
+{
+       while (nelems--) {
+               unsigned int npages;
+               dma_addr_t dma = sglist->dma_address;
+               unsigned int dmalen = sglist->dma_length;
+
+               if (dmalen == 0)
+                       break;
+
+               npages = num_dma_pages(dma, dmalen);
+               __iommu_free(tbl, dma, npages);
+               sglist++;
+       }
+}
+
+void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist,
+                     int nelems, int direction)
+{
+       unsigned long flags;
+       struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+
+       if (!translate_phb(to_pci_dev(dev)))
+               return;
+
+       spin_lock_irqsave(&tbl->it_lock, flags);
+
+       __calgary_unmap_sg(tbl, sglist, nelems, direction);
+
+       spin_unlock_irqrestore(&tbl->it_lock, flags);
+}
+
+static int calgary_nontranslate_map_sg(struct device* dev,
+       struct scatterlist *sg, int nelems, int direction)
+{
+       int i;
+
+       for (i = 0; i < nelems; i++ ) {
+               struct scatterlist *s = &sg[i];
+               BUG_ON(!s->page);
+               s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
+               s->dma_length = s->length;
+       }
+       return nelems;
+}
+
+int calgary_map_sg(struct device *dev, struct scatterlist *sg,
+       int nelems, int direction)
+{
+       struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+       unsigned long flags;
+       unsigned long vaddr;
+       unsigned int npages;
+       unsigned long entry;
+       int i;
+
+       if (!translate_phb(to_pci_dev(dev)))
+               return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
+
+       spin_lock_irqsave(&tbl->it_lock, flags);
+
+       for (i = 0; i < nelems; i++ ) {
+               struct scatterlist *s = &sg[i];
+               BUG_ON(!s->page);
+
+               vaddr = (unsigned long)page_address(s->page) + s->offset;
+               npages = num_dma_pages(vaddr, s->length);
+
+               entry = iommu_range_alloc(tbl, npages);
+               if (entry == bad_dma_address) {
+                       /* makes sure unmap knows to stop */
+                       s->dma_length = 0;
+                       goto error;
+               }
+
+               s->dma_address = (entry << PAGE_SHIFT) | s->offset;
+
+               /* insert into HW table */
+               tce_build(tbl, entry, npages, vaddr & PAGE_MASK,
+                         direction);
+
+               s->dma_length = s->length;
+       }
+
+       spin_unlock_irqrestore(&tbl->it_lock, flags);
+
+       return nelems;
+error:
+       __calgary_unmap_sg(tbl, sg, nelems, direction);
+       for (i = 0; i < nelems; i++) {
+               sg[i].dma_address = bad_dma_address;
+               sg[i].dma_length = 0;
+       }
+       spin_unlock_irqrestore(&tbl->it_lock, flags);
+       return 0;
+}
+
+dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
+       size_t size, int direction)
+{
+       dma_addr_t dma_handle = bad_dma_address;
+       unsigned long uaddr;
+       unsigned int npages;
+       struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+
+       uaddr = (unsigned long)vaddr;
+       npages = num_dma_pages(uaddr, size);
+
+       if (translate_phb(to_pci_dev(dev)))
+               dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
+       else
+               dma_handle = virt_to_bus(vaddr);
+
+       return dma_handle;
+}
+
+void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
+       size_t size, int direction)
+{
+       struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+       unsigned int npages;
+
+       if (!translate_phb(to_pci_dev(dev)))
+               return;
+
+       npages = num_dma_pages(dma_handle, size);
+       iommu_free(tbl, dma_handle, npages);
+}
+
+void* calgary_alloc_coherent(struct device *dev, size_t size,
+       dma_addr_t *dma_handle, gfp_t flag)
+{
+       void *ret = NULL;
+       dma_addr_t mapping;
+       unsigned int npages, order;
+       struct iommu_table *tbl;
+
+       tbl = to_pci_dev(dev)->bus->self->sysdata;
+
+       size = PAGE_ALIGN(size); /* size rounded up to full pages */
+       npages = size >> PAGE_SHIFT;
+       order = get_order(size);
+
+       /* alloc enough pages (and possibly more) */
+       ret = (void *)__get_free_pages(flag, order);
+       if (!ret)
+               goto error;
+       memset(ret, 0, size);
+
+       if (translate_phb(to_pci_dev(dev))) {
+               /* set up tces to cover the allocated range */
+               mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
+               if (mapping == bad_dma_address)
+                       goto free;
+
+               *dma_handle = mapping;
+       } else /* non translated slot */
+               *dma_handle = virt_to_bus(ret);
+
+       return ret;
+
+free:
+       free_pages((unsigned long)ret, get_order(size));
+       ret = NULL;
+error:
+       return ret;
+}
+
+static struct dma_mapping_ops calgary_dma_ops = {
+       .alloc_coherent = calgary_alloc_coherent,
+       .map_single = calgary_map_single,
+       .unmap_single = calgary_unmap_single,
+       .map_sg = calgary_map_sg,
+       .unmap_sg = calgary_unmap_sg,
+};
+
+static inline int busno_to_phbid(unsigned char num)
+{
+       return bus_to_phb[num];
+}
+
+static inline unsigned long split_queue_offset(unsigned char num)
+{
+       size_t idx = busno_to_phbid(num);
+
+       return split_queue_offsets[idx];
+}
+
+static inline unsigned long tar_offset(unsigned char num)
+{
+       size_t idx = busno_to_phbid(num);
+
+       return tar_offsets[idx];
+}
+
+static inline unsigned long phb_offset(unsigned char num)
+{
+       size_t idx = busno_to_phbid(num);
+
+       return phb_offsets[idx];
+}
+
+static inline void __iomem* calgary_reg(void __iomem *bar, unsigned long offset)
+{
+       unsigned long target = ((unsigned long)bar) | offset;
+       return (void __iomem*)target;
+}
+
+static void tce_cache_blast(struct iommu_table *tbl)
+{
+       u64 val;
+       u32 aer;
+       int i = 0;
+       void __iomem *bbar = tbl->bbar;
+       void __iomem *target;
+
+       /* disable arbitration on the bus */
+       target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET);
+       aer = readl(target);
+       writel(0, target);
+
+       /* read plssr to ensure it got there */
+       target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_PLSSR_OFFSET);
+       val = readl(target);
+
+       /* poll split queues until all DMA activity is done */
+       target = calgary_reg(bbar, split_queue_offset(tbl->it_busno));
+       do {
+               val = readq(target);
+               i++;
+       } while ((val & 0xff) != 0xff && i < 100);
+       if (i == 100)
+               printk(KERN_WARNING "Calgary: PCI bus not quiesced, "
+                      "continuing anyway\n");
+
+       /* invalidate TCE cache */
+       target = calgary_reg(bbar, tar_offset(tbl->it_busno));
+       writeq(tbl->tar_val, target);
+
+       /* enable arbitration */
+       target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET);
+       writel(aer, target);
+       (void)readl(target); /* flush */
+}
+
+static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start,
+       u64 limit)
+{
+       unsigned int numpages;
+
+       limit = limit | 0xfffff;
+       limit++;
+
+       numpages = ((limit - start) >> PAGE_SHIFT);
+       iommu_range_reserve(dev->sysdata, start, numpages);
+}
+
+static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev)
+{
+       void __iomem *target;
+       u64 low, high, sizelow;
+       u64 start, limit;
+       struct iommu_table *tbl = dev->sysdata;
+       unsigned char busnum = dev->bus->number;
+       void __iomem *bbar = tbl->bbar;
+
+       /* peripheral MEM_1 region */
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_LOW);
+       low = be32_to_cpu(readl(target));
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_HIGH);
+       high = be32_to_cpu(readl(target));
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_SIZE);
+       sizelow = be32_to_cpu(readl(target));
+
+       start = (high << 32) | low;
+       limit = sizelow;
+
+       calgary_reserve_mem_region(dev, start, limit);
+}
+
+static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev)
+{
+       void __iomem *target;
+       u32 val32;
+       u64 low, high, sizelow, sizehigh;
+       u64 start, limit;
+       struct iommu_table *tbl = dev->sysdata;
+       unsigned char busnum = dev->bus->number;
+       void __iomem *bbar = tbl->bbar;
+
+       /* is it enabled? */
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET);
+       val32 = be32_to_cpu(readl(target));
+       if (!(val32 & PHB_MEM2_ENABLE))
+               return;
+
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_LOW);
+       low = be32_to_cpu(readl(target));
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_HIGH);
+       high = be32_to_cpu(readl(target));
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_LOW);
+       sizelow = be32_to_cpu(readl(target));
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_HIGH);
+       sizehigh = be32_to_cpu(readl(target));
+
+       start = (high << 32) | low;
+       limit = (sizehigh << 32) | sizelow;
+
+       calgary_reserve_mem_region(dev, start, limit);
+}
+
+/*
+ * some regions of the IO address space do not get translated, so we
+ * must not give devices IO addresses in those regions. The regions
+ * are the 640KB-1MB region and the two PCI peripheral memory holes.
+ * Reserve all of them in the IOMMU bitmap to avoid giving them out
+ * later.
+ */
+static void __init calgary_reserve_regions(struct pci_dev *dev)
+{
+       unsigned int npages;
+       void __iomem *bbar;
+       unsigned char busnum;
+       u64 start;
+       struct iommu_table *tbl = dev->sysdata;
+
+       bbar = tbl->bbar;
+       busnum = dev->bus->number;
+
+       /* reserve bad_dma_address in case it's a legal address */
+       iommu_range_reserve(tbl, bad_dma_address, 1);
+
+       /* avoid the BIOS/VGA first 640KB-1MB region */
+       start = (640 * 1024);
+       npages = ((1024 - 640) * 1024) >> PAGE_SHIFT;
+       iommu_range_reserve(tbl, start, npages);
+
+       /* reserve the two PCI peripheral memory regions in IO space */
+       calgary_reserve_peripheral_mem_1(dev);
+       calgary_reserve_peripheral_mem_2(dev);
+}
+
+static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
+{
+       u64 val64;
+       u64 table_phys;
+       void __iomem *target;
+       int ret;
+       struct iommu_table *tbl;
+
+       /* build TCE tables for each PHB */
+       ret = build_tce_table(dev, bbar);
+       if (ret)
+               return ret;
+
+       calgary_reserve_regions(dev);
+
+       /* set TARs for each PHB */
+       target = calgary_reg(bbar, tar_offset(dev->bus->number));
+       val64 = be64_to_cpu(readq(target));
+
+       /* zero out all TAR bits under sw control */
+       val64 &= ~TAR_SW_BITS;
+
+       tbl = dev->sysdata;
+       table_phys = (u64)__pa(tbl->it_base);
+       val64 |= table_phys;
+
+       BUG_ON(specified_table_size > TCE_TABLE_SIZE_8M);
+       val64 |= (u64) specified_table_size;
+
+       tbl->tar_val = cpu_to_be64(val64);
+       writeq(tbl->tar_val, target);
+       readq(target); /* flush */
+
+       return 0;
+}
+
+static void __init calgary_free_tar(struct pci_dev *dev)
+{
+       u64 val64;
+       struct iommu_table *tbl = dev->sysdata;
+       void __iomem *target;
+
+       target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number));
+       val64 = be64_to_cpu(readq(target));
+       val64 &= ~TAR_SW_BITS;
+       writeq(cpu_to_be64(val64), target);
+       readq(target); /* flush */
+
+       kfree(tbl);
+       dev->sysdata = NULL;
+}
+
+static void calgary_watchdog(unsigned long data)
+{
+       struct pci_dev *dev = (struct pci_dev *)data;
+       struct iommu_table *tbl = dev->sysdata;
+       void __iomem *bbar = tbl->bbar;
+       u32 val32;
+       void __iomem *target;
+
+       target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_CSR_OFFSET);
+       val32 = be32_to_cpu(readl(target));
+
+       /* If no error, the agent ID in the CSR is not valid */
+       if (val32 & CSR_AGENT_MASK) {
+               printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, "
+                                 "CSR = %#x\n", dev->bus->number, val32);
+               writel(0, target);
+
+               /* Disable bus that caused the error */
+               target = calgary_reg(bbar, phb_offset(tbl->it_busno) |
+                                          PHB_CONFIG_RW_OFFSET);
+               val32 = be32_to_cpu(readl(target));
+               val32 |= PHB_SLOT_DISABLE;
+               writel(cpu_to_be32(val32), target);
+               readl(target); /* flush */
+       } else {
+               /* Reset the timer */
+               mod_timer(&tbl->watchdog_timer, jiffies + 2 * HZ);
+       }
+}
+
+static void __init calgary_enable_translation(struct pci_dev *dev)
+{
+       u32 val32;
+       unsigned char busnum;
+       void __iomem *target;
+       void __iomem *bbar;
+       struct iommu_table *tbl;
+
+       busnum = dev->bus->number;
+       tbl = dev->sysdata;
+       bbar = tbl->bbar;
+
+       /* enable TCE in PHB Config Register */
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET);
+       val32 = be32_to_cpu(readl(target));
+       val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE;
+
+       printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum);
+       printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this "
+              "bus.\n");
+
+       writel(cpu_to_be32(val32), target);
+       readl(target); /* flush */
+
+       init_timer(&tbl->watchdog_timer);
+       tbl->watchdog_timer.function = &calgary_watchdog;
+       tbl->watchdog_timer.data = (unsigned long)dev;
+       mod_timer(&tbl->watchdog_timer, jiffies);
+}
+
+static void __init calgary_disable_translation(struct pci_dev *dev)
+{
+       u32 val32;
+       unsigned char busnum;
+       void __iomem *target;
+       void __iomem *bbar;
+       struct iommu_table *tbl;
+
+       busnum = dev->bus->number;
+       tbl = dev->sysdata;
+       bbar = tbl->bbar;
+
+       /* disable TCE in PHB Config Register */
+       target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET);
+       val32 = be32_to_cpu(readl(target));
+       val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE);
+
+       printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum);
+       writel(cpu_to_be32(val32), target);
+       readl(target); /* flush */
+
+       del_timer_sync(&tbl->watchdog_timer);
+}
+
+static inline unsigned int __init locate_register_space(struct pci_dev *dev)
+{
+       int rionodeid;
+       u32 address;
+
+       /*
+        * Each Calgary has four busses. The first four busses (first Calgary)
+        * have RIO node ID 2, then the next four (second Calgary) have RIO
+        * node ID 3, the next four (third Calgary) have node ID 2 again, etc.
+        * We use a gross hack - relying on the dev->bus->number ordering,
+        * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1,
+        * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the
+        * second (id 3), and then it repeats modulo 14.
+        */
+       rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2;
+       /*
+        * register space address calculation as follows:
+        * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
+        * ChassisBase is always zero for x366/x260/x460
+        * RioNodeId is 2 for first Calgary, 3 for second Calgary
+        */
+       address = START_ADDRESS -
+               (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) +
+               (0x100000) * (rionodeid - CHASSIS_BASE);
+       return address;
+}
+
+static int __init calgary_init_one_nontraslated(struct pci_dev *dev)
+{
+       dev->sysdata = NULL;
+       dev->bus->self = dev;
+
+       return 0;
+}
+
+static int __init calgary_init_one(struct pci_dev *dev)
+{
+       u32 address;
+       void __iomem *bbar;
+       int ret;
+
+       address = locate_register_space(dev);
+       /* map entire 1MB of Calgary config space */
+       bbar = ioremap_nocache(address, 1024 * 1024);
+       if (!bbar) {
+               ret = -ENODATA;
+               goto done;
+       }
+
+       ret = calgary_setup_tar(dev, bbar);
+       if (ret)
+               goto iounmap;
+
+       dev->bus->self = dev;
+       calgary_enable_translation(dev);
+
+       return 0;
+
+iounmap:
+       iounmap(bbar);
+done:
+       return ret;
+}
+
+static int __init calgary_init(void)
+{
+       int i, ret = -ENODEV;
+       struct pci_dev *dev = NULL;
+
+       for (i = 0; i < MAX_PHB_BUS_NUM; i++) {
+               dev = pci_get_device(PCI_VENDOR_ID_IBM,
+                                    PCI_DEVICE_ID_IBM_CALGARY,
+                                    dev);
+               if (!dev)
+                       break;
+               if (!translate_phb(dev)) {
+                       calgary_init_one_nontraslated(dev);
+                       continue;
+               }
+               if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) {
+                       pci_dev_put(dev);
+                       continue;
+               }
+               ret = calgary_init_one(dev);
+               if (ret)
+                       goto error;
+       }
+
+       return ret;
+
+error:
+       for (i--; i >= 0; i--) {
+               dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
+                                             PCI_DEVICE_ID_IBM_CALGARY,
+                                             dev);
+               if (!translate_phb(dev)) {
+                       pci_dev_put(dev);
+                       continue;
+               }
+               if (!tce_table_kva[dev->bus->number] && !translate_empty_slots)
+                       continue;
+               calgary_disable_translation(dev);
+               calgary_free_tar(dev);
+               pci_dev_put(dev);
+       }
+
+       return ret;
+}
+
+static inline int __init determine_tce_table_size(u64 ram)
+{
+       int ret;
+
+       if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED)
+               return specified_table_size;
+
+       /*
+        * Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to
+        * TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each
+        * larger table size has twice as many entries, so shift the
+        * max ram address by 13 to divide by 8K and then look at the
+        * order of the result to choose between 0-7.
+        */
+       ret = get_order(ram >> 13);
+       if (ret > TCE_TABLE_SIZE_8M)
+               ret = TCE_TABLE_SIZE_8M;
+
+       return ret;
+}
+
+void __init detect_calgary(void)
+{
+       u32 val;
+       int bus;
+       void *tbl;
+       int calgary_found = 0;
+       int phb = -1;
+
+       /*
+        * if the user specified iommu=off or iommu=soft or we found
+        * another HW IOMMU already, bail out.
+        */
+       if (swiotlb || no_iommu || iommu_detected)
+               return;
+
+       specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
+
+       for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
+               int dev;
+
+               tce_table_kva[bus] = NULL;
+               bus_to_phb[bus] = -1;
+
+               if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
+                       continue;
+
+               /*
+                * There are 4 PHBs per Calgary chip.  Set phb to which phb (0-3)
+                * it is connected to releative to the clagary chip.
+                */
+               phb = (phb + 1) % PHBS_PER_CALGARY;
+
+               if (test_bit(bus, translation_disabled)) {
+                       printk(KERN_INFO "Calgary: translation is disabled for "
+                              "PHB 0x%x\n", bus);
+                       /* skip this phb, don't allocate a tbl for it */
+                       continue;
+               }
+               /*
+                * Scan the slots of the PCI bus to see if there is a device present.
+                * The parent bus will be the zero-ith device, so start at 1.
+                */
+               for (dev = 1; dev < 8; dev++) {
+                       val = read_pci_config(bus, dev, 0, 0);
+                       if (val != 0xffffffff || translate_empty_slots) {
+                               tbl = alloc_tce_table();
+                               if (!tbl)
+                                       goto cleanup;
+                               tce_table_kva[bus] = tbl;
+                               bus_to_phb[bus] = phb;
+                               calgary_found = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (calgary_found) {
+               iommu_detected = 1;
+               calgary_detected = 1;
+               printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
+                      "TCE table spec is %d.\n", specified_table_size);
+       }
+       return;
+
+cleanup:
+       for (--bus; bus >= 0; --bus)
+               if (tce_table_kva[bus])
+                       free_tce_table(tce_table_kva[bus]);
+}
+
+int __init calgary_iommu_init(void)
+{
+       int ret;
+
+       if (no_iommu || swiotlb)
+               return -ENODEV;
+
+       if (!calgary_detected)
+               return -ENODEV;
+
+       /* ok, we're trying to use Calgary - let's roll */
+       printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n");
+
+       ret = calgary_init();
+       if (ret) {
+               printk(KERN_ERR "PCI-DMA: Calgary init failed %d, "
+                      "falling back to no_iommu\n", ret);
+               if (end_pfn > MAX_DMA32_PFN)
+                       printk(KERN_ERR "WARNING more than 4GB of memory, "
+                                       "32bit PCI may malfunction.\n");
+               return ret;
+       }
+
+       force_iommu = 1;
+       dma_ops = &calgary_dma_ops;
+
+       return 0;
+}
+
+static int __init calgary_parse_options(char *p)
+{
+       unsigned int bridge;
+       size_t len;
+       char* endp;
+
+       while (*p) {
+               if (!strncmp(p, "64k", 3))
+                       specified_table_size = TCE_TABLE_SIZE_64K;
+               else if (!strncmp(p, "128k", 4))
+                       specified_table_size = TCE_TABLE_SIZE_128K;
+               else if (!strncmp(p, "256k", 4))
+                       specified_table_size = TCE_TABLE_SIZE_256K;
+               else if (!strncmp(p, "512k", 4))
+                       specified_table_size = TCE_TABLE_SIZE_512K;
+               else if (!strncmp(p, "1M", 2))
+                       specified_table_size = TCE_TABLE_SIZE_1M;
+               else if (!strncmp(p, "2M", 2))
+                       specified_table_size = TCE_TABLE_SIZE_2M;
+               else if (!strncmp(p, "4M", 2))
+                       specified_table_size = TCE_TABLE_SIZE_4M;
+               else if (!strncmp(p, "8M", 2))
+                       specified_table_size = TCE_TABLE_SIZE_8M;
+
+               len = strlen("translate_empty_slots");
+               if (!strncmp(p, "translate_empty_slots", len))
+                       translate_empty_slots = 1;
+
+               len = strlen("disable");
+               if (!strncmp(p, "disable", len)) {
+                       p += len;
+                       if (*p == '=')
+                               ++p;
+                       if (*p == '\0')
+                               break;
+                       bridge = simple_strtol(p, &endp, 0);
+                       if (p == endp)
+                               break;
+
+                       if (bridge < MAX_PHB_BUS_NUM) {
+                               printk(KERN_INFO "Calgary: disabling "
+                                      "translation for PHB 0x%x\n", bridge);
+                               set_bit(bridge, translation_disabled);
+                       }
+               }
+
+               p = strpbrk(p, ",");
+               if (!p)
+                       break;
+
+               p++; /* skip ',' */
+       }
+       return 1;
+}
+__setup("calgary=", calgary_parse_options);
diff --git a/arch/x86_64/kernel/stacktrace.c b/arch/x86_64/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..6026b31
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * arch/x86_64/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/module.h>
+#include <asm/stacktrace.h>
+
+static void save_stack_warning(void *data, char *msg)
+{
+}
+
+static void
+save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+}
+
+static int save_stack_stack(void *data, char *name)
+{
+       struct stack_trace *trace = (struct stack_trace *)data;
+       return trace->all_contexts ? 0 : -1;
+}
+
+static void save_stack_address(void *data, unsigned long addr)
+{
+       struct stack_trace *trace = (struct stack_trace *)data;
+       if (trace->skip > 0) {
+               trace->skip--;
+               return;
+       }
+       if (trace->nr_entries < trace->max_entries - 1)
+               trace->entries[trace->nr_entries++] = addr;
+}
+
+static struct stacktrace_ops save_stack_ops = {
+       .warning = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack = save_stack_stack,
+       .address = save_stack_address,
+};
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+       dump_trace(task, NULL, NULL, &save_stack_ops, trace);
+       trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+EXPORT_SYMBOL(save_stack_trace);
+
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c
new file mode 100644 (file)
index 0000000..1affe8c
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Derived from arch/powerpc/platforms/pseries/iommu.c
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Jon Mason <jdmason@us.ibm.com>
+ * Author: Muli Ben-Yehuda <muli@il.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <asm/tce.h>
+#include <asm/calgary.h>
+#include <asm/proto.h>
+
+/* flush a tce at 'tceaddr' to main memory */
+static inline void flush_tce(void* tceaddr)
+{
+       /* a single tce can't cross a cache line */
+       if (cpu_has_clflush)
+               asm volatile("clflush (%0)" :: "r" (tceaddr));
+       else
+               asm volatile("wbinvd":::"memory");
+}
+
+void tce_build(struct iommu_table *tbl, unsigned long index,
+       unsigned int npages, unsigned long uaddr, int direction)
+{
+       u64* tp;
+       u64 t;
+       u64 rpn;
+
+       t = (1 << TCE_READ_SHIFT);
+       if (direction != DMA_TO_DEVICE)
+               t |= (1 << TCE_WRITE_SHIFT);
+
+       tp = ((u64*)tbl->it_base) + index;
+
+       while (npages--) {
+               rpn = (virt_to_bus((void*)uaddr)) >> PAGE_SHIFT;
+               t &= ~TCE_RPN_MASK;
+               t |= (rpn << TCE_RPN_SHIFT);
+
+               *tp = cpu_to_be64(t);
+               flush_tce(tp);
+
+               uaddr += PAGE_SIZE;
+               tp++;
+       }
+}
+
+void tce_free(struct iommu_table *tbl, long index, unsigned int npages)
+{
+       u64* tp;
+
+       tp  = ((u64*)tbl->it_base) + index;
+
+       while (npages--) {
+               *tp = cpu_to_be64(0);
+               flush_tce(tp);
+               tp++;
+       }
+}
+
+static inline unsigned int table_size_to_number_of_entries(unsigned char size)
+{
+       /*
+        * size is the order of the table, 0-7
+        * smallest table is 8K entries, so shift result by 13 to
+        * multiply by 8K
+        */
+       return (1 << size) << 13;
+}
+
+static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
+{
+       unsigned int bitmapsz;
+       unsigned long bmppages;
+       int ret;
+
+       tbl->it_busno = dev->bus->number;
+
+       /* set the tce table size - measured in entries */
+       tbl->it_size = table_size_to_number_of_entries(specified_table_size);
+
+       tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number];
+       if (!tbl->it_base) {
+               printk(KERN_ERR "Calgary: iommu_table_setparms: "
+                      "no table allocated?!\n");
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       /*
+        * number of bytes needed for the bitmap size in number of
+        * entries; we need one bit per entry
+        */
+       bitmapsz = tbl->it_size / BITS_PER_BYTE;
+       bmppages = __get_free_pages(GFP_KERNEL, get_order(bitmapsz));
+       if (!bmppages) {
+               printk(KERN_ERR "Calgary: cannot allocate bitmap\n");
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       tbl->it_map = (unsigned long*)bmppages;
+
+       memset(tbl->it_map, 0, bitmapsz);
+
+       tbl->it_hint = 0;
+
+       spin_lock_init(&tbl->it_lock);
+
+       return 0;
+
+done:
+       return ret;
+}
+
+int build_tce_table(struct pci_dev *dev, void __iomem *bbar)
+{
+       struct iommu_table *tbl;
+       int ret;
+
+       if (dev->sysdata) {
+               printk(KERN_ERR "Calgary: dev %p has sysdata %p\n",
+                      dev, dev->sysdata);
+               BUG();
+       }
+
+       tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL);
+       if (!tbl) {
+               printk(KERN_ERR "Calgary: error allocating iommu_table\n");
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       ret = tce_table_setparms(dev, tbl);
+       if (ret)
+               goto free_tbl;
+
+       tce_free(tbl, 0, tbl->it_size);
+
+       tbl->bbar = bbar;
+
+       /*
+        * NUMA is already using the bus's sysdata pointer, so we use
+        * the bus's pci_dev's sysdata instead.
+        */
+       dev->sysdata = tbl;
+
+       return 0;
+
+free_tbl:
+       kfree(tbl);
+done:
+       return ret;
+}
+
+void* alloc_tce_table(void)
+{
+       unsigned int size;
+
+       size = table_size_to_number_of_entries(specified_table_size);
+       size *= TCE_ENTRY_SIZE;
+
+       return __alloc_bootmem_low(size, size, 0);
+}
+
+void free_tce_table(void *tbl)
+{
+       unsigned int size;
+
+       if (!tbl)
+               return;
+
+       size = table_size_to_number_of_entries(specified_table_size);
+       size *= TCE_ENTRY_SIZE;
+
+       free_bootmem(__pa(tbl), size);
+}
diff --git a/arch/x86_64/lib/rwlock.S b/arch/x86_64/lib/rwlock.S
new file mode 100644 (file)
index 0000000..0cde1f8
--- /dev/null
@@ -0,0 +1,38 @@
+/* Slow paths of read/write spinlocks. */
+
+#include <linux/linkage.h>
+#include <asm/rwlock.h>
+#include <asm/alternative-asm.i>
+#include <asm/dwarf2.h>
+
+/* rdi:        pointer to rwlock_t */
+ENTRY(__write_lock_failed)
+       CFI_STARTPROC
+       LOCK_PREFIX
+       addl $RW_LOCK_BIAS,(%rdi)
+1:     rep
+       nop
+       cmpl $RW_LOCK_BIAS,(%rdi)
+       jne 1b
+       LOCK_PREFIX
+       subl $RW_LOCK_BIAS,(%rdi)
+       jnz  __write_lock_failed
+       ret
+       CFI_ENDPROC
+END(__write_lock_failed)
+
+/* rdi:        pointer to rwlock_t */
+ENTRY(__read_lock_failed)
+       CFI_STARTPROC
+       LOCK_PREFIX
+       incl (%rdi)
+1:     rep
+       nop
+       cmpl $1,(%rdi)
+       js 1b
+       LOCK_PREFIX
+       decl (%rdi)
+       js __read_lock_failed
+       ret
+       CFI_ENDPROC
+END(__read_lock_failed)
diff --git a/configs/kernel-2.6.18-i586-smp.config b/configs/kernel-2.6.18-i586-smp.config
new file mode 100644 (file)
index 0000000..224fc97
--- /dev/null
@@ -0,0 +1,3368 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:39 2006
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+CONFIG_M586=y
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_ALIGNMENT_16=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_NR_CPUS=2
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_APIC_AUTO=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+# CONFIG_X86_MCE_P4THERMAL is not set
+CONFIG_VM86=y
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_EFI_VARS=y
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=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=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_EFI=y
+# CONFIG_IRQBALANCE is not set
+CONFIG_BOOT_IOREMAP=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_SUSPEND_SMP=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_ASUS is not set
+# CONFIG_ACPI_IBM is not set
+# CONFIG_ACPI_TOSHIBA is not set
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+# CONFIG_X86_POWERNOW_K8 is not set
+# CONFIG_X86_GX_SUSPMOD is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CS553X=m
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+CONFIG_SCSI_AHA1542=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+# CONFIG_AGP_ATI is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_AMD64 is not set
+CONFIG_AGP_INTEL=y
+# CONFIG_AGP_NVIDIA is not set
+CONFIG_AGP_SIS=y
+# CONFIG_AGP_SWORKS is not set
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_IMAC is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+CONFIG_SND_ES18XX=m
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SB16_CSP is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+
+#
+# Page alloc debug is incompatible with Software Suspend on i386
+#
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i586.config b/configs/kernel-2.6.18-i586.config
new file mode 100644 (file)
index 0000000..906c52b
--- /dev/null
@@ -0,0 +1,3357 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:39 2006
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+# CONFIG_SMP is not set
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+CONFIG_M586=y
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_F00F_BUG=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_ALIGNMENT_16=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_X86_UP_APIC is not set
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+CONFIG_VM86=y
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+# CONFIG_MICROCODE is not set
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_EFI_VARS=y
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=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=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_EFI=y
+CONFIG_BOOT_IOREMAP=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_ASUS is not set
+# CONFIG_ACPI_IBM is not set
+# CONFIG_ACPI_TOSHIBA is not set
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_POWERNOW_K6=m
+# CONFIG_X86_POWERNOW_K7 is not set
+# CONFIG_X86_POWERNOW_K8 is not set
+# CONFIG_X86_GX_SUSPMOD is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CS553X=m
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+CONFIG_SCSI_AHA1542=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_PCMCIA_XIRTULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+# CONFIG_AGP_ATI is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_AMD64 is not set
+CONFIG_AGP_INTEL=y
+# CONFIG_AGP_NVIDIA is not set
+CONFIG_AGP_SIS=y
+# CONFIG_AGP_SWORKS is not set
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_IMAC is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+CONFIG_SND_ES18XX=m
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SB16_CSP is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+
+#
+# Page alloc debug is incompatible with Software Suspend on i386
+#
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i686-kdump.config b/configs/kernel-2.6.18-i686-kdump.config
new file mode 100644 (file)
index 0000000..8e2ca42
--- /dev/null
@@ -0,0 +1,3413 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:39 2006
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+# CONFIG_SMP is not set
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_UP_APIC=y
+CONFIG_X86_UP_IOAPIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_APIC_AUTO=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_EFI_VARS=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+# CONFIG_NOHIGHMEM is not set
+# CONFIG_HIGHMEM4G is not set
+CONFIG_HIGHMEM64G=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_X86_PAE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=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=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_EFI=y
+CONFIG_BOOT_IOREMAP=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=y
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CS553X=m
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+CONFIG_SCSI_AHA1542=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_PCMCIA_XIRTULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+CONFIG_IBM_ASM=m
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_IMAC is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+CONFIG_SND_ES18XX=m
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SB16_CSP is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i686-smp.config b/configs/kernel-2.6.18-i686-smp.config
new file mode 100644 (file)
index 0000000..00cc6b4
--- /dev/null
@@ -0,0 +1,3414 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:40 2006
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+# CONFIG_X86_PC is not set
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+CONFIG_X86_GENERICARCH=y
+# CONFIG_X86_ES7000 is not set
+CONFIG_X86_CYCLONE_TIMER=y
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_NR_CPUS=32
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_APIC_AUTO=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_EFI_VARS=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+# CONFIG_NOHIGHMEM is not set
+# CONFIG_HIGHMEM4G is not set
+CONFIG_HIGHMEM64G=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_X86_PAE=y
+# CONFIG_NUMA is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_EFI=y
+# CONFIG_IRQBALANCE is not set
+CONFIG_BOOT_IOREMAP=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SUSPEND_SMP=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=y
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CS553X=m
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+CONFIG_SCSI_AHA1542=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+CONFIG_IBM_ASM=m
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_IMAC is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+CONFIG_SND_ES18XX=m
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SB16_CSP is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i686-xen.config b/configs/kernel-2.6.18-i686-xen.config
new file mode 100644 (file)
index 0000000..b6af801
--- /dev/null
@@ -0,0 +1,3260 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:40 2006
+#
+CONFIG_X86_32=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+# CONFIG_X86_PC is not set
+CONFIG_X86_XEN=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_NR_CPUS=32
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_APIC_AUTO=y
+CONFIG_X86_IO_APIC=y
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_MICROCODE=y
+CONFIG_X86_CPUID=m
+CONFIG_SWIOTLB=y
+
+#
+# Firmware Drivers
+#
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+# CONFIG_NOHIGHMEM is not set
+# CONFIG_HIGHMEM4G is not set
+CONFIG_HIGHMEM64G=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_X86_PAE=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_MTRR=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=y
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
+CONFIG_SERIAL_8250_PNP=m
+CONFIG_SERIAL_8250_CS=m
+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=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+CONFIG_IBM_ASM=m
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+CONFIG_XEN_PRIVILEGED_GUEST=y
+# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XEN_BLKDEV_BACKEND=m
+CONFIG_XEN_BLKDEV_TAP=m
+CONFIG_XEN_NETDEV_BACKEND=m
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+CONFIG_XEN_NETDEV_LOOPBACK=m
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
+# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_UTIL=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_SMPBOOT=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i686-xen0.config b/configs/kernel-2.6.18-i686-xen0.config
new file mode 100644 (file)
index 0000000..c6fe1ef
--- /dev/null
@@ -0,0 +1,3258 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:40 2006
+#
+CONFIG_X86_32=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+# CONFIG_X86_PC is not set
+CONFIG_X86_XEN=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_NR_CPUS=32
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_APIC_AUTO=y
+CONFIG_X86_IO_APIC=y
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_MICROCODE=y
+CONFIG_X86_CPUID=m
+CONFIG_SWIOTLB=y
+
+#
+# Firmware Drivers
+#
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_MTRR=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=y
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
+CONFIG_SERIAL_8250_PNP=m
+CONFIG_SERIAL_8250_CS=m
+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=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+CONFIG_IBM_ASM=m
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+CONFIG_XEN_PRIVILEGED_GUEST=y
+# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_BLKDEV_TAP=m
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+CONFIG_XEN_NETDEV_LOOPBACK=y
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
+# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_UTIL=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_SMPBOOT=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i686-xenU.config b/configs/kernel-2.6.18-i686-xenU.config
new file mode 100644 (file)
index 0000000..309644b
--- /dev/null
@@ -0,0 +1,1635 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:40 2006
+#
+CONFIG_X86_32=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+# CONFIG_X86_PC is not set
+CONFIG_X86_XEN=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_NR_CPUS=32
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_VM86=y
+# CONFIG_TOSHIBA is not set
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_X86_CPUID=m
+CONFIG_SWIOTLB=y
+
+#
+# Firmware Drivers
+#
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_SCx200 is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VIA_FIR=m
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# 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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_SCSI_SATA=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_MWAVE is not set
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+# CONFIG_CS5535_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_ARC is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+# CONFIG_XEN_PRIVILEGED_GUEST is not set
+CONFIG_XEN_UNPRIVILEGED_GUEST=y
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+# CONFIG_XEN_BLKDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_TAP=m
+# CONFIG_XEN_NETDEV_BACKEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_UTIL=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_SMPBOOT=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-i686.config b/configs/kernel-2.6.18-i686.config
new file mode 100644 (file)
index 0000000..96690dc
--- /dev/null
@@ -0,0 +1,3416 @@
+# i386
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:41 2006
+#
+CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86=y
+CONFIG_MMU=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+# CONFIG_SMP is not set
+CONFIG_X86_PC=y
+# CONFIG_X86_XEN is not set
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_NUMAQ is not set
+# CONFIG_X86_SUMMIT is not set
+# CONFIG_X86_BIGSMP is not set
+# CONFIG_X86_VISWS is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_ES7000 is not set
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# 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
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_UP_APIC=y
+CONFIG_X86_UP_IOAPIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_APIC_AUTO=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_SWIOTLB is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_EFI_VARS=y
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
+# CONFIG_HIGHMEM64G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=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=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HIGHPTE=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_EFI=y
+CONFIG_BOOT_IOREMAP=y
+CONFIG_REGPARM=y
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x400000
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management options (ACPI, APM)
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=1999
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+
+#
+# APM (Advanced Power Management) BIOS Support
+#
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+# CONFIG_APM_DO_ENABLE is not set
+CONFIG_APM_CPU_IDLE=y
+# CONFIG_APM_DISPLAY_BLANK is not set
+CONFIG_APM_RTC_IS_GMT=y
+# CONFIG_APM_ALLOW_INTS is not set
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+# CONFIG_X86_POWERNOW_K6 is not set
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+CONFIG_X86_SPEEDSTEP_ICH=y
+CONFIG_X86_SPEEDSTEP_SMI=y
+CONFIG_X86_P4_CLOCKMOD=m
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_LONGRUN=y
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOXEN_FE is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_CS553X=m
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_RZ1000=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_CS5535=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+CONFIG_SCSI_AHA1542=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+CONFIG_SCSI_ADVANSYS=m
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_PCMCIA_XIRTULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+CONFIG_SONYPI=m
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_ALI=y
+CONFIG_AGP_ATI=y
+CONFIG_AGP_AMD=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_NVIDIA=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_SWORKS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_EFFICEON=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_I801=m
+CONFIG_I2C_I810=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_SCx200_ACB is not set
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+CONFIG_IBM_ASM=m
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_IMAC is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+CONFIG_SND_ES18XX=m
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SB16_CSP is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_AMD76X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_R82600=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+
+#
+# Page alloc debug is incompatible with Software Suspend on i386
+#
+CONFIG_DEBUG_RODATA=y
+CONFIG_4KSTACKS=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_KTIME_SCALAR=y
diff --git a/configs/kernel-2.6.18-ia64-xen.config b/configs/kernel-2.6.18-ia64-xen.config
new file mode 100644 (file)
index 0000000..7fea409
--- /dev/null
@@ -0,0 +1,2883 @@
+# ia64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:41 2006
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_XEN=y
+CONFIG_XEN_IA64_VDSO_PARAVIRT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
+# CONFIG_IA64_GENERIC is not set
+CONFIG_IA64_DIG=y
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_SMP=y
+CONFIG_NR_CPUS=1024
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_SCHED_SMT=y
+# CONFIG_PERMIT_BSP_REMOVE is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+# CONFIG_VIRTUAL_MEM_MAP is not set
+# CONFIG_IA32_SUPPORT is not set
+CONFIG_IA64_MCA_RECOVERY=m
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_IA64_ACPI_CPUFREQ=m
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+# CONFIG_BCM43XX is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_I8XX_TCO=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_I460=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_IA64_GRANULE_16MB is not set
+CONFIG_IA64_GRANULE_64MB=y
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+# CONFIG_XEN_UTIL is not set
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SKBUFF=y
+# CONFIG_XEN_DEVMEM is not set
+CONFIG_XEN_REBOOT=y
+# CONFIG_XEN_SMPBOOT is not set
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+CONFIG_XEN_PRIVILEGED_GUEST=y
+# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XEN_BLKDEV_BACKEND=m
+# CONFIG_XEN_BLKDEV_TAP is not set
+CONFIG_XEN_NETDEV_BACKEND=m
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+CONFIG_XEN_NETDEV_LOOPBACK=m
+# CONFIG_XEN_PCIDEV_BACKEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
diff --git a/configs/kernel-2.6.18-ia64.config b/configs/kernel-2.6.18-ia64.config
new file mode 100644 (file)
index 0000000..e6c8653
--- /dev/null
@@ -0,0 +1,2902 @@
+# ia64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:41 2006
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_XEN is not set
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_IA64_UNCACHED_ALLOCATOR=y
+CONFIG_DMA_IS_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_IA64_SGI_SN_XP=y
+CONFIG_FORCE_MAX_ZONEORDER=17
+CONFIG_SMP=y
+CONFIG_NR_CPUS=1024
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_SCHED_SMT=y
+# CONFIG_PERMIT_BSP_REMOVE is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=8
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
+# CONFIG_IA32_SUPPORT is not set
+CONFIG_IA64_MCA_RECOVERY=m
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+CONFIG_SGI_SN=y
+
+#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+CONFIG_SGI_IOC3=m
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HOTPLUG_MEMORY=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_IA64_ACPI_CPUFREQ=m
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y
+CONFIG_HOTPLUG_PCI_SGI=m
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SGIIOC4=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+# CONFIG_BCM43XX is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=16
+CONFIG_SERIAL_8250_EXTENDED=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_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_SGI_IOC4=m
+CONFIG_SERIAL_SGI_IOC3=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_I8XX_TCO=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_I460=y
+CONFIG_AGP_HP_ZX1=y
+CONFIG_AGP_SGI_TIOCA=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_MMTIMER=y
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+# CONFIG_TCG_INFINEON is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_IPATH_CORE=m
+CONFIG_INFINIBAND_IPATH=m
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
diff --git a/configs/kernel-2.6.18-ppc-smp.config b/configs/kernel-2.6.18-ppc-smp.config
new file mode 100644 (file)
index 0000000..66147ea
--- /dev/null
@@ -0,0 +1,3204 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:41 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_MAMBO is not set
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+# CONFIG_RTAS_PROC is not set
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_PMAC=y
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+CONFIG_TAU_AVERAGE=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_KEXEC is not set
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_HIGHMEM_START_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=m
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=m
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
+CONFIG_SCSI_MAC53C94=m
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
+CONFIG_PMAC_APM_EMU=y
+CONFIG_PMAC_MEDIABAY=y
+CONFIG_PMAC_BACKLIGHT=y
+# CONFIG_PMAC_BACKLIGHT_LEGACY is not set
+CONFIG_ADB_MACIO=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+CONFIG_WINDFARM=y
+# CONFIG_ANSLCD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MACE=m
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_MV643XX_ETH=m
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+# CONFIG_HVC_RTAS is not set
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_UNINORTH=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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_HYDRA=m
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_POWERMAC=y
+CONFIG_I2C_MPC=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_M41T00=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# 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=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+CONFIG_DMASOUND_PMAC=m
+CONFIG_DMASOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+
+#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
diff --git a/configs/kernel-2.6.18-ppc.config b/configs/kernel-2.6.18-ppc.config
new file mode 100644 (file)
index 0000000..1db169f
--- /dev/null
@@ -0,0 +1,3208 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:41 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+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_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_MAMBO is not set
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+# CONFIG_RTAS_PROC is not set
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_PMAC=y
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+CONFIG_TAU_AVERAGE=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_HIGHMEM_START_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=m
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+# CONFIG_SCSI_7000FASST is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+# CONFIG_SCSI_AHA1542 is not set
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+CONFIG_SCSI_GDTH=m
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_SYM53C416 is not set
+CONFIG_SCSI_DC395x=m
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=m
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
+CONFIG_SCSI_MAC53C94=m
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
+CONFIG_PMAC_APM_EMU=y
+CONFIG_PMAC_MEDIABAY=y
+CONFIG_PMAC_BACKLIGHT=y
+# CONFIG_PMAC_BACKLIGHT_LEGACY is not set
+CONFIG_ADB_MACIO=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+CONFIG_WINDFARM=y
+# CONFIG_ANSLCD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MACE=m
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_PCMCIA_XIRTULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_MV643XX_ETH=m
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+# CONFIG_IBMTR is not set
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+# CONFIG_SMCTR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+# CONFIG_HISAX_16_0 is not set
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+# CONFIG_HISAX_AVM_A1 is not set
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+CONFIG_HISAX_DIEHLDIVA=y
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+CONFIG_HISAX_SEDLBAUER=y
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+CONFIG_HISAX_NICCY=y
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+# CONFIG_HVC_RTAS is not set
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_UNINORTH=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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_ELEKTOR is not set
+CONFIG_I2C_HYDRA=m
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_POWERMAC=y
+CONFIG_I2C_MPC=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_M41T00=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# 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=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+CONFIG_DMASOUND_PMAC=m
+CONFIG_DMASOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# ISA devices
+#
+CONFIG_SND_CS4231_LIB=m
+CONFIG_SND_ADLIB=m
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+CONFIG_SND_CS4236=m
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+CONFIG_SND_OPL3SA2=m
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+CONFIG_SND_MIRO=m
+# CONFIG_SND_SB8 is not set
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+
+#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
diff --git a/configs/kernel-2.6.18-ppc64-kdump.config b/configs/kernel-2.6.18-ppc64-kdump.config
new file mode 100644 (file)
index 0000000..aba7827
--- /dev/null
@@ -0,0 +1,3039 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:42 2006
+#
+CONFIG_PPC64=y
+CONFIG_64BIT=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_POWER4_ONLY is not set
+CONFIG_POWER3=y
+CONFIG_POWER4=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=128
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_PSERIES=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_PMAC64=y
+# CONFIG_PPC_MAPLE is not set
+CONFIG_PPC_CELL=y
+CONFIG_PPC_CELL_NATIVE=y
+CONFIG_PPC_IBM_CELL_BLADE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_MAMBO=y
+CONFIG_MAMBO_DISK=m
+CONFIG_MAMBO_NET=m
+CONFIG_XICS=y
+CONFIG_U3_DART=y
+CONFIG_PPC_RTAS=y
+CONFIG_RTAS_ERROR_LOGGING=y
+CONFIG_RTAS_PROC=y
+CONFIG_RTAS_FLASH=y
+CONFIG_MMIO_NVRAM=y
+CONFIG_MPIC_BROKEN_U3=y
+CONFIG_IBMVIO=y
+CONFIG_IBMEBUS=y
+# CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_970_NAP=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_PMAC64=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=m
+CONFIG_SPU_BASE=y
+CONFIG_SPUFS_MMAP=y
+CONFIG_CBE_RAS=y
+
+#
+# Kernel options
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_FORCE_MAX_ZONEORDER=9
+CONFIG_IOMMU_VMERGE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_PPC_SPLPAR=y
+CONFIG_EEH=y
+CONFIG_SCANLOG=y
+CONFIG_LPARCFG=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_NODES_SPAN_OTHER_NODES=y
+CONFIG_PPC_64K_PAGES=y
+CONFIG_SCHED_SMT=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y
+CONFIG_HOTPLUG_PCI_RPA=m
+CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
+CONFIG_KERNEL_START=0xc000000000000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# 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=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_IBMVSCSI=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
+CONFIG_PMAC_SMU=y
+CONFIG_THERM_PM72=y
+CONFIG_WINDFARM=y
+CONFIG_WINDFARM_PM81=y
+CONFIG_WINDFARM_PM91=y
+CONFIG_WINDFARM_PM112=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_SPIDER_NET=m
+# CONFIG_MV643XX_ETH is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_CS=m
+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_SERIAL_PMACZILOG=m
+CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_CONSOLE=y
+CONFIG_HVC_RTAS=y
+CONFIG_HVCS=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_UNINORTH=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_POWERMAC=y
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# 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=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+
+#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_IRQSTACKS=y
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+CONFIG_KEYS_COMPAT=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
diff --git a/configs/kernel-2.6.18-ppc64.config b/configs/kernel-2.6.18-ppc64.config
new file mode 100644 (file)
index 0000000..7b31ef8
--- /dev/null
@@ -0,0 +1,3038 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:42 2006
+#
+CONFIG_PPC64=y
+CONFIG_64BIT=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_POWER4_ONLY is not set
+CONFIG_POWER3=y
+CONFIG_POWER4=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=128
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_PSERIES=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_PMAC64=y
+# CONFIG_PPC_MAPLE is not set
+CONFIG_PPC_CELL=y
+CONFIG_PPC_CELL_NATIVE=y
+CONFIG_PPC_IBM_CELL_BLADE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_MAMBO=y
+CONFIG_MAMBO_DISK=m
+CONFIG_MAMBO_NET=m
+CONFIG_XICS=y
+CONFIG_U3_DART=y
+CONFIG_PPC_RTAS=y
+CONFIG_RTAS_ERROR_LOGGING=y
+CONFIG_RTAS_PROC=y
+CONFIG_RTAS_FLASH=y
+CONFIG_MMIO_NVRAM=y
+CONFIG_MPIC_BROKEN_U3=y
+CONFIG_IBMVIO=y
+CONFIG_IBMEBUS=y
+# CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_970_NAP=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_PMAC64=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=m
+CONFIG_SPU_BASE=y
+CONFIG_SPUFS_MMAP=y
+CONFIG_CBE_RAS=y
+
+#
+# Kernel options
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_FORCE_MAX_ZONEORDER=9
+CONFIG_IOMMU_VMERGE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_PPC_SPLPAR=y
+CONFIG_EEH=y
+CONFIG_SCANLOG=y
+CONFIG_LPARCFG=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_NODES_SPAN_OTHER_NODES=y
+CONFIG_PPC_64K_PAGES=y
+CONFIG_SCHED_SMT=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y
+CONFIG_HOTPLUG_PCI_RPA=m
+CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
+CONFIG_KERNEL_START=0xc000000000000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_TRIFLEX=y
+# CONFIG_BLK_DEV_CY82C693 is not set
+CONFIG_BLK_DEV_CS5520=y
+CONFIG_BLK_DEV_CS5530=y
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+# 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=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_IBMVSCSI=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
+CONFIG_PMAC_SMU=y
+CONFIG_THERM_PM72=y
+CONFIG_WINDFARM=y
+CONFIG_WINDFARM_PM81=y
+CONFIG_WINDFARM_PM91=y
+CONFIG_WINDFARM_PM112=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_SPIDER_NET=m
+# CONFIG_MV643XX_ETH is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+CONFIG_ISDN_DIVAS=m
+CONFIG_ISDN_DIVAS_BRIPCI=y
+CONFIG_ISDN_DIVAS_PRIPCI=y
+CONFIG_ISDN_DIVAS_DIVACAPI=m
+CONFIG_ISDN_DIVAS_USERIDI=m
+CONFIG_ISDN_DIVAS_MAINT=m
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_CS=m
+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_SERIAL_PMACZILOG=m
+CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_CONSOLE=y
+CONFIG_HVC_RTAS=y
+CONFIG_HVCS=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_AGP_UNINORTH=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_POWERMAC=y
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# 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=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+
+#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_IRQSTACKS=y
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+CONFIG_KEYS_COMPAT=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
diff --git a/configs/kernel-2.6.18-ppc64iseries.config b/configs/kernel-2.6.18-ppc64iseries.config
new file mode 100644 (file)
index 0000000..ffeabee
--- /dev/null
@@ -0,0 +1,1586 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:42 2006
+#
+CONFIG_PPC64=y
+CONFIG_64BIT=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_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
+
+#
+# Processor support
+#
+# CONFIG_POWER4_ONLY is not set
+CONFIG_POWER3=y
+CONFIG_POWER4=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=128
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+CONFIG_PPC_ISERIES=y
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_MAMBO is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_IBMVIO=y
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+# CONFIG_MPIC is not set
+
+#
+# Kernel options
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_FORCE_MAX_ZONEORDER=9
+CONFIG_IOMMU_VMERGE=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_LPARCFG=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_PPC_64K_PAGES=y
+# CONFIG_SCHED_SMT is not set
+CONFIG_PROC_DEVICETREE=y
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y
+CONFIG_KERNEL_START=0xc000000000000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+# CONFIG_SCSI_3W_9XXX is not set
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_HPTIOP=m
+# 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=m
+# CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_IBMVSCSI=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+# CONFIG_SUNGEM is not set
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_VORTEX is not set
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=m
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=m
+# CONFIG_8139TOO is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+# CONFIG_R8169 is not set
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_ISERIES_VETH=m
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# 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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+CONFIG_HW_RANDOM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+# CONFIG_INTEL_IOATDMA is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# iSeries device drivers
+#
+CONFIG_VIOCONS=y
+CONFIG_VIODASD=m
+CONFIG_VIOCD=m
+CONFIG_VIOTAPE=m
+CONFIG_VIOPATH=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+CONFIG_IRQSTACKS=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+CONFIG_KEYS_COMPAT=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
diff --git a/configs/kernel-2.6.18-s390.config b/configs/kernel-2.6.18-s390.config
new file mode 100644 (file)
index 0000000..971ecd1
--- /dev/null
@@ -0,0 +1,1133 @@
+# s390
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:42 2006
+#
+CONFIG_MMU=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_S390=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Base setup
+#
+
+#
+# Processor type and features
+#
+# CONFIG_64BIT is not set
+CONFIG_32BIT=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=32
+CONFIG_HOTPLUG_CPU=y
+CONFIG_DEFAULT_MIGRATION_COST=1000000
+CONFIG_MATHEMU=y
+CONFIG_AUDIT_ARCH=y
+
+#
+# Code generation options
+#
+CONFIG_MARCH_G5=y
+# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_Z990 is not set
+CONFIG_PACK_STACK=y
+# CONFIG_SMALL_STACK is not set
+CONFIG_CHECK_STACK=y
+CONFIG_STACK_GUARD=256
+# CONFIG_WARN_STACK is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+
+#
+# I/O subsystem configuration
+#
+CONFIG_MACHCHK_WARNING=y
+CONFIG_QDIO=m
+# CONFIG_QDIO_PERF_STATS is not set
+# CONFIG_QDIO_DEBUG is not set
+
+#
+# Misc
+#
+# CONFIG_PREEMPT is not set
+CONFIG_IPL=y
+# CONFIG_IPL_TAPE is not set
+CONFIG_IPL_VM=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_PROCESS_DEBUG is not set
+CONFIG_PFAULT=y
+# CONFIG_SHARED_KERNEL is not set
+CONFIG_CMM=m
+CONFIG_CMM_PROC=y
+CONFIG_CMM_IUCV=y
+CONFIG_VIRT_TIMER=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_APPLDATA_BASE=y
+CONFIG_APPLDATA_MEM=m
+CONFIG_APPLDATA_OS=m
+CONFIG_APPLDATA_NET_SUM=m
+CONFIG_NO_IDLE_HZ=y
+CONFIG_NO_IDLE_HZ_INIT=y
+CONFIG_S390_HYPFS_FS=y
+CONFIG_KEXEC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ZFCP=m
+CONFIG_CCW=y
+
+#
+# Block devices
+#
+# 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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# S/390 block device drivers
+#
+CONFIG_BLK_DEV_XPRAM=m
+CONFIG_DCSSBLK=m
+CONFIG_DASD=m
+CONFIG_DASD_PROFILE=y
+CONFIG_DASD_ECKD=m
+CONFIG_DASD_FBA=m
+CONFIG_DASD_DIAG=m
+CONFIG_DASD_EER=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Character device drivers
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=2048
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ZVM_WATCHDOG=m
+
+#
+# S/390 character device drivers
+#
+CONFIG_TN3270=y
+CONFIG_TN3270_TTY=y
+CONFIG_TN3270_FS=m
+CONFIG_TN3270_CONSOLE=y
+CONFIG_TN3215=y
+CONFIG_TN3215_CONSOLE=y
+CONFIG_CCW_CONSOLE=y
+CONFIG_SCLP=y
+CONFIG_SCLP_TTY=y
+CONFIG_SCLP_CONSOLE=y
+CONFIG_SCLP_VT220_TTY=y
+CONFIG_SCLP_VT220_CONSOLE=y
+CONFIG_SCLP_CPI=m
+CONFIG_S390_TAPE=m
+
+#
+# S/390 tape interface support
+#
+CONFIG_S390_TAPE_BLOCK=y
+
+#
+# S/390 tape hardware support
+#
+CONFIG_S390_TAPE_34XX=m
+CONFIG_S390_TAPE_3590=m
+CONFIG_VMLOGRDR=m
+CONFIG_VMCP=m
+CONFIG_MONREADER=m
+
+#
+# Cryptographic devices
+#
+CONFIG_Z90CRYPT=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+
+#
+# S/390 network device drivers
+#
+CONFIG_LCS=m
+CONFIG_CTC=m
+CONFIG_IUCV=m
+CONFIG_NETIUCV=m
+CONFIG_SMSGIUCV=m
+# CONFIG_CLAW is not set
+CONFIG_QETH=m
+
+#
+# Gigabit Ethernet default settings
+#
+CONFIG_QETH_IPV6=y
+CONFIG_QETH_VLAN=y
+CONFIG_CCWGROUP=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_IBM_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# 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=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DETECT_SOFTLOCKUP is not set
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_BOOT_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/configs/kernel-2.6.18-s390x.config b/configs/kernel-2.6.18-s390x.config
new file mode 100644 (file)
index 0000000..6340b1b
--- /dev/null
@@ -0,0 +1,1131 @@
+# s390
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:42 2006
+#
+CONFIG_MMU=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_S390=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_BLK_DEV_IO_TRACE=y
+
+#
+# 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"
+
+#
+# Base setup
+#
+
+#
+# Processor type and features
+#
+CONFIG_64BIT=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
+CONFIG_HOTPLUG_CPU=y
+CONFIG_DEFAULT_MIGRATION_COST=1000000
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_AUDIT_ARCH=y
+
+#
+# Code generation options
+#
+# CONFIG_MARCH_G5 is not set
+CONFIG_MARCH_Z900=y
+# CONFIG_MARCH_Z990 is not set
+CONFIG_PACK_STACK=y
+# CONFIG_SMALL_STACK is not set
+CONFIG_CHECK_STACK=y
+CONFIG_STACK_GUARD=256
+# CONFIG_WARN_STACK is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+
+#
+# I/O subsystem configuration
+#
+CONFIG_MACHCHK_WARNING=y
+CONFIG_QDIO=m
+# CONFIG_QDIO_PERF_STATS is not set
+# CONFIG_QDIO_DEBUG is not set
+
+#
+# Misc
+#
+# CONFIG_PREEMPT is not set
+CONFIG_IPL=y
+# CONFIG_IPL_TAPE is not set
+CONFIG_IPL_VM=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_PROCESS_DEBUG is not set
+CONFIG_PFAULT=y
+# CONFIG_SHARED_KERNEL is not set
+CONFIG_CMM=m
+CONFIG_CMM_PROC=y
+CONFIG_CMM_IUCV=y
+CONFIG_VIRT_TIMER=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_APPLDATA_BASE=y
+CONFIG_APPLDATA_MEM=m
+CONFIG_APPLDATA_OS=m
+CONFIG_APPLDATA_NET_SUM=m
+CONFIG_NO_IDLE_HZ=y
+CONFIG_NO_IDLE_HZ_INIT=y
+CONFIG_S390_HYPFS_FS=y
+CONFIG_KEXEC=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ZFCP=m
+CONFIG_CCW=y
+
+#
+# Block devices
+#
+# 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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# S/390 block device drivers
+#
+CONFIG_BLK_DEV_XPRAM=m
+CONFIG_DCSSBLK=m
+CONFIG_DASD=m
+CONFIG_DASD_PROFILE=y
+CONFIG_DASD_ECKD=m
+CONFIG_DASD_FBA=m
+CONFIG_DASD_DIAG=m
+CONFIG_DASD_EER=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Character device drivers
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=2048
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ZVM_WATCHDOG=m
+
+#
+# S/390 character device drivers
+#
+CONFIG_TN3270=y
+CONFIG_TN3270_TTY=y
+CONFIG_TN3270_FS=m
+CONFIG_TN3270_CONSOLE=y
+CONFIG_TN3215=y
+CONFIG_TN3215_CONSOLE=y
+CONFIG_CCW_CONSOLE=y
+CONFIG_SCLP=y
+CONFIG_SCLP_TTY=y
+CONFIG_SCLP_CONSOLE=y
+CONFIG_SCLP_VT220_TTY=y
+CONFIG_SCLP_VT220_CONSOLE=y
+CONFIG_SCLP_CPI=m
+CONFIG_S390_TAPE=m
+
+#
+# S/390 tape interface support
+#
+CONFIG_S390_TAPE_BLOCK=y
+
+#
+# S/390 tape hardware support
+#
+CONFIG_S390_TAPE_34XX=m
+CONFIG_S390_TAPE_3590=m
+CONFIG_VMLOGRDR=m
+CONFIG_VMCP=m
+CONFIG_MONREADER=m
+
+#
+# Cryptographic devices
+#
+CONFIG_Z90CRYPT=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+
+#
+# S/390 network device drivers
+#
+CONFIG_LCS=m
+CONFIG_CTC=m
+CONFIG_IUCV=m
+CONFIG_NETIUCV=m
+CONFIG_SMSGIUCV=m
+# CONFIG_CLAW is not set
+CONFIG_QETH=m
+
+#
+# Gigabit Ethernet default settings
+#
+CONFIG_QETH_IPV6=y
+CONFIG_QETH_VLAN=y
+CONFIG_CCWGROUP=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_IBM_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# 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=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DETECT_SOFTLOCKUP is not set
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_BOOT_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/configs/kernel-2.6.18-x86_64-kdump.config b/configs/kernel-2.6.18-x86_64-kdump.config
new file mode 100644 (file)
index 0000000..e62073e
--- /dev/null
@@ -0,0 +1,3136 @@
+# x86_64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:42 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+# CONFIG_X86_64_XEN is not set
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_TSC=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_IOMMU=y
+CONFIG_CALGARY_IOMMU=y
+CONFIG_SWIOTLB=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_AMD=y
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
+CONFIG_PHYSICAL_START=0x1000000
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_REORDER=y
+CONFIG_K8_NB=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_SBS=m
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_ACPI_CPUFREQ=m
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT 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=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_PCMCIA_XIRTULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+CONFIG_HYSDN=m
+CONFIG_HYSDN_CAPI=y
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+# CONFIG_HW_RANDOM_GEODE is not set
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
+# CONFIG_IOMMU_DEBUG is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/configs/kernel-2.6.18-x86_64-xen.config b/configs/kernel-2.6.18-x86_64-xen.config
new file mode 100644 (file)
index 0000000..b4a0c30
--- /dev/null
@@ -0,0 +1,3144 @@
+# x86_64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:43 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_64_XEN=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_GOOD_APIC=y
+CONFIG_MICROCODE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_XEN_GENAPIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
+CONFIG_SMP=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_CALGARY_IOMMU=y
+CONFIG_SWIOTLB=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x200000
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_REORDER=y
+CONFIG_K8_NB=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_ACPI_CPUFREQ=m
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_MMCONFIG is not set
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT 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=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
+CONFIG_SERIAL_8250_PNP=m
+CONFIG_SERIAL_8250_CS=m
+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=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+# CONFIG_HW_RANDOM_GEODE is not set
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# Firmware Drivers
+#
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+CONFIG_XEN_PRIVILEGED_GUEST=y
+# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XEN_BLKDEV_BACKEND=m
+CONFIG_XEN_BLKDEV_TAP=m
+CONFIG_XEN_NETDEV_BACKEND=m
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+CONFIG_XEN_NETDEV_LOOPBACK=m
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
+# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_UTIL=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_SMPBOOT=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/configs/kernel-2.6.18-x86_64-xen0.config b/configs/kernel-2.6.18-x86_64-xen0.config
new file mode 100644 (file)
index 0000000..25d6f90
--- /dev/null
@@ -0,0 +1,3144 @@
+# x86_64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:43 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_64_XEN=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_GOOD_APIC=y
+CONFIG_MICROCODE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_XEN_GENAPIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
+CONFIG_SMP=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_CALGARY_IOMMU=y
+CONFIG_SWIOTLB=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x200000
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_REORDER=y
+CONFIG_K8_NB=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_ACPI_CPUFREQ=m
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_MMCONFIG is not set
+CONFIG_XEN_PCIDEV_FRONTEND=y
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT 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=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
+CONFIG_SERIAL_8250_PNP=m
+CONFIG_SERIAL_8250_CS=m
+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=m
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+# CONFIG_HW_RANDOM_GEODE is not set
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# Firmware Drivers
+#
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+CONFIG_XEN_PRIVILEGED_GUEST=y
+# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_BLKDEV_TAP=m
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+CONFIG_XEN_NETDEV_LOOPBACK=y
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
+# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
+# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
+# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_UTIL=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_SMPBOOT=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/configs/kernel-2.6.18-x86_64-xenU.config b/configs/kernel-2.6.18-x86_64-xenU.config
new file mode 100644 (file)
index 0000000..78ffb64
--- /dev/null
@@ -0,0 +1,1581 @@
+# x86_64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:43 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_64_XEN=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_NO_IDT=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_GOOD_APIC=y
+# CONFIG_MICROCODE is not set
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_XEN_GENAPIC=y
+CONFIG_SMP=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_RESOURCES_64BIT=y
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_SWIOTLB=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x200000
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_REORDER=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# Bus options (PCI etc.)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VIA_FIR=m
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# 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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_SCSI_SATA=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_MWAVE is not set
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_ARC is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+
+#
+# Firmware Drivers
+#
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS 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=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030203
+
+#
+# XEN
+#
+# CONFIG_XEN_PRIVILEGED_GUEST is not set
+CONFIG_XEN_UNPRIVILEGED_GUEST=y
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_BACKEND=y
+# CONFIG_XEN_BLKDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_TAP=m
+# CONFIG_XEN_NETDEV_BACKEND is not set
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_FRAMEBUFFER=y
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_COMPAT_030002=y
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_UTIL=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_SMPBOOT=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/configs/kernel-2.6.18-x86_64.config b/configs/kernel-2.6.18-x86_64.config
new file mode 100644 (file)
index 0000000..16135f6
--- /dev/null
@@ -0,0 +1,3150 @@
+# x86_64
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18.2-rc1
+# Mon Nov 13 09:44:43 2006
+#
+CONFIG_X86_64=y
+CONFIG_64BIT=y
+CONFIG_X86=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+# CONFIG_IKCONFIG is not set
+CONFIG_CPUSETS=y
+CONFIG_RELAY=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=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=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Process debugging support
+#
+CONFIG_UTRACE=y
+CONFIG_PTRACE=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+
+#
+# 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"
+
+#
+# Processor type and features
+#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_GENERIC_CPU=y
+# CONFIG_X86_64_XEN is not set
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_TSC=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_MICROCODE=m
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_HT=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_MTRR=y
+CONFIG_SMP=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_NUMA=y
+CONFIG_K8_NUMA=y
+CONFIG_NODES_SHIFT=6
+CONFIG_X86_64_ACPI_NUMA=y
+# CONFIG_NUMA_EMU is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_NR_CPUS=255
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_IOMMU=y
+CONFIG_CALGARY_IOMMU=y
+CONFIG_SWIOTLB=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_AMD=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x200000
+# CONFIG_SECCOMP is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_REORDER=y
+CONFIG_K8_NB=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_SUSPEND_SMP=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_SLEEP_PROC_FS=y
+# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+# CONFIG_ACPI_HOTKEY is not set
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_DOCK=m
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_IBM=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_SBS=m
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO=y
+CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y
+CONFIG_X86_ACPI_CPUFREQ=m
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_SHPC=m
+# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_IA32_EMULATION=y
+# CONFIG_IA32_AOUT is not set
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+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_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+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=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_SECMARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_SIP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+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_OWNER=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+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 is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_DECNET_ROUTE_FWMARK=y
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# 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
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+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=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+CONFIG_IEEE80211_SOFTMAC_DEBUG=y
+CONFIG_TUX=m
+
+#
+# TUX options
+#
+CONFIG_TUX_EXTCGI=y
+CONFIG_TUX_EXTENDED_LOG=y
+# CONFIG_TUX_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+CONFIG_RFD_FTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PNC2000 is not set
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_AMD76XROM is not set
+# CONFIG_MTD_ICHXROM is not set
+CONFIG_MTD_SCB2_FLASH=m
+# CONFIG_MTD_NETtel is not set
+# CONFIG_MTD_DILNETPC is not set
+# CONFIG_MTD_L440GX is not set
+CONFIG_MTD_PCI=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_NANDSIM=m
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# 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=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=y
+CONFIG_BLK_DEV_ALI15X3=y
+# CONFIG_WDC_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_ATIIXP=y
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+CONFIG_BLK_DEV_HPT34X=y
+# CONFIG_HPT34X_AUTODMA is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_BLK_DEV_IT821X=y
+# CONFIG_BLK_DEV_NS87415 is not set
+CONFIG_BLK_DEV_PDC202XX_OLD=y
+# CONFIG_PDC202XX_BURST is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+CONFIG_BLK_DEV_SVWKS=y
+CONFIG_BLK_DEV_SIIMAGE=y
+CONFIG_BLK_DEV_SIS5513=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=4
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_SATA_AHCI=m
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_MV=m
+CONFIG_SCSI_SATA_NV=m
+CONFIG_SCSI_PDC_ADMA=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_SATA_QSTOR=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_SX4=m
+CONFIG_SCSI_SATA_SIL=m
+CONFIG_SCSI_SATA_SIL24=m
+CONFIG_SCSI_SATA_SIS=m
+CONFIG_SCSI_SATA_ULI=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=m
+CONFIG_SCSI_SATA_INTEL_COMBINED=y
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_OMIT_FLASHPOINT 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=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_FDOMAIN is not set
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+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_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_OUI_DB=y
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+CONFIG_I2O=m
+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_NET_SB1000=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+CONFIG_B44=m
+CONFIG_FORCEDETH=m
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+CONFIG_SKY2=m
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_CHELSIO_T1=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+
+#
+# Token Ring devices
+#
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+# CONFIG_TMS380TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+CONFIG_NET_WIRELESS_RTNETLINK=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_BCM43XX=m
+CONFIG_BCM43XX_DEBUG=y
+CONFIG_BCM43XX_DMA=y
+CONFIG_BCM43XX_PIO=y
+CONFIG_BCM43XX_DMA_AND_PIO_MODE=y
+# CONFIG_BCM43XX_DMA_MODE is not set
+# CONFIG_BCM43XX_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+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 is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+CONFIG_HISAX_NO_SENDCOMPLETE=y
+CONFIG_HISAX_NO_LLC=y
+CONFIG_HISAX_NO_KEYPAD=y
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_TELESPCI=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NETJET=y
+CONFIG_HISAX_NETJET_U=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_BKM_A4T=y
+CONFIG_HISAX_SCT_QUADRO=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_PCI=y
+CONFIG_HISAX_W6692=y
+CONFIG_HISAX_HFC_SX=y
+CONFIG_HISAX_ENTERNOW_PCI=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+# CONFIG_HISAX_HFCUSB is not set
+CONFIG_HISAX_HFC4S8S=m
+CONFIG_HISAX_FRITZ_PCIPNP=m
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+CONFIG_ISDN_DRV_GIGASET=m
+CONFIG_GIGASET_BASE=m
+CONFIG_GIGASET_M105=m
+# CONFIG_GIGASET_DEBUG is not set
+# CONFIG_GIGASET_UNDOCREQ is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCI=m
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+CONFIG_ISDN_DRV_AVMB1_T1PCI=m
+CONFIG_ISDN_DRV_AVMB1_C4=m
+
+#
+# Active Eicon DIVA Server cards
+#
+# CONFIG_CAPI_EICON is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+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_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_CRASH=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_ADVANTECH_WDT is not set
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+# CONFIG_SC520_WDT is not set
+# CONFIG_EUROTECH_WDT is not set
+# CONFIG_IB700_WDT is not set
+CONFIG_IBMASR=m
+# CONFIG_WAFER_WDT is not set
+CONFIG_I6300ESB_WDT=m
+CONFIG_I8XX_TCO=m
+# CONFIG_SC1200_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_SBC8360_WDT is not set
+# CONFIG_CPU5_WDT is not set
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+# CONFIG_HW_RANDOM_GEODE is not set
+CONFIG_NVRAM=y
+CONFIG_RTC=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
+CONFIG_AGP_SIS=y
+CONFIG_AGP_VIA=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+# CONFIG_RAW_DRIVER is not set
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+
+#
+# TPM devices
+#
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# 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=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+CONFIG_I2C_NFORCE2=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+# CONFIG_IBM_ASM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y
+
+#
+# Encoders and Decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+
+#
+# V4L USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_24XXX=y
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=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=m
+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=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+
+#
+# Radio Adapters
+#
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# 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_UMT_010=m
+CONFIG_DVB_USB_CXUSB=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_DTT200U=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_S5H1420=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+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
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+
+#
+# Miscellaneous devices
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6421=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_VIDEO_VIDEOBUF=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_BUF=m
+CONFIG_VIDEO_BUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+CONFIG_FB_VGA16=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_VIDEO_SELECT=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# 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
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+# CONFIG_SND_SERIAL_U16550 is not set
+CONFIG_SND_MPU401=m
+
+#
+# PCI devices
+#
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_ACECAD=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_TOUCHSCREEN=m
+CONFIG_USB_TOUCHSCREEN_EGALAX=y
+CONFIG_USB_TOUCHSCREEN_PANJIT=y
+CONFIG_USB_TOUCHSCREEN_3M=y
+CONFIG_USB_TOUCHSCREEN_ITM=y
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+CONFIG_USB_ATI_REMOTE2=m
+CONFIG_USB_KEYSPAN_REMOTE=m
+CONFIG_USB_APPLETOUCH=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=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_NET_ZAURUS=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_WBSD=m
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_IPATH_CORE=m
+CONFIG_INFINIBAND_IPATH=m
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_K8=m
+CONFIG_EDAC_POLL=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+CONFIG_RTC_DRV_V3020=m
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+CONFIG_OCFS2_FS=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_CACHEFILES=m
+CONFIG_CACHEFILES_DEBUG=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=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_JFFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_SQUASHFS_VMALLOC is not set
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+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
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_LIST=y
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+CONFIG_BOOT_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_RODATA=y
+# CONFIG_IOMMU_DEBUG is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_SECLVL is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_SIGNATURE=y
+CONFIG_CRYPTO_SIGNATURE_DSA=y
+CONFIG_CRYPTO_MPILIB=y
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
new file mode 100644 (file)
index 0000000..a01ce67
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+#include <acpi/acutils.h>
+
+ACPI_MODULE_NAME("cm_sbs")
+#define ACPI_AC_CLASS          "ac_adapter"
+#define ACPI_BATTERY_CLASS     "battery"
+#define ACPI_SBS_COMPONENT     0x00080000
+#define _COMPONENT             ACPI_SBS_COMPONENT
+static struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_battery_dir;
+
+static DEFINE_MUTEX(cm_sbs_mutex);
+
+static int lock_ac_dir_cnt;
+static int lock_battery_dir_cnt;
+
+struct proc_dir_entry *acpi_lock_ac_dir(void)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (!acpi_ac_dir)
+               acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
+       if (acpi_ac_dir) {
+               lock_ac_dir_cnt++;
+       } else {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Cannot create %s\n", ACPI_AC_CLASS));
+       }
+       mutex_unlock(&cm_sbs_mutex);
+       return acpi_ac_dir;
+}
+EXPORT_SYMBOL(acpi_lock_ac_dir);
+
+void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (acpi_ac_dir_param)
+               lock_ac_dir_cnt--;
+       if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
+               remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
+               acpi_ac_dir = 0;
+       }
+       mutex_unlock(&cm_sbs_mutex);
+}
+EXPORT_SYMBOL(acpi_unlock_ac_dir);
+
+struct proc_dir_entry *acpi_lock_battery_dir(void)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (!acpi_battery_dir) {
+               acpi_battery_dir =
+                   proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
+       }
+       if (acpi_battery_dir) {
+               lock_battery_dir_cnt++;
+       } else {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Cannot create %s\n", ACPI_BATTERY_CLASS));
+       }
+       mutex_unlock(&cm_sbs_mutex);
+       return acpi_battery_dir;
+}
+EXPORT_SYMBOL(acpi_lock_battery_dir);
+
+void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (acpi_battery_dir_param)
+               lock_battery_dir_cnt--;
+       if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
+           && acpi_battery_dir) {
+               remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
+               acpi_battery_dir = 0;
+       }
+       mutex_unlock(&cm_sbs_mutex);
+       return;
+}
+EXPORT_SYMBOL(acpi_unlock_battery_dir);
+
+static int __init acpi_cm_sbs_init(void)
+{
+       return 0;
+}
+subsys_initcall(acpi_cm_sbs_init);
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
new file mode 100644 (file)
index 0000000..578b99b
--- /dev/null
@@ -0,0 +1,739 @@
+/*
+ *  dock.c - ACPI dock station driver
+ *
+ *  Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/notifier.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver"
+
+ACPI_MODULE_NAME("dock")
+MODULE_AUTHOR("Kristen Carlson Accardi");
+MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+static struct atomic_notifier_head dock_notifier_list;
+
+struct dock_station {
+       acpi_handle handle;
+       unsigned long last_dock_time;
+       u32 flags;
+       spinlock_t dd_lock;
+       spinlock_t hp_lock;
+       struct list_head dependent_devices;
+       struct list_head hotplug_devices;
+};
+
+struct dock_dependent_device {
+       struct list_head list;
+       struct list_head hotplug_list;
+       acpi_handle handle;
+       acpi_notify_handler handler;
+       void *context;
+};
+
+#define DOCK_DOCKING   0x00000001
+#define DOCK_EVENT     3
+#define UNDOCK_EVENT   2
+
+static struct dock_station *dock_station;
+
+/*****************************************************************************
+ *                         Dock Dependent device functions                   *
+ *****************************************************************************/
+/**
+ *  alloc_dock_dependent_device - allocate and init a dependent device
+ *  @handle: the acpi_handle of the dependent device
+ *
+ *  Allocate memory for a dependent device structure for a device referenced
+ *  by the acpi handle
+ */
+static struct dock_dependent_device *
+alloc_dock_dependent_device(acpi_handle handle)
+{
+       struct dock_dependent_device *dd;
+
+       dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+       if (dd) {
+               dd->handle = handle;
+               INIT_LIST_HEAD(&dd->list);
+               INIT_LIST_HEAD(&dd->hotplug_list);
+       }
+       return dd;
+}
+
+/**
+ * add_dock_dependent_device - associate a device with the dock station
+ * @ds: The dock station
+ * @dd: The dependent device
+ *
+ * Add the dependent device to the dock's dependent device list.
+ */
+static void
+add_dock_dependent_device(struct dock_station *ds,
+                         struct dock_dependent_device *dd)
+{
+       spin_lock(&ds->dd_lock);
+       list_add_tail(&dd->list, &ds->dependent_devices);
+       spin_unlock(&ds->dd_lock);
+}
+
+/**
+ * dock_add_hotplug_device - associate a hotplug handler with the dock station
+ * @ds: The dock station
+ * @dd: The dependent device struct
+ *
+ * Add the dependent device to the dock's hotplug device list
+ */
+static void
+dock_add_hotplug_device(struct dock_station *ds,
+                       struct dock_dependent_device *dd)
+{
+       spin_lock(&ds->hp_lock);
+       list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
+       spin_unlock(&ds->hp_lock);
+}
+
+/**
+ * dock_del_hotplug_device - remove a hotplug handler from the dock station
+ * @ds: The dock station
+ * @dd: the dependent device struct
+ *
+ * Delete the dependent device from the dock's hotplug device list
+ */
+static void
+dock_del_hotplug_device(struct dock_station *ds,
+                       struct dock_dependent_device *dd)
+{
+       spin_lock(&ds->hp_lock);
+       list_del(&dd->hotplug_list);
+       spin_unlock(&ds->hp_lock);
+}
+
+/**
+ * find_dock_dependent_device - get a device dependent on this dock
+ * @ds: the dock station
+ * @handle: the acpi_handle of the device we want
+ *
+ * iterate over the dependent device list for this dock.  If the
+ * dependent device matches the handle, return.
+ */
+static struct dock_dependent_device *
+find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
+{
+       struct dock_dependent_device *dd;
+
+       spin_lock(&ds->dd_lock);
+       list_for_each_entry(dd, &ds->dependent_devices, list) {
+               if (handle == dd->handle) {
+                       spin_unlock(&ds->dd_lock);
+                       return dd;
+               }
+       }
+       spin_unlock(&ds->dd_lock);
+       return NULL;
+}
+
+/*****************************************************************************
+ *                         Dock functions                                    *
+ *****************************************************************************/
+/**
+ * is_dock - see if a device is a dock station
+ * @handle: acpi handle of the device
+ *
+ * If an acpi object has a _DCK method, then it is by definition a dock
+ * station, so return true.
+ */
+static int is_dock(acpi_handle handle)
+{
+       acpi_status status;
+       acpi_handle tmp;
+
+       status = acpi_get_handle(handle, "_DCK", &tmp);
+       if (ACPI_FAILURE(status))
+               return 0;
+       return 1;
+}
+
+/**
+ * is_dock_device - see if a device is on a dock station
+ * @handle: acpi handle of the device
+ *
+ * If this device is either the dock station itself,
+ * or is a device dependent on the dock station, then it
+ * is a dock device
+ */
+int is_dock_device(acpi_handle handle)
+{
+       if (!dock_station)
+               return 0;
+
+       if (is_dock(handle) || find_dock_dependent_device(dock_station, handle))
+               return 1;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(is_dock_device);
+
+/**
+ * dock_present - see if the dock station is present.
+ * @ds: the dock station
+ *
+ * execute the _STA method.  note that present does not
+ * imply that we are docked.
+ */
+static int dock_present(struct dock_station *ds)
+{
+       unsigned long sta;
+       acpi_status status;
+
+       if (ds) {
+               status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta);
+               if (ACPI_SUCCESS(status) && sta)
+                       return 1;
+       }
+       return 0;
+}
+
+
+
+/**
+ * dock_create_acpi_device - add new devices to acpi
+ * @handle - handle of the device to add
+ *
+ *  This function will create a new acpi_device for the given
+ *  handle if one does not exist already.  This should cause
+ *  acpi to scan for drivers for the given devices, and call
+ *  matching driver's add routine.
+ *
+ *  Returns a pointer to the acpi_device corresponding to the handle.
+ */
+static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
+{
+       struct acpi_device *device = NULL;
+       struct acpi_device *parent_device;
+       acpi_handle parent;
+       int ret;
+
+       if (acpi_bus_get_device(handle, &device)) {
+               /*
+                * no device created for this object,
+                * so we should create one.
+                */
+               acpi_get_parent(handle, &parent);
+               if (acpi_bus_get_device(parent, &parent_device))
+                       parent_device = NULL;
+
+               ret = acpi_bus_add(&device, parent_device, handle,
+                       ACPI_BUS_TYPE_DEVICE);
+               if (ret) {
+                       pr_debug("error adding bus, %x\n",
+                               -ret);
+                       return NULL;
+               }
+       }
+       return device;
+}
+
+/**
+ * dock_remove_acpi_device - remove the acpi_device struct from acpi
+ * @handle - the handle of the device to remove
+ *
+ *  Tell acpi to remove the acpi_device.  This should cause any loaded
+ *  driver to have it's remove routine called.
+ */
+static void dock_remove_acpi_device(acpi_handle handle)
+{
+       struct acpi_device *device;
+       int ret;
+
+       if (!acpi_bus_get_device(handle, &device)) {
+               ret = acpi_bus_trim(device, 1);
+               if (ret)
+                       pr_debug("error removing bus, %x\n", -ret);
+       }
+}
+
+
+/**
+ * hotplug_dock_devices - insert or remove devices on the dock station
+ * @ds: the dock station
+ * @event: either bus check or eject request
+ *
+ * Some devices on the dock station need to have drivers called
+ * to perform hotplug operations after a dock event has occurred.
+ * Traverse the list of dock devices that have registered a
+ * hotplug handler, and call the handler.
+ */
+static void hotplug_dock_devices(struct dock_station *ds, u32 event)
+{
+       struct dock_dependent_device *dd;
+
+       spin_lock(&ds->hp_lock);
+
+       /*
+        * First call driver specific hotplug functions
+        */
+       list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
+               if (dd->handler)
+                       dd->handler(dd->handle, event, dd->context);
+       }
+
+       /*
+        * Now make sure that an acpi_device is created for each
+        * dependent device, or removed if this is an eject request.
+        * This will cause acpi_drivers to be stopped/started if they
+        * exist
+        */
+       list_for_each_entry(dd, &ds->dependent_devices, list) {
+               if (event == ACPI_NOTIFY_EJECT_REQUEST)
+                       dock_remove_acpi_device(dd->handle);
+               else
+                       dock_create_acpi_device(dd->handle);
+       }
+       spin_unlock(&ds->hp_lock);
+}
+
+static void dock_event(struct dock_station *ds, u32 event, int num)
+{
+       /*
+        * we don't do events until someone tells me that
+        * they would like to have them.
+        */
+}
+
+/**
+ * eject_dock - respond to a dock eject request
+ * @ds: the dock station
+ *
+ * This is called after _DCK is called, to execute the dock station's
+ * _EJ0 method.
+ */
+static void eject_dock(struct dock_station *ds)
+{
+       struct acpi_object_list arg_list;
+       union acpi_object arg;
+       acpi_status status;
+       acpi_handle tmp;
+
+       /* all dock devices should have _EJ0, but check anyway */
+       status = acpi_get_handle(ds->handle, "_EJ0", &tmp);
+       if (ACPI_FAILURE(status)) {
+               pr_debug("No _EJ0 support for dock device\n");
+               return;
+       }
+
+       arg_list.count = 1;
+       arg_list.pointer = &arg;
+       arg.type = ACPI_TYPE_INTEGER;
+       arg.integer.value = 1;
+
+       if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0",
+                                             &arg_list, NULL)))
+               pr_debug("Failed to evaluate _EJ0!\n");
+}
+
+/**
+ * handle_dock - handle a dock event
+ * @ds: the dock station
+ * @dock: to dock, or undock - that is the question
+ *
+ * Execute the _DCK method in response to an acpi event
+ */
+static void handle_dock(struct dock_station *ds, int dock)
+{
+       acpi_status status;
+       struct acpi_object_list arg_list;
+       union acpi_object arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+
+       acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
+       obj = name_buffer.pointer;
+
+       printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking");
+
+       /* _DCK method has one argument */
+       arg_list.count = 1;
+       arg_list.pointer = &arg;
+       arg.type = ACPI_TYPE_INTEGER;
+       arg.integer.value = dock;
+       status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
+       if (ACPI_FAILURE(status))
+               pr_debug("%s: failed to execute _DCK\n", obj->string.pointer);
+       kfree(buffer.pointer);
+       kfree(name_buffer.pointer);
+}
+
+static inline void dock(struct dock_station *ds)
+{
+       handle_dock(ds, 1);
+}
+
+static inline void undock(struct dock_station *ds)
+{
+       handle_dock(ds, 0);
+}
+
+static inline void begin_dock(struct dock_station *ds)
+{
+       ds->flags |= DOCK_DOCKING;
+}
+
+static inline void complete_dock(struct dock_station *ds)
+{
+       ds->flags &= ~(DOCK_DOCKING);
+       ds->last_dock_time = jiffies;
+}
+
+/**
+ * dock_in_progress - see if we are in the middle of handling a dock event
+ * @ds: the dock station
+ *
+ * Sometimes while docking, false dock events can be sent to the driver
+ * because good connections aren't made or some other reason.  Ignore these
+ * if we are in the middle of doing something.
+ */
+static int dock_in_progress(struct dock_station *ds)
+{
+       if ((ds->flags & DOCK_DOCKING) ||
+           time_before(jiffies, (ds->last_dock_time + HZ)))
+               return 1;
+       return 0;
+}
+
+/**
+ * register_dock_notifier - add yourself to the dock notifier list
+ * @nb: the callers notifier block
+ *
+ * If a driver wishes to be notified about dock events, they can
+ * use this function to put a notifier block on the dock notifier list.
+ * this notifier call chain will be called after a dock event, but
+ * before hotplugging any new devices.
+ */
+int register_dock_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&dock_notifier_list, nb);
+}
+
+EXPORT_SYMBOL_GPL(register_dock_notifier);
+
+/**
+ * unregister_dock_notifier - remove yourself from the dock notifier list
+ * @nb: the callers notifier block
+ */
+void unregister_dock_notifier(struct notifier_block *nb)
+{
+       atomic_notifier_chain_unregister(&dock_notifier_list, nb);
+}
+
+EXPORT_SYMBOL_GPL(unregister_dock_notifier);
+
+/**
+ * register_hotplug_dock_device - register a hotplug function
+ * @handle: the handle of the device
+ * @handler: the acpi_notifier_handler to call after docking
+ * @context: device specific data
+ *
+ * If a driver would like to perform a hotplug operation after a dock
+ * event, they can register an acpi_notifiy_handler to be called by
+ * the dock driver after _DCK is executed.
+ */
+int
+register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler,
+                            void *context)
+{
+       struct dock_dependent_device *dd;
+
+       if (!dock_station)
+               return -ENODEV;
+
+       /*
+        * make sure this handle is for a device dependent on the dock,
+        * this would include the dock station itself
+        */
+       dd = find_dock_dependent_device(dock_station, handle);
+       if (dd) {
+               dd->handler = handler;
+               dd->context = context;
+               dock_add_hotplug_device(dock_station, dd);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
+
+/**
+ * unregister_hotplug_dock_device - remove yourself from the hotplug list
+ * @handle: the acpi handle of the device
+ */
+void unregister_hotplug_dock_device(acpi_handle handle)
+{
+       struct dock_dependent_device *dd;
+
+       if (!dock_station)
+               return;
+
+       dd = find_dock_dependent_device(dock_station, handle);
+       if (dd)
+               dock_del_hotplug_device(dock_station, dd);
+}
+
+EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
+
+/**
+ * dock_notify - act upon an acpi dock notification
+ * @handle: the dock station handle
+ * @event: the acpi event
+ * @data: our driver data struct
+ *
+ * If we are notified to dock, then check to see if the dock is
+ * present and then dock.  Notify all drivers of the dock event,
+ * and then hotplug and devices that may need hotplugging.  For undock
+ * check to make sure the dock device is still present, then undock
+ * and hotremove all the devices that may need removing.
+ */
+static void dock_notify(acpi_handle handle, u32 event, void *data)
+{
+       struct dock_station *ds = (struct dock_station *)data;
+
+       switch (event) {
+       case ACPI_NOTIFY_BUS_CHECK:
+               if (!dock_in_progress(ds) && dock_present(ds)) {
+                       begin_dock(ds);
+                       dock(ds);
+                       if (!dock_present(ds)) {
+                               printk(KERN_ERR PREFIX "Unable to dock!\n");
+                               break;
+                       }
+                       atomic_notifier_call_chain(&dock_notifier_list,
+                                                  event, NULL);
+                       hotplug_dock_devices(ds, event);
+                       complete_dock(ds);
+                       dock_event(ds, event, DOCK_EVENT);
+               }
+               break;
+       case ACPI_NOTIFY_DEVICE_CHECK:
+       /*
+         * According to acpi spec 3.0a, if a DEVICE_CHECK notification
+         * is sent and _DCK is present, it is assumed to mean an
+         * undock request.  This notify routine will only be called
+         * for objects defining _DCK, so we will fall through to eject
+         * request here.  However, we will pass an eject request through
+        * to the driver who wish to hotplug.
+         */
+       case ACPI_NOTIFY_EJECT_REQUEST:
+               if (!dock_in_progress(ds) && dock_present(ds)) {
+                       /*
+                        * here we need to generate the undock
+                        * event prior to actually doing the undock
+                        * so that the device struct still exists.
+                        */
+                       dock_event(ds, event, UNDOCK_EVENT);
+                       hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
+                       undock(ds);
+                       eject_dock(ds);
+                       if (dock_present(ds))
+                               printk(KERN_ERR PREFIX "Unable to undock!\n");
+               }
+               break;
+       default:
+               printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
+       }
+}
+
+/**
+ * find_dock_devices - find devices on the dock station
+ * @handle: the handle of the device we are examining
+ * @lvl: unused
+ * @context: the dock station private data
+ * @rv: unused
+ *
+ * This function is called by acpi_walk_namespace.  It will
+ * check to see if an object has an _EJD method.  If it does, then it
+ * will see if it is dependent on the dock station.
+ */
+static acpi_status
+find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       acpi_status status;
+       acpi_handle tmp;
+       struct dock_station *ds = (struct dock_station *)context;
+       struct dock_dependent_device *dd;
+
+       status = acpi_bus_get_ejd(handle, &tmp);
+       if (ACPI_FAILURE(status))
+               return AE_OK;
+
+       if (tmp == ds->handle) {
+               dd = alloc_dock_dependent_device(handle);
+               if (dd)
+                       add_dock_dependent_device(ds, dd);
+       }
+
+       return AE_OK;
+}
+
+/**
+ * dock_add - add a new dock station
+ * @handle: the dock station handle
+ *
+ * allocated and initialize a new dock station device.  Find all devices
+ * that are on the dock station, and register for dock event notifications.
+ */
+static int dock_add(acpi_handle handle)
+{
+       int ret;
+       acpi_status status;
+       struct dock_dependent_device *dd;
+
+       /* allocate & initialize the dock_station private data */
+       dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
+       if (!dock_station)
+               return -ENOMEM;
+       dock_station->handle = handle;
+       dock_station->last_dock_time = jiffies - HZ;
+       INIT_LIST_HEAD(&dock_station->dependent_devices);
+       INIT_LIST_HEAD(&dock_station->hotplug_devices);
+       spin_lock_init(&dock_station->dd_lock);
+       spin_lock_init(&dock_station->hp_lock);
+       ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
+
+       /* Find dependent devices */
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                           ACPI_UINT32_MAX, find_dock_devices, dock_station,
+                           NULL);
+
+       /* add the dock station as a device dependent on itself */
+       dd = alloc_dock_dependent_device(handle);
+       if (!dd) {
+               kfree(dock_station);
+               return -ENOMEM;
+       }
+       add_dock_dependent_device(dock_station, dd);
+
+       /* register for dock events */
+       status = acpi_install_notify_handler(dock_station->handle,
+                                            ACPI_SYSTEM_NOTIFY,
+                                            dock_notify, dock_station);
+
+       if (ACPI_FAILURE(status)) {
+               printk(KERN_ERR PREFIX "Error installing notify handler\n");
+               ret = -ENODEV;
+               goto dock_add_err;
+       }
+
+       printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME);
+
+       return 0;
+
+dock_add_err:
+       kfree(dock_station);
+       kfree(dd);
+       return ret;
+}
+
+/**
+ * dock_remove - free up resources related to the dock station
+ */
+static int dock_remove(void)
+{
+       struct dock_dependent_device *dd, *tmp;
+       acpi_status status;
+
+       if (!dock_station)
+               return 0;
+
+       /* remove dependent devices */
+       list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices,
+                                list)
+           kfree(dd);
+
+       /* remove dock notify handler */
+       status = acpi_remove_notify_handler(dock_station->handle,
+                                           ACPI_SYSTEM_NOTIFY,
+                                           dock_notify);
+       if (ACPI_FAILURE(status))
+               printk(KERN_ERR "Error removing notify handler\n");
+
+       /* free dock station memory */
+       kfree(dock_station);
+       return 0;
+}
+
+/**
+ * find_dock - look for a dock station
+ * @handle: acpi handle of a device
+ * @lvl: unused
+ * @context: counter of dock stations found
+ * @rv: unused
+ *
+ * This is called by acpi_walk_namespace to look for dock stations.
+ */
+static acpi_status
+find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       int *count = (int *)context;
+       acpi_status status = AE_OK;
+
+       if (is_dock(handle)) {
+               if (dock_add(handle) >= 0) {
+                       (*count)++;
+                       status = AE_CTRL_TERMINATE;
+               }
+       }
+       return status;
+}
+
+static int __init dock_init(void)
+{
+       int num = 0;
+
+       dock_station = NULL;
+
+       /* look for a dock station */
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                           ACPI_UINT32_MAX, find_dock, &num, NULL);
+
+       if (!num)
+               return -ENODEV;
+
+       return 0;
+}
+
+static void __exit dock_exit(void)
+{
+       dock_remove();
+}
+
+postcore_initcall(dock_init);
+module_exit(dock_exit);
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
new file mode 100644 (file)
index 0000000..6809c28
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $)
+ *
+ * Copyright (c) 2002, 2005 Ducrot Bruno
+ * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+
+#include "i2c_ec.h"
+
+#define        xudelay(t)      udelay(t)
+#define        xmsleep(t)      msleep(t)
+
+#define ACPI_EC_HC_COMPONENT   0x00080000
+#define ACPI_EC_HC_CLASS       "ec_hc_smbus"
+#define ACPI_EC_HC_HID         "ACPI0001"
+#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver"
+#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
+
+#define _COMPONENT             ACPI_EC_HC_COMPONENT
+
+ACPI_MODULE_NAME("acpi_smbus")
+
+static int acpi_ec_hc_add(struct acpi_device *device);
+static int acpi_ec_hc_remove(struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_ec_hc_driver = {
+       .name = ACPI_EC_HC_DRIVER_NAME,
+       .class = ACPI_EC_HC_CLASS,
+       .ids = ACPI_EC_HC_HID,
+       .ops = {
+               .add = acpi_ec_hc_add,
+               .remove = acpi_ec_hc_remove,
+               },
+};
+
+/* Various bit mask for EC_SC (R) */
+#define OBF            0x01
+#define IBF            0x02
+#define CMD            0x08
+#define BURST          0x10
+#define SCI_EVT                0x20
+#define SMI_EVT                0x40
+
+/* Commands for EC_SC (W) */
+#define RD_EC          0x80
+#define WR_EC          0x81
+#define BE_EC          0x82
+#define BD_EC          0x83
+#define QR_EC          0x84
+
+/*
+ * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
+ */
+
+#define ACPI_EC_SMB_PRTCL      0x00    /* protocol, PEC */
+#define ACPI_EC_SMB_STS                0x01    /* status */
+#define ACPI_EC_SMB_ADDR       0x02    /* address */
+#define ACPI_EC_SMB_CMD                0x03    /* command */
+#define ACPI_EC_SMB_DATA       0x04    /* 32 data registers */
+#define ACPI_EC_SMB_BCNT       0x24    /* number of data bytes */
+#define ACPI_EC_SMB_ALRM_A     0x25    /* alarm address */
+#define ACPI_EC_SMB_ALRM_D     0x26    /* 2 bytes alarm data */
+
+#define ACPI_EC_SMB_STS_DONE   0x80
+#define ACPI_EC_SMB_STS_ALRM   0x40
+#define ACPI_EC_SMB_STS_RES    0x20
+#define ACPI_EC_SMB_STS_STATUS 0x1f
+
+#define ACPI_EC_SMB_STATUS_OK          0x00
+#define ACPI_EC_SMB_STATUS_FAIL                0x07
+#define ACPI_EC_SMB_STATUS_DNAK                0x10
+#define ACPI_EC_SMB_STATUS_DERR                0x11
+#define ACPI_EC_SMB_STATUS_CMD_DENY    0x12
+#define ACPI_EC_SMB_STATUS_UNKNOWN     0x13
+#define ACPI_EC_SMB_STATUS_ACC_DENY    0x17
+#define ACPI_EC_SMB_STATUS_TIMEOUT     0x18
+#define ACPI_EC_SMB_STATUS_NOTSUP      0x19
+#define ACPI_EC_SMB_STATUS_BUSY                0x1A
+#define ACPI_EC_SMB_STATUS_PEC         0x1F
+
+#define ACPI_EC_SMB_PRTCL_WRITE                        0x00
+#define ACPI_EC_SMB_PRTCL_READ                 0x01
+#define ACPI_EC_SMB_PRTCL_QUICK                        0x02
+#define ACPI_EC_SMB_PRTCL_BYTE                 0x04
+#define ACPI_EC_SMB_PRTCL_BYTE_DATA            0x06
+#define ACPI_EC_SMB_PRTCL_WORD_DATA            0x08
+#define ACPI_EC_SMB_PRTCL_BLOCK_DATA           0x0a
+#define ACPI_EC_SMB_PRTCL_PROC_CALL            0x0c
+#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL      0x0d
+#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA       0x4a
+#define ACPI_EC_SMB_PRTCL_PEC                  0x80
+
+/* Length of pre/post transaction sleep (msec) */
+#define ACPI_EC_SMB_TRANSACTION_SLEEP          1
+#define ACPI_EC_SMB_ACCESS_SLEEP1              1
+#define ACPI_EC_SMB_ACCESS_SLEEP2              10
+
+static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data)
+{
+       u8 val;
+       int err;
+
+       err = ec_read(smbus->base + address, &val);
+       if (!err) {
+               *data = val;
+       }
+       xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
+       return (err);
+}
+
+static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data)
+{
+       int err;
+
+       err = ec_write(smbus->base + address, data);
+       return (err);
+}
+
+static int
+acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+                  char read_write, u8 command, int size,
+                  union i2c_smbus_data *data)
+{
+       struct acpi_ec_smbus *smbus = adap->algo_data;
+       unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 };
+       int i;
+
+       if (read_write == I2C_SMBUS_READ) {
+               protocol = ACPI_EC_SMB_PRTCL_READ;
+       } else {
+               protocol = ACPI_EC_SMB_PRTCL_WRITE;
+       }
+       pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0;
+
+       switch (size) {
+
+       case I2C_SMBUS_QUICK:
+               protocol |= ACPI_EC_SMB_PRTCL_QUICK;
+               read_write = I2C_SMBUS_WRITE;
+               break;
+
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BYTE;
+               break;
+
+       case I2C_SMBUS_BYTE_DATA:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA;
+               break;
+
+       case I2C_SMBUS_WORD_DATA:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1,
+                                         data->word >> 8);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec;
+               break;
+
+       case I2C_SMBUS_BLOCK_DATA:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       len = min_t(u8, data->block[0], 32);
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
+                       for (i = 0; i < len; i++)
+                               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
+                                                 data->block[i + 1]);
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec;
+               break;
+
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               len = min_t(u8, data->block[0], 32);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       for (i = 0; i < len; i++) {
+                               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
+                                                 data->block[i + 1]);
+                       }
+               }
+               protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA;
+               break;
+
+       case I2C_SMBUS_PROC_CALL:
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8);
+               protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec;
+               read_write = I2C_SMBUS_READ;
+               break;
+
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               protocol |= pec;
+               len = min_t(u8, data->block[0], 31);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
+               acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
+               for (i = 0; i < len; i++)
+                       acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
+                                         data->block[i + 1]);
+               protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec;
+               read_write = I2C_SMBUS_READ;
+               break;
+
+       default:
+               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: "
+                                 "Unsupported transaction %d\n", size));
+               return (-1);
+       }
+
+       acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1);
+       acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol);
+
+       acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
+
+       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
+               xudelay(500);
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
+       }
+       if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
+               xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2);
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
+       }
+       if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
+           || (temp[0] & ACPI_EC_SMB_STS_STATUS)) {
+               return (-1);
+       }
+
+       if (read_write == I2C_SMBUS_WRITE) {
+               return (0);
+       }
+
+       switch (size) {
+
+       case I2C_SMBUS_BYTE:
+       case I2C_SMBUS_BYTE_DATA:
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte);
+               break;
+
+       case I2C_SMBUS_WORD_DATA:
+       case I2C_SMBUS_PROC_CALL:
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0);
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1);
+               data->word = (temp[1] << 8) | temp[0];
+               break;
+
+       case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               len = 0;
+               acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len);
+               len = min_t(u8, len, 32);
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               for (i = 0; i < len; i++)
+                       acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i,
+                                        data->block + i + 1);
+               data->block[0] = len;
+               break;
+       }
+
+       return (0);
+}
+
+static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
+{
+
+       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_BLOCK_DATA |
+               I2C_FUNC_SMBUS_PROC_CALL |
+               I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+               I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
+}
+
+static struct i2c_algorithm acpi_ec_smbus_algorithm = {
+       .smbus_xfer = acpi_ec_smb_access,
+       .functionality = acpi_ec_smb_func,
+};
+
+static int acpi_ec_hc_add(struct acpi_device *device)
+{
+       int status;
+       unsigned long val;
+       struct acpi_ec_hc *ec_hc;
+       struct acpi_ec_smbus *smbus;
+
+       if (!device) {
+               return -EINVAL;
+       }
+
+       ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
+       if (!ec_hc) {
+               return -ENOMEM;
+       }
+       memset(ec_hc, 0, sizeof(struct acpi_ec_hc));
+
+       smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
+       if (!smbus) {
+               kfree(ec_hc);
+               return -ENOMEM;
+       }
+       memset(smbus, 0, sizeof(struct acpi_ec_smbus));
+
+       ec_hc->handle = device->handle;
+       strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS);
+       acpi_driver_data(device) = ec_hc;
+
+       status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
+               kfree(ec_hc);
+               kfree(smbus);
+               return -EIO;
+       }
+
+       smbus->ec = acpi_driver_data(device->parent);
+       smbus->base = (val & 0xff00ull) >> 8;
+       smbus->alert = val & 0xffull;
+
+       smbus->adapter.owner = THIS_MODULE;
+       smbus->adapter.algo = &acpi_ec_smbus_algorithm;
+       smbus->adapter.algo_data = smbus;
+
+       if (i2c_add_adapter(&smbus->adapter)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+                                 "EC SMBus adapter: Failed to register adapter\n"));
+               kfree(smbus);
+               kfree(ec_hc);
+               return -EIO;
+       }
+
+       ec_hc->smbus = smbus;
+
+       printk(KERN_INFO PREFIX "%s [%s]\n",
+              acpi_device_name(device), acpi_device_bid(device));
+
+       return AE_OK;
+}
+
+static int acpi_ec_hc_remove(struct acpi_device *device, int type)
+{
+       struct acpi_ec_hc *ec_hc;
+
+       if (!device) {
+               return -EINVAL;
+       }
+       ec_hc = acpi_driver_data(device);
+
+       i2c_del_adapter(&ec_hc->smbus->adapter);
+       kfree(ec_hc->smbus);
+       kfree(ec_hc);
+
+       return AE_OK;
+}
+
+static int __init acpi_ec_hc_init(void)
+{
+       int result;
+
+       result = acpi_bus_register_driver(&acpi_ec_hc_driver);
+       if (result < 0) {
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit acpi_ec_hc_exit(void)
+{
+       acpi_bus_unregister_driver(&acpi_ec_hc_driver);
+}
+
+struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
+{
+       return ((struct acpi_ec_hc *)acpi_driver_data(device->parent));
+}
+
+EXPORT_SYMBOL(acpi_get_ec_hc);
+
+module_init(acpi_ec_hc_init);
+module_exit(acpi_ec_hc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ducrot Bruno");
+MODULE_DESCRIPTION("ACPI EC SMBus driver");
diff --git a/drivers/acpi/i2c_ec.h b/drivers/acpi/i2c_ec.h
new file mode 100644 (file)
index 0000000..7c53fb7
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
+ *
+ * Copyright (c) 2002, 2005 Ducrot Bruno
+ *
+ * This program is free software; 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.
+ */
+
+struct acpi_ec_smbus {
+       struct i2c_adapter adapter;
+       union acpi_ec *ec;
+       int base;
+       int alert;
+};
+
+struct acpi_ec_hc {
+       acpi_handle handle;
+       struct acpi_ec_smbus *smbus;
+};
+
+struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
new file mode 100644 (file)
index 0000000..62bef0b
--- /dev/null
@@ -0,0 +1,1769 @@
+/*
+ *  acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $)
+ *
+ *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+
+#include "i2c_ec.h"
+
+#define        DEF_CAPACITY_UNIT       3
+#define        MAH_CAPACITY_UNIT       1
+#define        MWH_CAPACITY_UNIT       2
+#define        CAPACITY_UNIT           DEF_CAPACITY_UNIT
+
+#define        REQUEST_UPDATE_MODE     1
+#define        QUEUE_UPDATE_MODE       2
+
+#define        DATA_TYPE_COMMON        0
+#define        DATA_TYPE_INFO          1
+#define        DATA_TYPE_STATE         2
+#define        DATA_TYPE_ALARM         3
+#define        DATA_TYPE_AC_STATE      4
+
+extern struct proc_dir_entry *acpi_lock_ac_dir(void);
+extern struct proc_dir_entry *acpi_lock_battery_dir(void);
+extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
+
+#define ACPI_SBS_COMPONENT             0x00080000
+#define ACPI_SBS_CLASS                 "sbs"
+#define ACPI_AC_CLASS                  "ac_adapter"
+#define ACPI_BATTERY_CLASS             "battery"
+#define ACPI_SBS_HID                   "ACPI0002"
+#define ACPI_SBS_DRIVER_NAME           "ACPI Smart Battery System Driver"
+#define ACPI_SBS_DEVICE_NAME           "Smart Battery System"
+#define ACPI_SBS_FILE_INFO             "info"
+#define ACPI_SBS_FILE_STATE            "state"
+#define ACPI_SBS_FILE_ALARM            "alarm"
+#define ACPI_BATTERY_DIR_NAME          "BAT%i"
+#define ACPI_AC_DIR_NAME               "AC0"
+#define ACPI_SBC_SMBUS_ADDR            0x9
+#define ACPI_SBSM_SMBUS_ADDR           0xa
+#define ACPI_SB_SMBUS_ADDR             0xb
+#define ACPI_SBS_AC_NOTIFY_STATUS      0x80
+#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
+#define ACPI_SBS_BATTERY_NOTIFY_INFO   0x81
+
+#define _COMPONENT                     ACPI_SBS_COMPONENT
+
+#define        MAX_SBS_BAT                     4
+#define        MAX_SMBUS_ERR                   1
+
+ACPI_MODULE_NAME("acpi_sbs");
+
+MODULE_AUTHOR("Rich Townsend");
+MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
+MODULE_LICENSE("GPL");
+
+static struct semaphore sbs_sem;
+
+#define        UPDATE_MODE             QUEUE_UPDATE_MODE
+/* REQUEST_UPDATE_MODE  QUEUE_UPDATE_MODE */
+#define        UPDATE_INFO_MODE        0
+#define        UPDATE_TIME             60
+#define        UPDATE_TIME2            0
+
+static int capacity_mode = CAPACITY_UNIT;
+static int update_mode = UPDATE_MODE;
+static int update_info_mode = UPDATE_INFO_MODE;
+static int update_time = UPDATE_TIME;
+static int update_time2 = UPDATE_TIME2;
+
+module_param(capacity_mode, int, CAPACITY_UNIT);
+module_param(update_mode, int, UPDATE_MODE);
+module_param(update_info_mode, int, UPDATE_INFO_MODE);
+module_param(update_time, int, UPDATE_TIME);
+module_param(update_time2, int, UPDATE_TIME2);
+
+static int acpi_sbs_add(struct acpi_device *device);
+static int acpi_sbs_remove(struct acpi_device *device, int type);
+static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
+static void acpi_sbs_update_queue(void *data);
+
+static struct acpi_driver acpi_sbs_driver = {
+       .name = ACPI_SBS_DRIVER_NAME,
+       .class = ACPI_SBS_CLASS,
+       .ids = ACPI_SBS_HID,
+       .ops = {
+               .add = acpi_sbs_add,
+               .remove = acpi_sbs_remove,
+               },
+};
+
+struct acpi_battery_info {
+       int capacity_mode;
+       s16 full_charge_capacity;
+       s16 design_capacity;
+       s16 design_voltage;
+       int vscale;
+       int ipscale;
+       s16 serial_number;
+       char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3];
+       char device_name[I2C_SMBUS_BLOCK_MAX + 3];
+       char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3];
+};
+
+struct acpi_battery_state {
+       s16 voltage;
+       s16 amperage;
+       s16 remaining_capacity;
+       s16 average_time_to_empty;
+       s16 average_time_to_full;
+       s16 battery_status;
+};
+
+struct acpi_battery_alarm {
+       s16 remaining_capacity;
+};
+
+struct acpi_battery {
+       int alive;
+       int battery_present;
+       int id;
+       int init_state;
+       struct acpi_sbs *sbs;
+       struct acpi_battery_info info;
+       struct acpi_battery_state state;
+       struct acpi_battery_alarm alarm;
+       struct proc_dir_entry *battery_entry;
+};
+
+struct acpi_sbs {
+       acpi_handle handle;
+       struct acpi_device *device;
+       struct acpi_ec_smbus *smbus;
+       int sbsm_present;
+       int sbsm_batteries_supported;
+       int ac_present;
+       struct proc_dir_entry *ac_entry;
+       struct acpi_battery battery[MAX_SBS_BAT];
+       int update_info_mode;
+       int zombie;
+       int update_time;
+       int update_time2;
+       struct timer_list update_timer;
+};
+
+static void acpi_update_delay(struct acpi_sbs *sbs);
+static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type);
+
+/* --------------------------------------------------------------------------
+                               SMBus Communication
+   -------------------------------------------------------------------------- */
+
+static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus)
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       char *err_str;
+       int err_number;
+
+       data.word = 0;
+
+       result = smbus->adapter.algo->
+           smbus_xfer(&smbus->adapter,
+                      ACPI_SB_SMBUS_ADDR,
+                      0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data);
+
+       err_number = (data.word & 0x000f);
+
+       switch (data.word & 0x000f) {
+       case 0x0000:
+               err_str = "unexpected bus error";
+               break;
+       case 0x0001:
+               err_str = "busy";
+               break;
+       case 0x0002:
+               err_str = "reserved command";
+               break;
+       case 0x0003:
+               err_str = "unsupported command";
+               break;
+       case 0x0004:
+               err_str = "access denied";
+               break;
+       case 0x0005:
+               err_str = "overflow/underflow";
+               break;
+       case 0x0006:
+               err_str = "bad size";
+               break;
+       case 0x0007:
+               err_str = "unknown error";
+               break;
+       default:
+               err_str = "unrecognized error";
+       }
+       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                         "%s: ret %i, err %i\n", err_str, result, err_number));
+}
+
+static int
+acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func,
+                        u16 * word,
+                        void (*err_handler) (struct acpi_ec_smbus * smbus))
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       int i;
+
+       if (err_handler == NULL) {
+               err_handler = acpi_battery_smbus_err_handler;
+       }
+
+       for (i = 0; i < MAX_SMBUS_ERR; i++) {
+               result =
+                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
+                                                   I2C_SMBUS_READ, func,
+                                                   I2C_SMBUS_WORD_DATA, &data);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
+                                         i));
+                       if (err_handler) {
+                               err_handler(smbus);
+                       }
+               } else {
+                       *word = data.word;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+static int
+acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func,
+                       char *str,
+                       void (*err_handler) (struct acpi_ec_smbus * smbus))
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       int i;
+
+       if (err_handler == NULL) {
+               err_handler = acpi_battery_smbus_err_handler;
+       }
+
+       for (i = 0; i < MAX_SMBUS_ERR; i++) {
+               result =
+                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
+                                                   I2C_SMBUS_READ, func,
+                                                   I2C_SMBUS_BLOCK_DATA,
+                                                   &data);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
+                                         i));
+                       if (err_handler) {
+                               err_handler(smbus);
+                       }
+               } else {
+                       strncpy(str, (const char *)data.block + 1,
+                               data.block[0]);
+                       str[data.block[0]] = 0;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+static int
+acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func,
+                         int word,
+                         void (*err_handler) (struct acpi_ec_smbus * smbus))
+{
+       union i2c_smbus_data data;
+       int result = 0;
+       int i;
+
+       if (err_handler == NULL) {
+               err_handler = acpi_battery_smbus_err_handler;
+       }
+
+       data.word = word;
+
+       for (i = 0; i < MAX_SMBUS_ERR; i++) {
+               result =
+                   smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
+                                                   I2C_SMBUS_WRITE, func,
+                                                   I2C_SMBUS_WORD_DATA, &data);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "try %i: smbus->adapter.algo"
+                                         "->smbus_xfer() failed\n", i));
+                       if (err_handler) {
+                               err_handler(smbus);
+                       }
+               } else {
+                       break;
+               }
+       }
+
+       return result;
+}
+
+/* --------------------------------------------------------------------------
+                            Smart Battery System Management
+   -------------------------------------------------------------------------- */
+
+/* Smart Battery */
+
+static int acpi_sbs_generate_event(struct acpi_device *device,
+                                  int event, int state, char *bid, char *class)
+{
+       char bid_saved[5];
+       char class_saved[20];
+       int result = 0;
+
+       strcpy(bid_saved, acpi_device_bid(device));
+       strcpy(class_saved, acpi_device_class(device));
+
+       strcpy(acpi_device_bid(device), bid);
+       strcpy(acpi_device_class(device), class);
+
+       result = acpi_bus_generate_event(device, event, state);
+
+       strcpy(acpi_device_bid(device), bid_saved);
+       strcpy(acpi_device_class(device), class_saved);
+
+       return result;
+}
+
+static int acpi_battery_get_present(struct acpi_battery *battery)
+{
+       s16 state;
+       int result = 0;
+       int is_present = 0;
+
+       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
+                                         ACPI_SBSM_SMBUS_ADDR, 0x01,
+                                         &state, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed"));
+       }
+       if (!result) {
+               is_present = (state & 0x000f) & (1 << battery->id);
+       }
+       battery->battery_present = is_present;
+
+       return result;
+}
+
+static int acpi_battery_is_present(struct acpi_battery *battery)
+{
+       return (battery->battery_present);
+}
+
+static int acpi_ac_is_present(struct acpi_sbs *sbs)
+{
+       return (sbs->ac_present);
+}
+
+static int acpi_battery_select(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+       s16 state;
+       int foo;
+
+       if (battery->sbs->sbsm_present) {
+
+               /* Take special care not to knobble other nibbles of
+                * state (aka selector_state), since
+                * it causes charging to halt on SBSELs */
+
+               result =
+                   acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
+                                            &state, NULL);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_read_word() failed\n"));
+                       goto end;
+               }
+
+               foo = (state & 0x0fff) | (1 << (battery->id + 12));
+               result =
+                   acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
+                                             foo, NULL);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_write_word() failed\n"));
+                       goto end;
+               }
+       }
+
+      end:
+       return result;
+}
+
+static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
+{
+       struct acpi_ec_smbus *smbus = sbs->smbus;
+       int result = 0;
+       s16 battery_system_info;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04,
+                                         &battery_system_info, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
+
+      end:
+
+       return result;
+}
+
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+       s16 battery_mode;
+       s16 specification_info;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
+                                         &battery_mode,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+       battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10,
+                                         &battery->info.full_charge_capacity,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18,
+                                         &battery->info.design_capacity,
+                                         &acpi_battery_smbus_err_handler);
+
+       if (result) {
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19,
+                                         &battery->info.design_voltage,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a,
+                                         &specification_info,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       switch ((specification_info & 0x0f00) >> 8) {
+       case 1:
+               battery->info.vscale = 10;
+               break;
+       case 2:
+               battery->info.vscale = 100;
+               break;
+       case 3:
+               battery->info.vscale = 1000;
+               break;
+       default:
+               battery->info.vscale = 1;
+       }
+
+       switch ((specification_info & 0xf000) >> 12) {
+       case 1:
+               battery->info.ipscale = 10;
+               break;
+       case 2:
+               battery->info.ipscale = 100;
+               break;
+       case 3:
+               battery->info.ipscale = 1000;
+               break;
+       default:
+               battery->info.ipscale = 1;
+       }
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c,
+                                         &battery->info.serial_number,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20,
+                                        battery->info.manufacturer_name,
+                                        &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_str() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21,
+                                        battery->info.device_name,
+                                        &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_str() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22,
+                                        battery->info.device_chemistry,
+                                        &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_str() failed\n"));
+               goto end;
+       }
+
+      end:
+       return result;
+}
+
+static void acpi_update_delay(struct acpi_sbs *sbs)
+{
+       if (sbs->zombie) {
+               return;
+       }
+       if (sbs->update_time2 > 0) {
+               msleep(sbs->update_time2 * 1000);
+       }
+}
+
+static int acpi_battery_get_state(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09,
+                                         &battery->state.voltage,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a,
+                                         &battery->state.amperage,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f,
+                                         &battery->state.remaining_capacity,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12,
+                                         &battery->state.average_time_to_empty,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13,
+                                         &battery->state.average_time_to_full,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16,
+                                         &battery->state.battery_status,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+
+      end:
+       return result;
+}
+
+static int acpi_battery_get_alarm(struct acpi_battery *battery)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
+                                         &battery->alarm.remaining_capacity,
+                                         &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       acpi_update_delay(battery->sbs);
+
+      end:
+
+       return result;
+}
+
+static int acpi_battery_set_alarm(struct acpi_battery *battery,
+                                 unsigned long alarm)
+{
+       struct acpi_ec_smbus *smbus = battery->sbs->smbus;
+       int result = 0;
+       s16 battery_mode;
+       int foo;
+
+       result = acpi_battery_select(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_select() failed\n"));
+               goto end;
+       }
+
+       /* If necessary, enable the alarm */
+
+       if (alarm > 0) {
+               result =
+                   acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
+                                            &battery_mode,
+                                            &acpi_battery_smbus_err_handler);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_read_word() failed\n"));
+                       goto end;
+               }
+
+               result =
+                   acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
+                                             battery_mode & 0xbfff,
+                                             &acpi_battery_smbus_err_handler);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_smbus_write_word() failed\n"));
+                       goto end;
+               }
+       }
+
+       foo = alarm / (battery->info.capacity_mode ? 10 : 1);
+       result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
+                                          foo,
+                                          &acpi_battery_smbus_err_handler);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_write_word() failed\n"));
+               goto end;
+       }
+
+      end:
+
+       return result;
+}
+
+static int acpi_battery_set_mode(struct acpi_battery *battery)
+{
+       int result = 0;
+       s16 battery_mode;
+
+       if (capacity_mode == DEF_CAPACITY_UNIT) {
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
+                                         ACPI_SB_SMBUS_ADDR, 0x03,
+                                         &battery_mode, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       if (capacity_mode == MAH_CAPACITY_UNIT) {
+               battery_mode &= 0x7fff;
+       } else {
+               battery_mode |= 0x8000;
+       }
+       result = acpi_sbs_smbus_write_word(battery->sbs->smbus,
+                                          ACPI_SB_SMBUS_ADDR, 0x03,
+                                          battery_mode, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_write_word() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
+                                         ACPI_SB_SMBUS_ADDR, 0x03,
+                                         &battery_mode, NULL);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+      end:
+       return result;
+}
+
+static int acpi_battery_init(struct acpi_battery *battery)
+{
+       int result = 0;
+
+       result = acpi_battery_select(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_init() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_set_mode(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_set_mode() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_info(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_info() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_state(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_state() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_alarm(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_alarm() failed\n"));
+               goto end;
+       }
+
+      end:
+       return result;
+}
+
+static int acpi_ac_get_present(struct acpi_sbs *sbs)
+{
+       struct acpi_ec_smbus *smbus = sbs->smbus;
+       int result = 0;
+       s16 charger_status;
+
+       result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13,
+                                         &charger_status, NULL);
+
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_smbus_read_word() failed\n"));
+               goto end;
+       }
+
+       sbs->ac_present = (charger_status & 0x8000) >> 15;
+
+      end:
+
+       return result;
+}
+
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc/acpi)
+   -------------------------------------------------------------------------- */
+
+/* Generic Routines */
+
+static int
+acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
+                       struct proc_dir_entry *parent_dir,
+                       char *dir_name,
+                       struct file_operations *info_fops,
+                       struct file_operations *state_fops,
+                       struct file_operations *alarm_fops, void *data)
+{
+       struct proc_dir_entry *entry = NULL;
+
+       if (!*dir) {
+               *dir = proc_mkdir(dir_name, parent_dir);
+               if (!*dir) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "proc_mkdir() failed\n"));
+                       return -ENODEV;
+               }
+               (*dir)->owner = THIS_MODULE;
+       }
+
+       /* 'info' [R] */
+       if (info_fops) {
+               entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
+               if (!entry) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "create_proc_entry() failed\n"));
+               } else {
+                       entry->proc_fops = info_fops;
+                       entry->data = data;
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       /* 'state' [R] */
+       if (state_fops) {
+               entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
+               if (!entry) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "create_proc_entry() failed\n"));
+               } else {
+                       entry->proc_fops = state_fops;
+                       entry->data = data;
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       /* 'alarm' [R/W] */
+       if (alarm_fops) {
+               entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
+               if (!entry) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "create_proc_entry() failed\n"));
+               } else {
+                       entry->proc_fops = alarm_fops;
+                       entry->data = data;
+                       entry->owner = THIS_MODULE;
+               }
+       }
+
+       return 0;
+}
+
+static void
+acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
+                          struct proc_dir_entry *parent_dir)
+{
+
+       if (*dir) {
+               remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
+               remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
+               remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
+               remove_proc_entry((*dir)->name, parent_dir);
+               *dir = NULL;
+       }
+
+}
+
+/* Smart Battery Interface */
+
+static struct proc_dir_entry *acpi_battery_dir = NULL;
+
+static int acpi_battery_read_info(struct seq_file *seq, void *offset)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       int cscale;
+       int result = 0;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       if (acpi_battery_is_present(battery)) {
+               seq_printf(seq, "present:                 yes\n");
+       } else {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+
+       if (battery->info.capacity_mode) {
+               cscale = battery->info.vscale * battery->info.ipscale;
+       } else {
+               cscale = battery->info.ipscale;
+       }
+       seq_printf(seq, "design capacity:         %i%s",
+                  battery->info.design_capacity * cscale,
+                  battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+
+       seq_printf(seq, "last full capacity:      %i%s",
+                  battery->info.full_charge_capacity * cscale,
+                  battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+
+       seq_printf(seq, "battery technology:      rechargeable\n");
+
+       seq_printf(seq, "design voltage:          %i mV\n",
+                  battery->info.design_voltage * battery->info.vscale);
+
+       seq_printf(seq, "design capacity warning: unknown\n");
+       seq_printf(seq, "design capacity low:     unknown\n");
+       seq_printf(seq, "capacity granularity 1:  unknown\n");
+       seq_printf(seq, "capacity granularity 2:  unknown\n");
+
+       seq_printf(seq, "model number:            %s\n",
+                  battery->info.device_name);
+
+       seq_printf(seq, "serial number:           %i\n",
+                  battery->info.serial_number);
+
+       seq_printf(seq, "battery type:            %s\n",
+                  battery->info.device_chemistry);
+
+       seq_printf(seq, "OEM info:                %s\n",
+                  battery->info.manufacturer_name);
+
+      end:
+
+       up(&sbs_sem);
+
+       return result;
+}
+
+static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_battery_read_info, PDE(inode)->data);
+}
+
+static int acpi_battery_read_state(struct seq_file *seq, void *offset)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       int result = 0;
+       int cscale;
+       int foo;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       if (acpi_battery_is_present(battery)) {
+               seq_printf(seq, "present:                 yes\n");
+       } else {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+
+       if (battery->info.capacity_mode) {
+               cscale = battery->info.vscale * battery->info.ipscale;
+       } else {
+               cscale = battery->info.ipscale;
+       }
+
+       if (battery->state.battery_status & 0x0010) {
+               seq_printf(seq, "capacity state:          critical\n");
+       } else {
+               seq_printf(seq, "capacity state:          ok\n");
+       }
+       if (battery->state.amperage < 0) {
+               seq_printf(seq, "charging state:          discharging\n");
+               foo = battery->state.remaining_capacity * cscale * 60 /
+                   (battery->state.average_time_to_empty == 0 ? 1 :
+                    battery->state.average_time_to_empty);
+               seq_printf(seq, "present rate:            %i%s\n",
+                          foo, battery->info.capacity_mode ? "0 mW" : " mA");
+       } else if (battery->state.amperage > 0) {
+               seq_printf(seq, "charging state:          charging\n");
+               foo = (battery->info.full_charge_capacity -
+                      battery->state.remaining_capacity) * cscale * 60 /
+                   (battery->state.average_time_to_full == 0 ? 1 :
+                    battery->state.average_time_to_full);
+               seq_printf(seq, "present rate:            %i%s\n",
+                          foo, battery->info.capacity_mode ? "0 mW" : " mA");
+       } else {
+               seq_printf(seq, "charging state:          charged\n");
+               seq_printf(seq, "present rate:            0 %s\n",
+                          battery->info.capacity_mode ? "mW" : "mA");
+       }
+
+       seq_printf(seq, "remaining capacity:      %i%s",
+                  battery->state.remaining_capacity * cscale,
+                  battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+
+       seq_printf(seq, "present voltage:         %i mV\n",
+                  battery->state.voltage * battery->info.vscale);
+
+      end:
+
+       up(&sbs_sem);
+
+       return result;
+}
+
+static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_battery_read_state, PDE(inode)->data);
+}
+
+static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       int result = 0;
+       int cscale;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       if (!acpi_battery_is_present(battery)) {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+
+       if (battery->info.capacity_mode) {
+               cscale = battery->info.vscale * battery->info.ipscale;
+       } else {
+               cscale = battery->info.ipscale;
+       }
+
+       seq_printf(seq, "alarm:                   ");
+       if (battery->alarm.remaining_capacity) {
+               seq_printf(seq, "%i%s",
+                          battery->alarm.remaining_capacity * cscale,
+                          battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
+       } else {
+               seq_printf(seq, "disabled\n");
+       }
+
+      end:
+
+       up(&sbs_sem);
+
+       return result;
+}
+
+static ssize_t
+acpi_battery_write_alarm(struct file *file, const char __user * buffer,
+                        size_t count, loff_t * ppos)
+{
+       struct seq_file *seq = (struct seq_file *)file->private_data;
+       struct acpi_battery *battery = (struct acpi_battery *)seq->private;
+       char alarm_string[12] = { '\0' };
+       int result, old_alarm, new_alarm;
+
+       if (battery->sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (!acpi_battery_is_present(battery)) {
+               result = -ENODEV;
+               goto end;
+       }
+
+       if (count > sizeof(alarm_string) - 1) {
+               result = -EINVAL;
+               goto end;
+       }
+
+       if (copy_from_user(alarm_string, buffer, count)) {
+               result = -EFAULT;
+               goto end;
+       }
+
+       alarm_string[count] = 0;
+
+       old_alarm = battery->alarm.remaining_capacity;
+       new_alarm = simple_strtoul(alarm_string, NULL, 0);
+
+       result = acpi_battery_set_alarm(battery, new_alarm);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_set_alarm() failed\n"));
+               (void)acpi_battery_set_alarm(battery, old_alarm);
+               goto end;
+       }
+       result = acpi_battery_get_alarm(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_alarm() failed\n"));
+               (void)acpi_battery_set_alarm(battery, old_alarm);
+               goto end;
+       }
+
+      end:
+       up(&sbs_sem);
+
+       if (result) {
+               return result;
+       } else {
+               return count;
+       }
+}
+
+static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
+}
+
+static struct file_operations acpi_battery_info_fops = {
+       .open = acpi_battery_info_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static struct file_operations acpi_battery_state_fops = {
+       .open = acpi_battery_state_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static struct file_operations acpi_battery_alarm_fops = {
+       .open = acpi_battery_alarm_open_fs,
+       .read = seq_read,
+       .write = acpi_battery_write_alarm,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+/* Legacy AC Adapter Interface */
+
+static struct proc_dir_entry *acpi_ac_dir = NULL;
+
+static int acpi_ac_read_state(struct seq_file *seq, void *offset)
+{
+       struct acpi_sbs *sbs = (struct acpi_sbs *)seq->private;
+       int result;
+
+       if (sbs->zombie) {
+               return -ENODEV;
+       }
+
+       down(&sbs_sem);
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_update_run() failed\n"));
+               }
+       }
+
+       seq_printf(seq, "state:                   %s\n",
+                  sbs->ac_present ? "on-line" : "off-line");
+
+       up(&sbs_sem);
+
+       return 0;
+}
+
+static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_ac_read_state, PDE(inode)->data);
+}
+
+static struct file_operations acpi_ac_state_fops = {
+       .open = acpi_ac_state_open_fs,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+/* --------------------------------------------------------------------------
+                                 Driver Interface
+   -------------------------------------------------------------------------- */
+
+/* Smart Battery */
+
+static int acpi_battery_add(struct acpi_sbs *sbs, int id)
+{
+       int is_present;
+       int result;
+       char dir_name[32];
+       struct acpi_battery *battery;
+
+       battery = &sbs->battery[id];
+
+       battery->alive = 0;
+
+       battery->init_state = 0;
+       battery->id = id;
+       battery->sbs = sbs;
+
+       result = acpi_battery_select(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_select() failed\n"));
+               goto end;
+       }
+
+       result = acpi_battery_get_present(battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_battery_get_present() failed\n"));
+               goto end;
+       }
+
+       is_present = acpi_battery_is_present(battery);
+
+       if (is_present) {
+               result = acpi_battery_init(battery);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_init() failed\n"));
+                       goto end;
+               }
+               battery->init_state = 1;
+       }
+
+       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+
+       result = acpi_sbs_generic_add_fs(&battery->battery_entry,
+                                        acpi_battery_dir,
+                                        dir_name,
+                                        &acpi_battery_info_fops,
+                                        &acpi_battery_state_fops,
+                                        &acpi_battery_alarm_fops, battery);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_generic_add_fs() failed\n"));
+               goto end;
+       }
+       battery->alive = 1;
+
+      end:
+       return result;
+}
+
+static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
+{
+
+       if (sbs->battery[id].battery_entry) {
+               acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry),
+                                          acpi_battery_dir);
+       }
+}
+
+static int acpi_ac_add(struct acpi_sbs *sbs)
+{
+       int result;
+
+       result = acpi_ac_get_present(sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_ac_get_present() failed\n"));
+               goto end;
+       }
+
+       result = acpi_sbs_generic_add_fs(&sbs->ac_entry,
+                                        acpi_ac_dir,
+                                        ACPI_AC_DIR_NAME,
+                                        NULL, &acpi_ac_state_fops, NULL, sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_generic_add_fs() failed\n"));
+               goto end;
+       }
+
+      end:
+
+       return result;
+}
+
+static void acpi_ac_remove(struct acpi_sbs *sbs)
+{
+
+       if (sbs->ac_entry) {
+               acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir);
+       }
+}
+
+static void acpi_sbs_update_queue_run(unsigned long data)
+{
+       acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data);
+}
+
+static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
+{
+       struct acpi_battery *battery;
+       int result = 0;
+       int old_ac_present;
+       int old_battery_present;
+       int new_ac_present;
+       int new_battery_present;
+       int id;
+       char dir_name[32];
+       int do_battery_init, do_ac_init;
+       s16 old_remaining_capacity;
+
+       if (sbs->zombie) {
+               goto end;
+       }
+
+       old_ac_present = acpi_ac_is_present(sbs);
+
+       result = acpi_ac_get_present(sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_ac_get_present() failed\n"));
+       }
+
+       new_ac_present = acpi_ac_is_present(sbs);
+
+       do_ac_init = (old_ac_present != new_ac_present);
+
+       if (data_type == DATA_TYPE_AC_STATE) {
+               goto end;
+       }
+
+       for (id = 0; id < MAX_SBS_BAT; id++) {
+               battery = &sbs->battery[id];
+               if (battery->alive == 0) {
+                       continue;
+               }
+
+               old_remaining_capacity = battery->state.remaining_capacity;
+
+               old_battery_present = acpi_battery_is_present(battery);
+
+               result = acpi_battery_select(battery);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_select() failed\n"));
+               }
+               if (sbs->zombie) {
+                       goto end;
+               }
+
+               result = acpi_battery_get_present(battery);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_get_present() failed\n"));
+               }
+               if (sbs->zombie) {
+                       goto end;
+               }
+
+               new_battery_present = acpi_battery_is_present(battery);
+
+               do_battery_init = ((old_battery_present != new_battery_present)
+                                  && new_battery_present);
+
+               if (sbs->zombie) {
+                       goto end;
+               }
+               if (do_ac_init || do_battery_init ||
+                   update_info_mode || sbs->update_info_mode) {
+                       if (sbs->update_info_mode) {
+                               sbs->update_info_mode = 0;
+                       } else {
+                               sbs->update_info_mode = 1;
+                       }
+                       result = acpi_battery_init(battery);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_battery_init() "
+                                                 "failed\n"));
+                       }
+               }
+               if (data_type == DATA_TYPE_INFO) {
+                       continue;
+               }
+
+               if (sbs->zombie) {
+                       goto end;
+               }
+               if (new_battery_present) {
+                       result = acpi_battery_get_alarm(battery);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_battery_get_alarm() "
+                                                 "failed\n"));
+                       }
+                       if (data_type == DATA_TYPE_ALARM) {
+                               continue;
+                       }
+
+                       result = acpi_battery_get_state(battery);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_battery_get_state() "
+                                                 "failed\n"));
+                       }
+               }
+               if (sbs->zombie) {
+                       goto end;
+               }
+               if (data_type != DATA_TYPE_COMMON) {
+                       continue;
+               }
+
+               if (old_battery_present != new_battery_present) {
+                       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+                       result = acpi_sbs_generate_event(sbs->device,
+                                                        ACPI_SBS_BATTERY_NOTIFY_STATUS,
+                                                        new_battery_present,
+                                                        dir_name,
+                                                        ACPI_BATTERY_CLASS);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_sbs_generate_event() "
+                                                 "failed\n"));
+                       }
+               }
+               if (old_remaining_capacity != battery->state.remaining_capacity) {
+                       (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
+                       result = acpi_sbs_generate_event(sbs->device,
+                                                        ACPI_SBS_BATTERY_NOTIFY_STATUS,
+                                                        new_battery_present,
+                                                        dir_name,
+                                                        ACPI_BATTERY_CLASS);
+                       if (result) {
+                               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                 "acpi_sbs_generate_event() failed\n"));
+                       }
+               }
+
+       }
+       if (sbs->zombie) {
+               goto end;
+       }
+       if (data_type != DATA_TYPE_COMMON) {
+               goto end;
+       }
+
+       if (old_ac_present != new_ac_present) {
+               result = acpi_sbs_generate_event(sbs->device,
+                                                ACPI_SBS_AC_NOTIFY_STATUS,
+                                                new_ac_present,
+                                                ACPI_AC_DIR_NAME,
+                                                ACPI_AC_CLASS);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_generate_event() failed\n"));
+               }
+       }
+
+      end:
+       return result;
+}
+
+static void acpi_sbs_update_queue(void *data)
+{
+       struct acpi_sbs *sbs = data;
+       unsigned long delay = -1;
+       int result;
+
+       if (sbs->zombie) {
+               goto end;
+       }
+
+       result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_sbs_update_run() failed\n"));
+       }
+
+       if (sbs->zombie) {
+               goto end;
+       }
+
+       if (update_mode == REQUEST_UPDATE_MODE) {
+               goto end;
+       }
+
+       delay = jiffies + HZ * update_time;
+       sbs->update_timer.data = (unsigned long)data;
+       sbs->update_timer.function = acpi_sbs_update_queue_run;
+       sbs->update_timer.expires = delay;
+       add_timer(&sbs->update_timer);
+      end:
+       ;
+}
+
+static int acpi_sbs_add(struct acpi_device *device)
+{
+       struct acpi_sbs *sbs = NULL;
+       struct acpi_ec_hc *ec_hc = NULL;
+       int result, remove_result = 0;
+       unsigned long sbs_obj;
+       int id, cnt;
+       acpi_status status = AE_OK;
+
+       sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
+       if (!sbs) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n"));
+               return -ENOMEM;
+       }
+       memset(sbs, 0, sizeof(struct acpi_sbs));
+
+       cnt = 0;
+       while (cnt < 10) {
+               cnt++;
+               ec_hc = acpi_get_ec_hc(device);
+               if (ec_hc) {
+                       break;
+               }
+               msleep(1000);
+       }
+
+       if (!ec_hc) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_get_ec_hc() failed: "
+                                 "NO driver found for EC HC SMBus\n"));
+               result = -ENODEV;
+               goto end;
+       }
+
+       sbs->device = device;
+       sbs->smbus = ec_hc->smbus;
+
+       strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
+       acpi_driver_data(device) = sbs;
+
+       sbs->update_time = 0;
+       sbs->update_time2 = 0;
+
+       result = acpi_ac_add(sbs);
+       if (result) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_ac_add() failed\n"));
+               goto end;
+       }
+       result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
+       if (ACPI_FAILURE(result)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_evaluate_integer() failed\n"));
+               result = -EIO;
+               goto end;
+       }
+
+       if (sbs_obj > 0) {
+               result = acpi_sbsm_get_info(sbs);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbsm_get_info() failed\n"));
+                       goto end;
+               }
+               sbs->sbsm_present = 1;
+       }
+       if (sbs->sbsm_present == 0) {
+               result = acpi_battery_add(sbs, 0);
+               if (result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_battery_add() failed\n"));
+                       goto end;
+               }
+       } else {
+               for (id = 0; id < MAX_SBS_BAT; id++) {
+                       if ((sbs->sbsm_batteries_supported & (1 << id))) {
+                               result = acpi_battery_add(sbs, id);
+                               if (result) {
+                                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                                         "acpi_battery_add() "
+                                                         "failed\n"));
+                                       goto end;
+                               }
+                       }
+               }
+       }
+
+       sbs->handle = device->handle;
+
+       init_timer(&sbs->update_timer);
+       if (update_mode == QUEUE_UPDATE_MODE) {
+               status = acpi_os_execute(OSL_GPE_HANDLER,
+                                        acpi_sbs_update_queue, (void *)sbs);
+               if (status != AE_OK) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_os_execute() failed\n"));
+               }
+       }
+       sbs->update_time = update_time;
+       sbs->update_time2 = update_time2;
+
+       printk(KERN_INFO PREFIX "%s [%s]\n",
+              acpi_device_name(device), acpi_device_bid(device));
+
+      end:
+       if (result) {
+               remove_result = acpi_sbs_remove(device, 0);
+               if (remove_result) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                         "acpi_sbs_remove() failed\n"));
+               }
+       }
+
+       return result;
+}
+
+int acpi_sbs_remove(struct acpi_device *device, int type)
+{
+       struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device);
+       int id;
+
+       if (!device || !sbs) {
+               return -EINVAL;
+       }
+
+       sbs->zombie = 1;
+       sbs->update_time = 0;
+       sbs->update_time2 = 0;
+       del_timer_sync(&sbs->update_timer);
+       acpi_os_wait_events_complete(NULL);
+       del_timer_sync(&sbs->update_timer);
+
+       for (id = 0; id < MAX_SBS_BAT; id++) {
+               acpi_battery_remove(sbs, id);
+       }
+
+       acpi_ac_remove(sbs);
+
+       kfree(sbs);
+
+       return 0;
+}
+
+static int __init acpi_sbs_init(void)
+{
+       int result = 0;
+
+       if (acpi_disabled)
+               return -ENODEV;
+
+       init_MUTEX(&sbs_sem);
+
+       if (capacity_mode != DEF_CAPACITY_UNIT
+           && capacity_mode != MAH_CAPACITY_UNIT
+           && capacity_mode != MWH_CAPACITY_UNIT) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_sbs_init: "
+                                 "invalid capacity_mode = %d\n",
+                                 capacity_mode));
+               return -EINVAL;
+       }
+
+       acpi_ac_dir = acpi_lock_ac_dir();
+       if (!acpi_ac_dir) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_lock_ac_dir() failed\n"));
+               return -ENODEV;
+       }
+
+       acpi_battery_dir = acpi_lock_battery_dir();
+       if (!acpi_battery_dir) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_lock_battery_dir() failed\n"));
+               return -ENODEV;
+       }
+
+       result = acpi_bus_register_driver(&acpi_sbs_driver);
+       if (result < 0) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "acpi_bus_register_driver() failed\n"));
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __exit acpi_sbs_exit(void)
+{
+
+       acpi_bus_unregister_driver(&acpi_sbs_driver);
+
+       acpi_unlock_ac_dir(acpi_ac_dir);
+       acpi_ac_dir = NULL;
+       acpi_unlock_battery_dir(acpi_battery_dir);
+       acpi_battery_dir = NULL;
+
+       return;
+}
+
+module_init(acpi_sbs_init);
+module_exit(acpi_sbs_exit);
diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c
new file mode 100644 (file)
index 0000000..0c85e9d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * hypervisor.c - /sys/hypervisor subsystem.
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/kobject.h>
+#include <linux/device.h>
+
+#include "base.h"
+
+decl_subsys(hypervisor, NULL, NULL);
+EXPORT_SYMBOL_GPL(hypervisor_subsys);
+
+int __init hypervisor_init(void)
+{
+       return subsystem_register(&hypervisor_subsys);
+}
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
new file mode 100644 (file)
index 0000000..d222239
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * ISA bus.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/isa.h>
+
+static struct device isa_bus = {
+       .bus_id         = "isa"
+};
+
+struct isa_dev {
+       struct device dev;
+       struct device *next;
+       unsigned int id;
+};
+
+#define to_isa_dev(x) container_of((x), struct isa_dev, dev)
+
+static int isa_bus_match(struct device *dev, struct device_driver *driver)
+{
+       struct isa_driver *isa_driver = to_isa_driver(driver);
+
+       if (dev->platform_data == isa_driver) {
+               if (!isa_driver->match ||
+                       isa_driver->match(dev, to_isa_dev(dev)->id))
+                       return 1;
+               dev->platform_data = NULL;
+       }
+       return 0;
+}
+
+static int isa_bus_probe(struct device *dev)
+{
+       struct isa_driver *isa_driver = dev->platform_data;
+
+       if (isa_driver->probe)
+               return isa_driver->probe(dev, to_isa_dev(dev)->id);
+
+       return 0;
+}
+
+static int isa_bus_remove(struct device *dev)
+{
+       struct isa_driver *isa_driver = dev->platform_data;
+
+       if (isa_driver->remove)
+               return isa_driver->remove(dev, to_isa_dev(dev)->id);
+
+       return 0;
+}
+
+static void isa_bus_shutdown(struct device *dev)
+{
+       struct isa_driver *isa_driver = dev->platform_data;
+
+       if (isa_driver->shutdown)
+               isa_driver->shutdown(dev, to_isa_dev(dev)->id);
+}
+
+static int isa_bus_suspend(struct device *dev, pm_message_t state)
+{
+       struct isa_driver *isa_driver = dev->platform_data;
+
+       if (isa_driver->suspend)
+               return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
+
+       return 0;
+}
+
+static int isa_bus_resume(struct device *dev)
+{
+       struct isa_driver *isa_driver = dev->platform_data;
+
+       if (isa_driver->resume)
+               return isa_driver->resume(dev, to_isa_dev(dev)->id);
+
+       return 0;
+}
+
+static struct bus_type isa_bus_type = {
+       .name           = "isa",
+       .match          = isa_bus_match,
+       .probe          = isa_bus_probe,
+       .remove         = isa_bus_remove,
+       .shutdown       = isa_bus_shutdown,
+       .suspend        = isa_bus_suspend,
+       .resume         = isa_bus_resume
+};
+
+static void isa_dev_release(struct device *dev)
+{
+       kfree(to_isa_dev(dev));
+}
+
+void isa_unregister_driver(struct isa_driver *isa_driver)
+{
+       struct device *dev = isa_driver->devices;
+
+       while (dev) {
+               struct device *tmp = to_isa_dev(dev)->next;
+               device_unregister(dev);
+               dev = tmp;
+       }
+       driver_unregister(&isa_driver->driver);
+}
+EXPORT_SYMBOL_GPL(isa_unregister_driver);
+
+int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
+{
+       int error;
+       unsigned int id;
+
+       isa_driver->driver.bus  = &isa_bus_type;
+       isa_driver->devices     = NULL;
+
+       error = driver_register(&isa_driver->driver);
+       if (error)
+               return error;
+
+       for (id = 0; id < ndev; id++) {
+               struct isa_dev *isa_dev;
+
+               isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL);
+               if (!isa_dev) {
+                       error = -ENOMEM;
+                       break;
+               }
+
+               isa_dev->dev.parent     = &isa_bus;
+               isa_dev->dev.bus        = &isa_bus_type;
+
+               snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u",
+                               isa_driver->driver.name, id);
+
+               isa_dev->dev.platform_data      = isa_driver;
+               isa_dev->dev.release            = isa_dev_release;
+               isa_dev->id                     = id;
+
+               error = device_register(&isa_dev->dev);
+               if (error) {
+                       put_device(&isa_dev->dev);
+                       break;
+               }
+
+               if (isa_dev->dev.platform_data) {
+                       isa_dev->next = isa_driver->devices;
+                       isa_driver->devices = &isa_dev->dev;
+               } else
+                       device_unregister(&isa_dev->dev);
+       }
+
+       if (!error && !isa_driver->devices)
+               error = -ENODEV;
+
+       if (error)
+               isa_unregister_driver(isa_driver);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(isa_register_driver);
+
+static int __init isa_bus_init(void)
+{
+       int error;
+
+       error = bus_register(&isa_bus_type);
+       if (!error) {
+               error = device_register(&isa_bus);
+               if (error)
+                       bus_unregister(&isa_bus_type);
+       }
+       return error;
+}
+
+device_initcall(isa_bus_init);
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
new file mode 100644 (file)
index 0000000..a9ab30f
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * drivers/base/power/trace.c
+ *
+ * Copyright (C) 2006 Linus Torvalds
+ *
+ * Trace facility for suspend/resume problems, when none of the
+ * devices may be working.
+ */
+
+#include <linux/resume-trace.h>
+#include <linux/rtc.h>
+
+#include <asm/rtc.h>
+
+#include "power.h"
+
+/*
+ * Horrid, horrid, horrid.
+ *
+ * It turns out that the _only_ piece of hardware that actually
+ * keeps its value across a hard boot (and, more importantly, the
+ * POST init sequence) is literally the realtime clock.
+ *
+ * Never mind that an RTC chip has 114 bytes (and often a whole
+ * other bank of an additional 128 bytes) of nice SRAM that is
+ * _designed_ to keep data - the POST will clear it. So we literally
+ * can just use the few bytes of actual time data, which means that
+ * we're really limited.
+ *
+ * It means, for example, that we can't use the seconds at all
+ * (since the time between the hang and the boot might be more
+ * than a minute), and we'd better not depend on the low bits of
+ * the minutes either.
+ *
+ * There are the wday fields etc, but I wouldn't guarantee those
+ * are dependable either. And if the date isn't valid, either the
+ * hw or POST will do strange things.
+ *
+ * So we're left with:
+ *  - year: 0-99
+ *  - month: 0-11
+ *  - day-of-month: 1-28
+ *  - hour: 0-23
+ *  - min: (0-30)*2
+ *
+ * Giving us a total range of 0-16128000 (0xf61800), ie less
+ * than 24 bits of actual data we can save across reboots.
+ *
+ * And if your box can't boot in less than three minutes,
+ * you're screwed.
+ *
+ * Now, almost 24 bits of data is pitifully small, so we need
+ * to be pretty dense if we want to use it for anything nice.
+ * What we do is that instead of saving off nice readable info,
+ * we save off _hashes_ of information that we can hopefully
+ * regenerate after the reboot.
+ *
+ * In particular, this means that we might be unlucky, and hit
+ * a case where we have a hash collision, and we end up not
+ * being able to tell for certain exactly which case happened.
+ * But that's hopefully unlikely.
+ *
+ * What we do is to take the bits we can fit, and split them
+ * into three parts (16*997*1009 = 16095568), and use the values
+ * for:
+ *  - 0-15: user-settable
+ *  - 0-996: file + line number
+ *  - 0-1008: device
+ */
+#define USERHASH (16)
+#define FILEHASH (997)
+#define DEVHASH (1009)
+
+#define DEVSEED (7919)
+
+static unsigned int dev_hash_value;
+
+static int set_magic_time(unsigned int user, unsigned int file, unsigned int device)
+{
+       unsigned int n = user + USERHASH*(file + FILEHASH*device);
+
+       // June 7th, 2006
+       static struct rtc_time time = {
+               .tm_sec = 0,
+               .tm_min = 0,
+               .tm_hour = 0,
+               .tm_mday = 7,
+               .tm_mon = 5,    // June - counting from zero
+               .tm_year = 106,
+               .tm_wday = 3,
+               .tm_yday = 160,
+               .tm_isdst = 1
+       };
+
+       time.tm_year = (n % 100);
+       n /= 100;
+       time.tm_mon = (n % 12);
+       n /= 12;
+       time.tm_mday = (n % 28) + 1;
+       n /= 28;
+       time.tm_hour = (n % 24);
+       n /= 24;
+       time.tm_min = (n % 20) * 3;
+       n /= 20;
+       set_rtc_time(&time);
+       return n ? -1 : 0;
+}
+
+static unsigned int read_magic_time(void)
+{
+       struct rtc_time time;
+       unsigned int val;
+
+       get_rtc_time(&time);
+       printk("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
+               time.tm_hour, time.tm_min, time.tm_sec,
+               time.tm_mon, time.tm_mday, time.tm_year);
+       val = time.tm_year;                             /* 100 years */
+       if (val > 100)
+               val -= 100;
+       val += time.tm_mon * 100;                       /* 12 months */
+       val += (time.tm_mday-1) * 100 * 12;             /* 28 month-days */
+       val += time.tm_hour * 100 * 12 * 28;            /* 24 hours */
+       val += (time.tm_min / 3) * 100 * 12 * 28 * 24;  /* 20 3-minute intervals */
+       return val;
+}
+
+/*
+ * This is just the sdbm hash function with a user-supplied
+ * seed and final size parameter.
+ */
+static unsigned int hash_string(unsigned int seed, const char *data, unsigned int mod)
+{
+       unsigned char c;
+       while ((c = *data++) != 0) {
+               seed = (seed << 16) + (seed << 6) - seed + c;
+       }
+       return seed % mod;
+}
+
+void set_trace_device(struct device *dev)
+{
+       dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH);
+}
+
+/*
+ * We could just take the "tracedata" index into the .tracedata
+ * section instead. Generating a hash of the data gives us a
+ * chance to work across kernel versions, and perhaps more
+ * importantly it also gives us valid/invalid check (ie we will
+ * likely not give totally bogus reports - if the hash matches,
+ * it's not any guarantee, but it's a high _likelihood_ that
+ * the match is valid).
+ */
+void generate_resume_trace(void *tracedata, unsigned int user)
+{
+       unsigned short lineno = *(unsigned short *)tracedata;
+       const char *file = *(const char **)(tracedata + 2);
+       unsigned int user_hash_value, file_hash_value;
+
+       user_hash_value = user % USERHASH;
+       file_hash_value = hash_string(lineno, file, FILEHASH);
+       set_magic_time(user_hash_value, file_hash_value, dev_hash_value);
+}
+
+extern char __tracedata_start, __tracedata_end;
+static int show_file_hash(unsigned int value)
+{
+       int match;
+       char *tracedata;
+
+       match = 0;
+       for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) {
+               unsigned short lineno = *(unsigned short *)tracedata;
+               const char *file = *(const char **)(tracedata + 2);
+               unsigned int hash = hash_string(lineno, file, FILEHASH);
+               if (hash != value)
+                       continue;
+               printk("  hash matches %s:%u\n", file, lineno);
+               match++;
+       }
+       return match;
+}
+
+static int show_dev_hash(unsigned int value)
+{
+       int match = 0;
+       struct list_head * entry = dpm_active.prev;
+
+       while (entry != &dpm_active) {
+               struct device * dev = to_device(entry);
+               unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
+               if (hash == value) {
+                       printk("  hash matches device %s\n", dev->bus_id);
+                       match++;
+               }
+               entry = entry->prev;
+       }
+       return match;
+}
+
+static unsigned int hash_value_early_read;
+
+static int early_resume_init(void)
+{
+       hash_value_early_read = read_magic_time();
+       return 0;
+}
+
+static int late_resume_init(void)
+{
+       unsigned int val = hash_value_early_read;
+       unsigned int user, file, dev;
+
+       user = val % USERHASH;
+       val = val / USERHASH;
+       file = val % FILEHASH;
+       val = val / FILEHASH;
+       dev = val /* % DEVHASH */;
+
+       printk("  Magic number: %d:%d:%d\n", user, file, dev);
+       show_file_hash(file);
+       show_dev_hash(dev);
+       return 0;
+}
+
+core_initcall(early_resume_init);
+late_initcall(late_resume_init);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
new file mode 100644 (file)
index 0000000..9f7635f
--- /dev/null
@@ -0,0 +1,90 @@
+#
+# Hardware Random Number Generator (RNG) configuration
+#
+
+config HW_RANDOM
+       bool "Hardware Random Number Generator Core support"
+       default y
+       ---help---
+         Hardware Random Number Generator Core infrastructure.
+
+         If unsure, say Y.
+
+config HW_RANDOM_INTEL
+       tristate "Intel HW Random Number Generator support"
+       depends on HW_RANDOM && (X86 || IA64) && PCI
+       default y
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on Intel i8xx-based motherboards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called intel-rng.
+
+         If unsure, say Y.
+
+config HW_RANDOM_AMD
+       tristate "AMD HW Random Number Generator support"
+       depends on HW_RANDOM && X86 && PCI
+       default y
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on AMD 76x-based motherboards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called amd-rng.
+
+         If unsure, say Y.
+
+config HW_RANDOM_GEODE
+       tristate "AMD Geode HW Random Number Generator support"
+       depends on HW_RANDOM && X86 && PCI
+       default y
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on the AMD Geode LX.
+
+         To compile this driver as a module, choose M here: the
+         module will be called geode-rng.
+
+         If unsure, say Y.
+
+config HW_RANDOM_VIA
+       tristate "VIA HW Random Number Generator support"
+       depends on HW_RANDOM && X86_32
+       default y
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on VIA based motherboards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called via-rng.
+
+         If unsure, say Y.
+
+config HW_RANDOM_IXP4XX
+       tristate "Intel IXP4xx NPU HW Random Number Generator support"
+       depends on HW_RANDOM && ARCH_IXP4XX
+       default y
+       ---help---
+         This driver provides kernel-side support for the Random
+         Number Generator hardware found on the Intel IXP4xx NPU.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ixp4xx-rng.
+
+         If unsure, say Y.
+
+config HW_RANDOM_OMAP
+       tristate "OMAP Random Number Generator support"
+       depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+       default y
+       ---help---
+         This driver provides kernel-side support for the Random Number
+         Generator hardware found on OMAP16xx and OMAP24xx multimedia
+         processors.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap-rng.
+
+         If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
new file mode 100644 (file)
index 0000000..e263ae9
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for HW Random Number Generator (RNG) device drivers.
+#
+
+obj-$(CONFIG_HW_RANDOM) += core.o
+obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
+obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
+obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
+obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
+obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
new file mode 100644 (file)
index 0000000..71e4e0f
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * RNG driver for AMD RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+
+
+#define PFX    KBUILD_MODNAME ": "
+
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static const struct pci_device_id pci_tbl[] = {
+       { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+       { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+       { 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+static struct pci_dev *amd_pdev;
+
+
+static int amd_rng_data_present(struct hwrng *rng)
+{
+       u32 pmbase = (u32)rng->priv;
+
+       return !!(inl(pmbase + 0xF4) & 1);
+}
+
+static int amd_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       u32 pmbase = (u32)rng->priv;
+
+       *data = inl(pmbase + 0xF0);
+
+       return 4;
+}
+
+static int amd_rng_init(struct hwrng *rng)
+{
+       u8 rnen;
+
+       pci_read_config_byte(amd_pdev, 0x40, &rnen);
+       rnen |= (1 << 7);       /* RNG on */
+       pci_write_config_byte(amd_pdev, 0x40, rnen);
+
+       pci_read_config_byte(amd_pdev, 0x41, &rnen);
+       rnen |= (1 << 7);       /* PMIO enable */
+       pci_write_config_byte(amd_pdev, 0x41, rnen);
+
+       return 0;
+}
+
+static void amd_rng_cleanup(struct hwrng *rng)
+{
+       u8 rnen;
+
+       pci_read_config_byte(amd_pdev, 0x40, &rnen);
+       rnen &= ~(1 << 7);      /* RNG off */
+       pci_write_config_byte(amd_pdev, 0x40, rnen);
+}
+
+
+static struct hwrng amd_rng = {
+       .name           = "amd",
+       .init           = amd_rng_init,
+       .cleanup        = amd_rng_cleanup,
+       .data_present   = amd_rng_data_present,
+       .data_read      = amd_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+       int err = -ENODEV;
+       struct pci_dev *pdev = NULL;
+       const struct pci_device_id *ent;
+       u32 pmbase;
+
+       for_each_pci_dev(pdev) {
+               ent = pci_match_id(pci_tbl, pdev);
+               if (ent)
+                       goto found;
+       }
+       /* Device not found. */
+       goto out;
+
+found:
+       err = pci_read_config_dword(pdev, 0x58, &pmbase);
+       if (err)
+               goto out;
+       err = -EIO;
+       pmbase &= 0x0000FF00;
+       if (pmbase == 0)
+               goto out;
+       amd_rng.priv = (unsigned long)pmbase;
+       amd_pdev = pdev;
+
+       printk(KERN_INFO "AMD768 RNG detected\n");
+       err = hwrng_register(&amd_rng);
+       if (err) {
+               printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+                      err);
+               goto out;
+       }
+out:
+       return err;
+}
+
+static void __exit mod_exit(void)
+{
+       hwrng_unregister(&amd_rng);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("The Linux Kernel team");
+MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
new file mode 100644 (file)
index 0000000..154a81d
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+        Added support for the AMD Geode LX RNG
+       (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
+
+       derived from
+
+       Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+       (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+
+       derived from
+
+        Hardware driver for the AMD 768 Random Number Generator (RNG)
+        (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+
+       derived from
+
+       Hardware driver for Intel i810 Random Number Generator (RNG)
+       Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+       Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+
+       Added generic RNG API
+       Copyright 2006 Michael Buesch <mbuesch@freenet.de>
+       Copyright 2005 (c) MontaVista Software, Inc.
+
+       Please read Documentation/hw_random.txt for details on use.
+
+       ----------------------------------------------------------
+       This software may be used and distributed according to the terms
+        of the GNU General Public License, incorporated herein by reference.
+
+ */
+
+
+#include <linux/device.h>
+#include <linux/hw_random.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+
+#define RNG_MODULE_NAME                "hw_random"
+#define PFX                    RNG_MODULE_NAME ": "
+#define RNG_MISCDEV_MINOR      183 /* official */
+
+
+static struct hwrng *current_rng;
+static LIST_HEAD(rng_list);
+static DEFINE_MUTEX(rng_mutex);
+
+
+static inline int hwrng_init(struct hwrng *rng)
+{
+       if (!rng->init)
+               return 0;
+       return rng->init(rng);
+}
+
+static inline void hwrng_cleanup(struct hwrng *rng)
+{
+       if (rng && rng->cleanup)
+               rng->cleanup(rng);
+}
+
+static inline int hwrng_data_present(struct hwrng *rng)
+{
+       if (!rng->data_present)
+               return 1;
+       return rng->data_present(rng);
+}
+
+static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
+{
+       return rng->data_read(rng, data);
+}
+
+
+static int rng_dev_open(struct inode *inode, struct file *filp)
+{
+       /* enforce read-only access to this chrdev */
+       if ((filp->f_mode & FMODE_READ) == 0)
+               return -EINVAL;
+       if (filp->f_mode & FMODE_WRITE)
+               return -EINVAL;
+       return 0;
+}
+
+static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+                           size_t size, loff_t *offp)
+{
+       u32 data;
+       ssize_t ret = 0;
+       int i, err = 0;
+       int data_present;
+       int bytes_read;
+
+       while (size) {
+               err = -ERESTARTSYS;
+               if (mutex_lock_interruptible(&rng_mutex))
+                       goto out;
+               if (!current_rng) {
+                       mutex_unlock(&rng_mutex);
+                       err = -ENODEV;
+                       goto out;
+               }
+               if (filp->f_flags & O_NONBLOCK) {
+                       data_present = hwrng_data_present(current_rng);
+               } else {
+                       /* Some RNG require some time between data_reads to gather
+                        * new entropy. Poll it.
+                        */
+                       for (i = 0; i < 20; i++) {
+                               data_present = hwrng_data_present(current_rng);
+                               if (data_present)
+                                       break;
+                               udelay(10);
+                       }
+               }
+               bytes_read = 0;
+               if (data_present)
+                       bytes_read = hwrng_data_read(current_rng, &data);
+               mutex_unlock(&rng_mutex);
+
+               err = -EAGAIN;
+               if (!bytes_read && (filp->f_flags & O_NONBLOCK))
+                       goto out;
+
+               err = -EFAULT;
+               while (bytes_read && size) {
+                       if (put_user((u8)data, buf++))
+                               goto out;
+                       size--;
+                       ret++;
+                       bytes_read--;
+                       data >>= 8;
+               }
+
+               if (need_resched())
+                       schedule_timeout_interruptible(1);
+               err = -ERESTARTSYS;
+               if (signal_pending(current))
+                       goto out;
+       }
+out:
+       return ret ? : err;
+}
+
+
+static const struct file_operations rng_chrdev_ops = {
+       .owner          = THIS_MODULE,
+       .open           = rng_dev_open,
+       .read           = rng_dev_read,
+};
+
+static struct miscdevice rng_miscdev = {
+       .minor          = RNG_MISCDEV_MINOR,
+       .name           = RNG_MODULE_NAME,
+       .fops           = &rng_chrdev_ops,
+};
+
+
+static ssize_t hwrng_attr_current_store(struct class_device *class,
+                                       const char *buf, size_t len)
+{
+       int err;
+       struct hwrng *rng;
+
+       err = mutex_lock_interruptible(&rng_mutex);
+       if (err)
+               return -ERESTARTSYS;
+       err = -ENODEV;
+       list_for_each_entry(rng, &rng_list, list) {
+               if (strcmp(rng->name, buf) == 0) {
+                       if (rng == current_rng) {
+                               err = 0;
+                               break;
+                       }
+                       err = hwrng_init(rng);
+                       if (err)
+                               break;
+                       hwrng_cleanup(current_rng);
+                       current_rng = rng;
+                       err = 0;
+                       break;
+               }
+       }
+       mutex_unlock(&rng_mutex);
+
+       return err ? : len;
+}
+
+static ssize_t hwrng_attr_current_show(struct class_device *class,
+                                      char *buf)
+{
+       int err;
+       ssize_t ret;
+       const char *name = "none";
+
+       err = mutex_lock_interruptible(&rng_mutex);
+       if (err)
+               return -ERESTARTSYS;
+       if (current_rng)
+               name = current_rng->name;
+       ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
+       mutex_unlock(&rng_mutex);
+
+       return ret;
+}
+
+static ssize_t hwrng_attr_available_show(struct class_device *class,
+                                        char *buf)
+{
+       int err;
+       ssize_t ret = 0;
+       struct hwrng *rng;
+
+       err = mutex_lock_interruptible(&rng_mutex);
+       if (err)
+               return -ERESTARTSYS;
+       buf[0] = '\0';
+       list_for_each_entry(rng, &rng_list, list) {
+               strncat(buf, rng->name, PAGE_SIZE - ret - 1);
+               ret += strlen(rng->name);
+               strncat(buf, " ", PAGE_SIZE - ret - 1);
+               ret++;
+       }
+       strncat(buf, "\n", PAGE_SIZE - ret - 1);
+       ret++;
+       mutex_unlock(&rng_mutex);
+
+       return ret;
+}
+
+static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
+                        hwrng_attr_current_show,
+                        hwrng_attr_current_store);
+static CLASS_DEVICE_ATTR(rng_available, S_IRUGO,
+                        hwrng_attr_available_show,
+                        NULL);
+
+
+static void unregister_miscdev(void)
+{
+       class_device_remove_file(rng_miscdev.class,
+                                &class_device_attr_rng_available);
+       class_device_remove_file(rng_miscdev.class,
+                                &class_device_attr_rng_current);
+       misc_deregister(&rng_miscdev);
+}
+
+static int register_miscdev(void)
+{
+       int err;
+
+       err = misc_register(&rng_miscdev);
+       if (err)
+               goto out;
+       err = class_device_create_file(rng_miscdev.class,
+                                      &class_device_attr_rng_current);
+       if (err)
+               goto err_misc_dereg;
+       err = class_device_create_file(rng_miscdev.class,
+                                      &class_device_attr_rng_available);
+       if (err)
+               goto err_remove_current;
+out:
+       return err;
+
+err_remove_current:
+       class_device_remove_file(rng_miscdev.class,
+                                &class_device_attr_rng_current);
+err_misc_dereg:
+       misc_deregister(&rng_miscdev);
+       goto out;
+}
+
+int hwrng_register(struct hwrng *rng)
+{
+       int must_register_misc;
+       int err = -EINVAL;
+       struct hwrng *old_rng, *tmp;
+
+       if (rng->name == NULL ||
+           rng->data_read == NULL)
+               goto out;
+
+       mutex_lock(&rng_mutex);
+
+       /* Must not register two RNGs with the same name. */
+       err = -EEXIST;
+       list_for_each_entry(tmp, &rng_list, list) {
+               if (strcmp(tmp->name, rng->name) == 0)
+                       goto out_unlock;
+       }
+
+       must_register_misc = (current_rng == NULL);
+       old_rng = current_rng;
+       if (!old_rng) {
+               err = hwrng_init(rng);
+               if (err)
+                       goto out_unlock;
+               current_rng = rng;
+       }
+       err = 0;
+       if (must_register_misc) {
+               err = register_miscdev();
+               if (err) {
+                       if (!old_rng) {
+                               hwrng_cleanup(rng);
+                               current_rng = NULL;
+                       }
+                       goto out_unlock;
+               }
+       }
+       INIT_LIST_HEAD(&rng->list);
+       list_add_tail(&rng->list, &rng_list);
+out_unlock:
+       mutex_unlock(&rng_mutex);
+out:
+       return err;
+}
+EXPORT_SYMBOL_GPL(hwrng_register);
+
+void hwrng_unregister(struct hwrng *rng)
+{
+       int err;
+
+       mutex_lock(&rng_mutex);
+
+       list_del(&rng->list);
+       if (current_rng == rng) {
+               hwrng_cleanup(rng);
+               if (list_empty(&rng_list)) {
+                       current_rng = NULL;
+               } else {
+                       current_rng = list_entry(rng_list.prev, struct hwrng, list);
+                       err = hwrng_init(current_rng);
+                       if (err)
+                               current_rng = NULL;
+               }
+       }
+       if (list_empty(&rng_list))
+               unregister_miscdev();
+
+       mutex_unlock(&rng_mutex);
+}
+EXPORT_SYMBOL_GPL(hwrng_unregister);
+
+
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
new file mode 100644 (file)
index 0000000..d37ced0
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * RNG driver for AMD Geode RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+
+
+#define PFX    KBUILD_MODNAME ": "
+
+#define GEODE_RNG_DATA_REG   0x50
+#define GEODE_RNG_STATUS_REG 0x54
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static const struct pci_device_id pci_tbl[] = {
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+       { 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+
+static int geode_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       void __iomem *mem = (void __iomem *)rng->priv;
+
+       *data = readl(mem + GEODE_RNG_DATA_REG);
+
+       return 4;
+}
+
+static int geode_rng_data_present(struct hwrng *rng)
+{
+       void __iomem *mem = (void __iomem *)rng->priv;
+
+       return !!(readl(mem + GEODE_RNG_STATUS_REG));
+}
+
+
+static struct hwrng geode_rng = {
+       .name           = "geode",
+       .data_present   = geode_rng_data_present,
+       .data_read      = geode_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+       int err = -ENODEV;
+       struct pci_dev *pdev = NULL;
+       const struct pci_device_id *ent;
+       void __iomem *mem;
+       unsigned long rng_base;
+
+       for_each_pci_dev(pdev) {
+               ent = pci_match_id(pci_tbl, pdev);
+               if (ent)
+                       goto found;
+       }
+       /* Device not found. */
+       goto out;
+
+found:
+       rng_base = pci_resource_start(pdev, 0);
+       if (rng_base == 0)
+               goto out;
+       err = -ENOMEM;
+       mem = ioremap(rng_base, 0x58);
+       if (!mem)
+               goto out;
+       geode_rng.priv = (unsigned long)mem;
+
+       printk(KERN_INFO "AMD Geode RNG detected\n");
+       err = hwrng_register(&geode_rng);
+       if (err) {
+               printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+                      err);
+               goto err_unmap;
+       }
+out:
+       return err;
+
+err_unmap:
+       iounmap(mem);
+       goto out;
+}
+
+static void __exit mod_exit(void)
+{
+       void __iomem *mem = (void __iomem *)geode_rng.priv;
+
+       hwrng_unregister(&geode_rng);
+       iounmap(mem);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
new file mode 100644 (file)
index 0000000..8efbc9c
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * RNG driver for Intel RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+
+
+#define PFX    KBUILD_MODNAME ": "
+
+/*
+ * RNG registers
+ */
+#define INTEL_RNG_HW_STATUS                    0
+#define         INTEL_RNG_PRESENT              0x40
+#define         INTEL_RNG_ENABLED              0x01
+#define INTEL_RNG_STATUS                       1
+#define         INTEL_RNG_DATA_PRESENT         0x01
+#define INTEL_RNG_DATA                         2
+
+/*
+ * Magic address at which Intel PCI bridges locate the RNG
+ */
+#define INTEL_RNG_ADDR                         0xFFBC015F
+#define INTEL_RNG_ADDR_LEN                     3
+
+/*
+ * LPC bridge PCI config space registers
+ */
+#define FWH_DEC_EN1_REG_OLD                    0xe3
+#define FWH_DEC_EN1_REG_NEW                    0xd9 /* high byte of 16-bit register */
+#define FWH_F8_EN_MASK                         0x80
+
+#define BIOS_CNTL_REG_OLD                      0x4e
+#define BIOS_CNTL_REG_NEW                      0xdc
+#define BIOS_CNTL_WRITE_ENABLE_MASK            0x01
+#define BIOS_CNTL_LOCK_ENABLE_MASK             0x02
+
+/*
+ * Magic address at which Intel Firmware Hubs get accessed
+ */
+#define INTEL_FWH_ADDR                         0xffff0000
+#define INTEL_FWH_ADDR_LEN                     2
+
+/*
+ * Intel Firmware Hub command codes (write to any address inside the device)
+ */
+#define INTEL_FWH_RESET_CMD                    0xff /* aka READ_ARRAY */
+#define INTEL_FWH_READ_ID_CMD                  0x90
+
+/*
+ * Intel Firmware Hub Read ID command result addresses
+ */
+#define INTEL_FWH_MANUFACTURER_CODE_ADDRESS    0x000000
+#define INTEL_FWH_DEVICE_CODE_ADDRESS          0x000001
+
+/*
+ * Intel Firmware Hub Read ID command result values
+ */
+#define INTEL_FWH_MANUFACTURER_CODE            0x89
+#define INTEL_FWH_DEVICE_CODE_8M               0xac
+#define INTEL_FWH_DEVICE_CODE_4M               0xad
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static const struct pci_device_id pci_tbl[] = {
+/* AA
+       { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
+/* AB
+       { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
+/* ??
+       { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+/* BAM, CAM, DBM, FBM, GxM
+       { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
+       { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
+       { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
+       { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
+       { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
+       { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
+/* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
+       { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
+       { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
+       { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
+       { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
+       { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
+       { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
+       { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
+       { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
+/* E
+       { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+       { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E  */
+       { 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+
+static inline u8 hwstatus_get(void __iomem *mem)
+{
+       return readb(mem + INTEL_RNG_HW_STATUS);
+}
+
+static inline u8 hwstatus_set(void __iomem *mem,
+                             u8 hw_status)
+{
+       writeb(hw_status, mem + INTEL_RNG_HW_STATUS);
+       return hwstatus_get(mem);
+}
+
+static int intel_rng_data_present(struct hwrng *rng)
+{
+       void __iomem *mem = (void __iomem *)rng->priv;
+
+       return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
+}
+
+static int intel_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       void __iomem *mem = (void __iomem *)rng->priv;
+
+       *data = readb(mem + INTEL_RNG_DATA);
+
+       return 1;
+}
+
+static int intel_rng_init(struct hwrng *rng)
+{
+       void __iomem *mem = (void __iomem *)rng->priv;
+       u8 hw_status;
+       int err = -EIO;
+
+       hw_status = hwstatus_get(mem);
+       /* turn RNG h/w on, if it's off */
+       if ((hw_status & INTEL_RNG_ENABLED) == 0)
+               hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED);
+       if ((hw_status & INTEL_RNG_ENABLED) == 0) {
+               printk(KERN_ERR PFX "cannot enable RNG, aborting\n");
+               goto out;
+       }
+       err = 0;
+out:
+       return err;
+}
+
+static void intel_rng_cleanup(struct hwrng *rng)
+{
+       void __iomem *mem = (void __iomem *)rng->priv;
+       u8 hw_status;
+
+       hw_status = hwstatus_get(mem);
+       if (hw_status & INTEL_RNG_ENABLED)
+               hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED);
+       else
+               printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
+}
+
+
+static struct hwrng intel_rng = {
+       .name           = "intel",
+       .init           = intel_rng_init,
+       .cleanup        = intel_rng_cleanup,
+       .data_present   = intel_rng_data_present,
+       .data_read      = intel_rng_data_read,
+};
+
+
+#ifdef CONFIG_SMP
+static char __initdata waitflag;
+
+static void __init intel_init_wait(void *unused)
+{
+       while (waitflag)
+               cpu_relax();
+}
+#endif
+
+static int __init mod_init(void)
+{
+       int err = -ENODEV;
+       unsigned i;
+       struct pci_dev *dev = NULL;
+       void __iomem *mem;
+       unsigned long flags;
+       u8 bios_cntl_off, fwh_dec_en1_off;
+       u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff;
+       u8 hw_status, mfc, dvc;
+
+       for (i = 0; !dev && pci_tbl[i].vendor; ++i)
+               dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL);
+
+       if (!dev)
+               goto out; /* Device not found. */
+
+       /* Check for Intel 82802 */
+       if (dev->device < 0x2640) {
+               fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD;
+               bios_cntl_off = BIOS_CNTL_REG_OLD;
+       } else {
+               fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW;
+               bios_cntl_off = BIOS_CNTL_REG_NEW;
+       }
+
+       pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val);
+       pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val);
+
+       mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN);
+       if (mem == NULL) {
+               pci_dev_put(dev);
+               err = -EBUSY;
+               goto out;
+       }
+
+       /*
+        * Since the BIOS code/data is going to disappear from its normal
+        * location with the Read ID command, all activity on the system
+        * must be stopped until the state is back to normal.
+        */
+#ifdef CONFIG_SMP
+       set_mb(waitflag, 1);
+       if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) {
+               set_mb(waitflag, 0);
+               pci_dev_put(dev);
+               printk(KERN_ERR PFX "cannot run on all processors\n");
+               err = -EAGAIN;
+               goto err_unmap;
+       }
+#endif
+       local_irq_save(flags);
+
+       if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
+               pci_write_config_byte(dev,
+                                     fwh_dec_en1_off,
+                                     fwh_dec_en1_val | FWH_F8_EN_MASK);
+       if (!(bios_cntl_val &
+             (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+               pci_write_config_byte(dev,
+                                     bios_cntl_off,
+                                     bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK);
+
+       writeb(INTEL_FWH_RESET_CMD, mem);
+       writeb(INTEL_FWH_READ_ID_CMD, mem);
+       mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS);
+       dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS);
+       writeb(INTEL_FWH_RESET_CMD, mem);
+
+       if (!(bios_cntl_val &
+             (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)))
+               pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val);
+       if (!(fwh_dec_en1_val & FWH_F8_EN_MASK))
+               pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val);
+
+       local_irq_restore(flags);
+#ifdef CONFIG_SMP
+       /* Tell other CPUs to resume. */
+       set_mb(waitflag, 0);
+#endif
+
+       iounmap(mem);
+       pci_dev_put(dev);
+
+       if (mfc != INTEL_FWH_MANUFACTURER_CODE ||
+           (dvc != INTEL_FWH_DEVICE_CODE_8M &&
+            dvc != INTEL_FWH_DEVICE_CODE_4M)) {
+               printk(KERN_ERR PFX "FWH not detected\n");
+               err = -ENODEV;
+               goto out;
+       }
+
+       err = -ENOMEM;
+       mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
+       if (!mem)
+               goto out;
+       intel_rng.priv = (unsigned long)mem;
+
+       /* Check for Random Number Generator */
+       err = -ENODEV;
+       hw_status = hwstatus_get(mem);
+       if ((hw_status & INTEL_RNG_PRESENT) == 0)
+               goto err_unmap;
+
+       printk(KERN_INFO "Intel 82802 RNG detected\n");
+       err = hwrng_register(&intel_rng);
+       if (err) {
+               printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+                      err);
+               goto err_unmap;
+       }
+out:
+       return err;
+
+err_unmap:
+       iounmap(mem);
+       goto out;
+}
+
+static void __exit mod_exit(void)
+{
+       void __iomem *mem = (void __iomem *)intel_rng.priv;
+
+       hwrng_unregister(&intel_rng);
+       iounmap(mem);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
new file mode 100644 (file)
index 0000000..7f7615b
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * drivers/char/rng/ixp4xx-rng.c
+ *
+ * RNG driver for Intel IXP4xx family of NPUs
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Fixes by Michael Buesch
+ *
+ * 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/types.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/hw_random.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+
+static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer)
+{
+       void __iomem * rng_base = (void __iomem *)rng->priv;
+
+       *buffer = __raw_readl(rng_base);
+
+       return 4;
+}
+
+static struct hwrng ixp4xx_rng_ops = {
+       .name           = "ixp4xx",
+       .data_read      = ixp4xx_rng_data_read,
+};
+
+static int __init ixp4xx_rng_init(void)
+{
+       void __iomem * rng_base;
+       int err;
+
+       rng_base = ioremap(0x70002100, 4);
+       if (!rng_base)
+               return -ENOMEM;
+       ixp4xx_rng_ops.priv = (unsigned long)rng_base;
+       err = hwrng_register(&ixp4xx_rng_ops);
+       if (err)
+               iounmap(rng_base);
+
+       return err;
+}
+
+static void __exit ixp4xx_rng_exit(void)
+{
+       void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv;
+
+       hwrng_unregister(&ixp4xx_rng_ops);
+       iounmap(rng_base);
+}
+
+subsys_initcall(ixp4xx_rng_init);
+module_exit(ixp4xx_rng_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
new file mode 100644 (file)
index 0000000..a01d796
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * driver/char/hw_random/omap-rng.c
+ *
+ * RNG driver for TI OMAP CPU family
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Mostly based on original driver:
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrj��<juha.yrjola@nokia.com>
+ *
+ * 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.
+ *
+ * TODO:
+ *
+ * - Make status updated be interrupt driven so we don't poll
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+
+#include <asm/io.h>
+
+#define RNG_OUT_REG            0x00            /* Output register */
+#define RNG_STAT_REG           0x04            /* Status register
+                                                       [0] = STAT_BUSY */
+#define RNG_ALARM_REG          0x24            /* Alarm register
+                                                       [7:0] = ALARM_COUNTER */
+#define RNG_CONFIG_REG         0x28            /* Configuration register
+                                                       [11:6] = RESET_COUNT
+                                                       [5:3]  = RING2_DELAY
+                                                       [2:0]  = RING1_DELAY */
+#define RNG_REV_REG            0x3c            /* Revision register
+                                                       [7:0] = REV_NB */
+#define RNG_MASK_REG           0x40            /* Mask and reset register
+                                                       [2] = IT_EN
+                                                       [1] = SOFTRESET
+                                                       [0] = AUTOIDLE */
+#define RNG_SYSSTATUS          0x44            /* System status
+                                                       [0] = RESETDONE */
+
+static void __iomem *rng_base;
+static struct clk *rng_ick;
+static struct platform_device *rng_dev;
+
+static u32 omap_rng_read_reg(int reg)
+{
+       return __raw_readl(rng_base + reg);
+}
+
+static void omap_rng_write_reg(int reg, u32 val)
+{
+       __raw_writel(val, rng_base + reg);
+}
+
+/* REVISIT: Does the status bit really work on 16xx? */
+static int omap_rng_data_present(struct hwrng *rng)
+{
+       return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+}
+
+static int omap_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       *data = omap_rng_read_reg(RNG_OUT_REG);
+
+       return 4;
+}
+
+static struct hwrng omap_rng_ops = {
+       .name           = "omap",
+       .data_present   = omap_rng_data_present,
+       .data_read      = omap_rng_data_read,
+};
+
+static int __init omap_rng_probe(struct platform_device *pdev)
+{
+       struct resource *res, *mem;
+       int ret;
+
+       /*
+        * A bit ugly, and it will never actually happen but there can
+        * be only one RNG and this catches any bork
+        */
+       BUG_ON(rng_dev);
+
+       if (cpu_is_omap24xx()) {
+               rng_ick = clk_get(NULL, "rng_ick");
+               if (IS_ERR(rng_ick)) {
+                       dev_err(&pdev->dev, "Could not get rng_ick\n");
+                       ret = PTR_ERR(rng_ick);
+                       return ret;
+               } else
+                       clk_enable(rng_ick);
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       if (!res)
+               return -ENOENT;
+
+       mem = request_mem_region(res->start, res->end - res->start + 1,
+                                pdev->name);
+       if (mem == NULL)
+               return -EBUSY;
+
+       dev_set_drvdata(&pdev->dev, mem);
+       rng_base = (u32 __iomem *)io_p2v(res->start);
+
+       ret = hwrng_register(&omap_rng_ops);
+       if (ret) {
+               release_resource(mem);
+               rng_base = NULL;
+               return ret;
+       }
+
+       dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
+               omap_rng_read_reg(RNG_REV_REG));
+       omap_rng_write_reg(RNG_MASK_REG, 0x1);
+
+       rng_dev = pdev;
+
+       return 0;
+}
+
+static int __exit omap_rng_remove(struct platform_device *pdev)
+{
+       struct resource *mem = dev_get_drvdata(&pdev->dev);
+
+       hwrng_unregister(&omap_rng_ops);
+
+       omap_rng_write_reg(RNG_MASK_REG, 0x0);
+
+       if (cpu_is_omap24xx()) {
+               clk_disable(rng_ick);
+               clk_put(rng_ick);
+       }
+
+       release_resource(mem);
+       rng_base = NULL;
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
+{
+       omap_rng_write_reg(RNG_MASK_REG, 0x0);
+       return 0;
+}
+
+static int omap_rng_resume(struct platform_device *pdev)
+{
+       omap_rng_write_reg(RNG_MASK_REG, 0x1);
+       return 0;
+}
+
+#else
+
+#define        omap_rng_suspend        NULL
+#define        omap_rng_resume         NULL
+
+#endif
+
+
+static struct platform_driver omap_rng_driver = {
+       .driver = {
+               .name           = "omap_rng",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = omap_rng_probe,
+       .remove         = __exit_p(omap_rng_remove),
+       .suspend        = omap_rng_suspend,
+       .resume         = omap_rng_resume
+};
+
+static int __init omap_rng_init(void)
+{
+       if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
+               return -ENODEV;
+
+       return platform_driver_register(&omap_rng_driver);
+}
+
+static void __exit omap_rng_exit(void)
+{
+       platform_driver_unregister(&omap_rng_driver);
+}
+
+module_init(omap_rng_init);
+module_exit(omap_rng_exit);
+
+MODULE_AUTHOR("Deepak Saxena (and others)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
new file mode 100644 (file)
index 0000000..0e786b6
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * RNG driver for VIA RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/cpufeature.h>
+
+
+#define PFX    KBUILD_MODNAME ": "
+
+
+enum {
+       VIA_STRFILT_CNT_SHIFT   = 16,
+       VIA_STRFILT_FAIL        = (1 << 15),
+       VIA_STRFILT_ENABLE      = (1 << 14),
+       VIA_RAWBITS_ENABLE      = (1 << 13),
+       VIA_RNG_ENABLE          = (1 << 6),
+       VIA_XSTORE_CNT_MASK     = 0x0F,
+
+       VIA_RNG_CHUNK_8         = 0x00, /* 64 rand bits, 64 stored bits */
+       VIA_RNG_CHUNK_4         = 0x01, /* 32 rand bits, 32 stored bits */
+       VIA_RNG_CHUNK_4_MASK    = 0xFFFFFFFF,
+       VIA_RNG_CHUNK_2         = 0x02, /* 16 rand bits, 32 stored bits */
+       VIA_RNG_CHUNK_2_MASK    = 0xFFFF,
+       VIA_RNG_CHUNK_1         = 0x03, /* 8 rand bits, 32 stored bits */
+       VIA_RNG_CHUNK_1_MASK    = 0xFF,
+};
+
+/*
+ * Investigate using the 'rep' prefix to obtain 32 bits of random data
+ * in one insn.  The upside is potentially better performance.  The
+ * downside is that the instruction becomes no longer atomic.  Due to
+ * this, just like familiar issues with /dev/random itself, the worst
+ * case of a 'rep xstore' could potentially pause a cpu for an
+ * unreasonably long time.  In practice, this condition would likely
+ * only occur when the hardware is failing.  (or so we hope :))
+ *
+ * Another possible performance boost may come from simply buffering
+ * until we have 4 bytes, thus returning a u32 at a time,
+ * instead of the current u8-at-a-time.
+ */
+
+static inline u32 xstore(u32 *addr, u32 edx_in)
+{
+       u32 eax_out;
+
+       asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
+               :"=m"(*addr), "=a"(eax_out)
+               :"D"(addr), "d"(edx_in));
+
+       return eax_out;
+}
+
+static int via_rng_data_present(struct hwrng *rng)
+{
+       u32 bytes_out;
+       u32 *via_rng_datum = (u32 *)(&rng->priv);
+
+       /* We choose the recommended 1-byte-per-instruction RNG rate,
+        * for greater randomness at the expense of speed.  Larger
+        * values 2, 4, or 8 bytes-per-instruction yield greater
+        * speed at lesser randomness.
+        *
+        * If you change this to another VIA_CHUNK_n, you must also
+        * change the ->n_bytes values in rng_vendor_ops[] tables.
+        * VIA_CHUNK_8 requires further code changes.
+        *
+        * A copy of MSR_VIA_RNG is placed in eax_out when xstore
+        * completes.
+        */
+
+       *via_rng_datum = 0; /* paranoia, not really necessary */
+       bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
+       bytes_out &= VIA_XSTORE_CNT_MASK;
+       if (bytes_out == 0)
+               return 0;
+       return 1;
+}
+
+static int via_rng_data_read(struct hwrng *rng, u32 *data)
+{
+       u32 via_rng_datum = (u32)rng->priv;
+
+       *data = via_rng_datum;
+
+       return 1;
+}
+
+static int via_rng_init(struct hwrng *rng)
+{
+       u32 lo, hi, old_lo;
+
+       /* Control the RNG via MSR.  Tread lightly and pay very close
+        * close attention to values written, as the reserved fields
+        * are documented to be "undefined and unpredictable"; but it
+        * does not say to write them as zero, so I make a guess that
+        * we restore the values we find in the register.
+        */
+       rdmsr(MSR_VIA_RNG, lo, hi);
+
+       old_lo = lo;
+       lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
+       lo &= ~VIA_XSTORE_CNT_MASK;
+       lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
+       lo |= VIA_RNG_ENABLE;
+
+       if (lo != old_lo)
+               wrmsr(MSR_VIA_RNG, lo, hi);
+
+       /* perhaps-unnecessary sanity check; remove after testing if
+          unneeded */
+       rdmsr(MSR_VIA_RNG, lo, hi);
+       if ((lo & VIA_RNG_ENABLE) == 0) {
+               printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+
+static struct hwrng via_rng = {
+       .name           = "via",
+       .init           = via_rng_init,
+       .data_present   = via_rng_data_present,
+       .data_read      = via_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+       int err;
+
+       if (!cpu_has_xstore)
+               return -ENODEV;
+       printk(KERN_INFO "VIA RNG detected\n");
+       err = hwrng_register(&via_rng);
+       if (err) {
+               printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+                      err);
+               goto out;
+       }
+out:
+       return err;
+}
+
+static void __exit mod_exit(void)
+{
+       hwrng_unregister(&via_rng);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c
new file mode 100644 (file)
index 0000000..4d47d79
--- /dev/null
@@ -0,0 +1,139 @@
+/* linux/drivers/char/nsc_gpio.c
+
+   National Semiconductor common GPIO device-file/VFS methods.
+   Allows a user space process to control the GPIO pins.
+
+   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
+   Copyright (c) 2005      Jim Cromie <jim.cromie@gmail.com>
+*/
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/nsc_gpio.h>
+#include <linux/platform_device.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define NAME "nsc_gpio"
+
+void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index)
+{
+       /* retrieve current config w/o changing it */
+       u32 config = amp->gpio_config(index, ~0, 0);
+
+       /* user requested via 'v' command, so its INFO */
+       dev_info(amp->dev, "io%02u: 0x%04x %s %s %s %s %s %s %s\tio:%d/%d\n",
+                index, config,
+                (config & 1) ? "OE" : "TS",      /* output-enabled/tristate */
+                (config & 2) ? "PP" : "OD",      /* push pull / open drain */
+                (config & 4) ? "PUE" : "PUD",    /* pull up enabled/disabled */
+                (config & 8) ? "LOCKED" : "",    /* locked / unlocked */
+                (config & 16) ? "LEVEL" : "EDGE",/* level/edge input */
+                (config & 32) ? "HI" : "LO",     /* trigger on rise/fall edge */
+                (config & 64) ? "DEBOUNCE" : "", /* debounce */
+
+                amp->gpio_get(index), amp->gpio_current(index));
+}
+
+ssize_t nsc_gpio_write(struct file *file, const char __user *data,
+                      size_t len, loff_t *ppos)
+{
+       unsigned m = iminor(file->f_dentry->d_inode);
+       struct nsc_gpio_ops *amp = file->private_data;
+       struct device *dev = amp->dev;
+       size_t i;
+       int err = 0;
+
+       for (i = 0; i < len; ++i) {
+               char c;
+               if (get_user(c, data + i))
+                       return -EFAULT;
+               switch (c) {
+               case '0':
+                       amp->gpio_set(m, 0);
+                       break;
+               case '1':
+                       amp->gpio_set(m, 1);
+                       break;
+               case 'O':
+                       dev_dbg(dev, "GPIO%d output enabled\n", m);
+                       amp->gpio_config(m, ~1, 1);
+                       break;
+               case 'o':
+                       dev_dbg(dev, "GPIO%d output disabled\n", m);
+                       amp->gpio_config(m, ~1, 0);
+                       break;
+               case 'T':
+                       dev_dbg(dev, "GPIO%d output is push pull\n", m);
+                       amp->gpio_config(m, ~2, 2);
+                       break;
+               case 't':
+                       dev_dbg(dev, "GPIO%d output is open drain\n", m);
+                       amp->gpio_config(m, ~2, 0);
+                       break;
+               case 'P':
+                       dev_dbg(dev, "GPIO%d pull up enabled\n", m);
+                       amp->gpio_config(m, ~4, 4);
+                       break;
+               case 'p':
+                       dev_dbg(dev, "GPIO%d pull up disabled\n", m);
+                       amp->gpio_config(m, ~4, 0);
+                       break;
+               case 'v':
+                       /* View Current pin settings */
+                       amp->gpio_dump(amp, m);
+                       break;
+               case '\n':
+                       /* end of settings string, do nothing */
+                       break;
+               default:
+                       dev_err(dev, "io%2d bad setting: chr<0x%2x>\n",
+                               m, (int)c);
+                       err++;
+               }
+       }
+       if (err)
+               return -EINVAL; /* full string handled, report error */
+
+       return len;
+}
+
+ssize_t nsc_gpio_read(struct file *file, char __user * buf,
+                     size_t len, loff_t * ppos)
+{
+       unsigned m = iminor(file->f_dentry->d_inode);
+       int value;
+       struct nsc_gpio_ops *amp = file->private_data;
+
+       value = amp->gpio_get(m);
+       if (put_user(value ? '1' : '0', buf))
+               return -EFAULT;
+
+       return 1;
+}
+
+/* common file-ops routines for both scx200_gpio and pc87360_gpio */
+EXPORT_SYMBOL(nsc_gpio_write);
+EXPORT_SYMBOL(nsc_gpio_read);
+EXPORT_SYMBOL(nsc_gpio_dump);
+
+static int __init nsc_gpio_init(void)
+{
+       printk(KERN_DEBUG NAME " initializing\n");
+       return 0;
+}
+
+static void __exit nsc_gpio_cleanup(void)
+{
+       printk(KERN_DEBUG NAME " cleanup\n");
+}
+
+module_init(nsc_gpio_init);
+module_exit(nsc_gpio_cleanup);
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_DESCRIPTION("NatSemi GPIO Common Methods");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
new file mode 100644 (file)
index 0000000..84e5a68
--- /dev/null
@@ -0,0 +1,357 @@
+/* linux/drivers/char/pc8736x_gpio.c
+
+   National Semiconductor PC8736x GPIO driver.  Allows a user space
+   process to play with the GPIO pins.
+
+   Copyright (c) 2005,2006 Jim Cromie <jim.cromie@gmail.com>
+
+   adapted from linux/drivers/char/scx200_gpio.c
+   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>,
+*/
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/nsc_gpio.h>
+#include <linux/platform_device.h>
+#include <asm/uaccess.h>
+
+#define DEVNAME "pc8736x_gpio"
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_DESCRIPTION("NatSemi/Winbond PC-8736x GPIO Pin Driver");
+MODULE_LICENSE("GPL");
+
+static int major;              /* default to dynamic major */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static DEFINE_MUTEX(pc8736x_gpio_config_lock);
+static unsigned pc8736x_gpio_base;
+static u8 pc8736x_gpio_shadow[4];
+
+#define SIO_BASE1       0x2E   /* 1st command-reg to check */
+#define SIO_BASE2       0x4E   /* alt command-reg to check */
+
+#define SIO_SID                0x20    /* SuperI/O ID Register */
+#define SIO_SID_VALUE  0xe9    /* Expected value in SuperI/O ID Register */
+
+#define SIO_CF1                0x21    /* chip config, bit0 is chip enable */
+
+#define PC8736X_GPIO_RANGE     16 /* ioaddr range */
+#define PC8736X_GPIO_CT                32 /* minors matching 4 8 bit ports */
+
+#define SIO_UNIT_SEL   0x7     /* unit select reg */
+#define SIO_UNIT_ACT   0x30    /* unit enable */
+#define SIO_GPIO_UNIT  0x7     /* unit number of GPIO */
+#define SIO_VLM_UNIT   0x0D
+#define SIO_TMS_UNIT   0x0E
+
+/* config-space addrs to read/write each unit's runtime addr */
+#define SIO_BASE_HADDR         0x60
+#define SIO_BASE_LADDR         0x61
+
+/* GPIO config-space pin-control addresses */
+#define SIO_GPIO_PIN_SELECT    0xF0
+#define SIO_GPIO_PIN_CONFIG     0xF1
+#define SIO_GPIO_PIN_EVENT      0xF2
+
+static unsigned char superio_cmd = 0;
+static unsigned char selected_device = 0xFF;   /* bogus start val */
+
+/* GPIO port runtime access, functionality */
+static int port_offset[] = { 0, 4, 8, 10 };    /* non-uniform offsets ! */
+/* static int event_capable[] = { 1, 1, 0, 0 };   ports 2,3 are hobbled */
+
+#define PORT_OUT       0
+#define PORT_IN                1
+#define PORT_EVT_EN    2
+#define PORT_EVT_STST  3
+
+static struct platform_device *pdev;  /* use in dev_*() */
+
+static inline void superio_outb(int addr, int val)
+{
+       outb_p(addr, superio_cmd);
+       outb_p(val, superio_cmd + 1);
+}
+
+static inline int superio_inb(int addr)
+{
+       outb_p(addr, superio_cmd);
+       return inb_p(superio_cmd + 1);
+}
+
+static int pc8736x_superio_present(void)
+{
+       /* try the 2 possible values, read a hardware reg to verify */
+       superio_cmd = SIO_BASE1;
+       if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+               return superio_cmd;
+
+       superio_cmd = SIO_BASE2;
+       if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+               return superio_cmd;
+
+       return 0;
+}
+
+static void device_select(unsigned devldn)
+{
+       superio_outb(SIO_UNIT_SEL, devldn);
+       selected_device = devldn;
+}
+
+static void select_pin(unsigned iminor)
+{
+       /* select GPIO port/pin from device minor number */
+       device_select(SIO_GPIO_UNIT);
+       superio_outb(SIO_GPIO_PIN_SELECT,
+                    ((iminor << 1) & 0xF0) | (iminor & 0x7));
+}
+
+static inline u32 pc8736x_gpio_configure_fn(unsigned index, u32 mask, u32 bits,
+                                           u32 func_slct)
+{
+       u32 config, new_config;
+
+       mutex_lock(&pc8736x_gpio_config_lock);
+
+       device_select(SIO_GPIO_UNIT);
+       select_pin(index);
+
+       /* read current config value */
+       config = superio_inb(func_slct);
+
+       /* set new config */
+       new_config = (config & mask) | bits;
+       superio_outb(func_slct, new_config);
+
+       mutex_unlock(&pc8736x_gpio_config_lock);
+
+       return config;
+}
+
+static u32 pc8736x_gpio_configure(unsigned index, u32 mask, u32 bits)
+{
+       return pc8736x_gpio_configure_fn(index, mask, bits,
+                                        SIO_GPIO_PIN_CONFIG);
+}
+
+static int pc8736x_gpio_get(unsigned minor)
+{
+       int port, bit, val;
+
+       port = minor >> 3;
+       bit = minor & 7;
+       val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN);
+       val >>= bit;
+       val &= 1;
+
+       dev_dbg(&pdev->dev, "_gpio_get(%d from %x bit %d) == val %d\n",
+               minor, pc8736x_gpio_base + port_offset[port] + PORT_IN, bit,
+               val);
+
+       return val;
+}
+
+static void pc8736x_gpio_set(unsigned minor, int val)
+{
+       int port, bit, curval;
+
+       minor &= 0x1f;
+       port = minor >> 3;
+       bit = minor & 7;
+       curval = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_OUT);
+
+       dev_dbg(&pdev->dev, "addr:%x cur:%x bit-pos:%d cur-bit:%x + new:%d -> bit-new:%d\n",
+               pc8736x_gpio_base + port_offset[port] + PORT_OUT,
+               curval, bit, (curval & ~(1 << bit)), val, (val << bit));
+
+       val = (curval & ~(1 << bit)) | (val << bit);
+
+       dev_dbg(&pdev->dev, "gpio_set(minor:%d port:%d bit:%d)"
+               " %2x -> %2x\n", minor, port, bit, curval, val);
+
+       outb_p(val, pc8736x_gpio_base + port_offset[port] + PORT_OUT);
+
+       curval = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_OUT);
+       val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN);
+
+       dev_dbg(&pdev->dev, "wrote %x, read: %x\n", curval, val);
+       pc8736x_gpio_shadow[port] = val;
+}
+
+static void pc8736x_gpio_set_high(unsigned index)
+{
+       pc8736x_gpio_set(index, 1);
+}
+
+static void pc8736x_gpio_set_low(unsigned index)
+{
+       pc8736x_gpio_set(index, 0);
+}
+
+static int pc8736x_gpio_current(unsigned minor)
+{
+       int port, bit;
+       minor &= 0x1f;
+       port = minor >> 3;
+       bit = minor & 7;
+       return ((pc8736x_gpio_shadow[port] >> bit) & 0x01);
+}
+
+static void pc8736x_gpio_change(unsigned index)
+{
+       pc8736x_gpio_set(index, !pc8736x_gpio_current(index));
+}
+
+static struct nsc_gpio_ops pc8736x_gpio_ops = {
+       .owner          = THIS_MODULE,
+       .gpio_config    = pc8736x_gpio_configure,
+       .gpio_dump      = nsc_gpio_dump,
+       .gpio_get       = pc8736x_gpio_get,
+       .gpio_set       = pc8736x_gpio_set,
+       .gpio_change    = pc8736x_gpio_change,
+       .gpio_current   = pc8736x_gpio_current
+};
+
+static int pc8736x_gpio_open(struct inode *inode, struct file *file)
+{
+       unsigned m = iminor(inode);
+       file->private_data = &pc8736x_gpio_ops;
+
+       dev_dbg(&pdev->dev, "open %d\n", m);
+
+       if (m >= PC8736X_GPIO_CT)
+               return -EINVAL;
+       return nonseekable_open(inode, file);
+}
+
+static const struct file_operations pc8736x_gpio_fileops = {
+       .owner  = THIS_MODULE,
+       .open   = pc8736x_gpio_open,
+       .write  = nsc_gpio_write,
+       .read   = nsc_gpio_read,
+};
+
+static void __init pc8736x_init_shadow(void)
+{
+       int port;
+
+       /* read the current values driven on the GPIO signals */
+       for (port = 0; port < 4; ++port)
+               pc8736x_gpio_shadow[port]
+                   = inb_p(pc8736x_gpio_base + port_offset[port]
+                           + PORT_OUT);
+
+}
+
+static struct cdev pc8736x_gpio_cdev;
+
+static int __init pc8736x_gpio_init(void)
+{
+       int rc;
+       dev_t devid;
+
+       pdev = platform_device_alloc(DEVNAME, 0);
+       if (!pdev)
+               return -ENOMEM;
+
+       rc = platform_device_add(pdev);
+       if (rc) {
+               rc = -ENODEV;
+               goto undo_platform_dev_alloc;
+       }
+       dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n");
+
+       if (!pc8736x_superio_present()) {
+               rc = -ENODEV;
+               dev_err(&pdev->dev, "no device found\n");
+               goto undo_platform_dev_add;
+       }
+       pc8736x_gpio_ops.dev = &pdev->dev;
+
+       /* Verify that chip and it's GPIO unit are both enabled.
+          My BIOS does this, so I take minimum action here
+        */
+       rc = superio_inb(SIO_CF1);
+       if (!(rc & 0x01)) {
+               rc = -ENODEV;
+               dev_err(&pdev->dev, "device not enabled\n");
+               goto undo_platform_dev_add;
+       }
+       device_select(SIO_GPIO_UNIT);
+       if (!superio_inb(SIO_UNIT_ACT)) {
+               rc = -ENODEV;
+               dev_err(&pdev->dev, "GPIO unit not enabled\n");
+               goto undo_platform_dev_add;
+       }
+
+       /* read the GPIO unit base addr that chip responds to */
+       pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
+                            | superio_inb(SIO_BASE_LADDR));
+
+       if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) {
+               rc = -ENODEV;
+               dev_err(&pdev->dev, "GPIO ioport %x busy\n",
+                       pc8736x_gpio_base);
+               goto undo_platform_dev_add;
+       }
+       dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);
+
+       if (major) {
+               devid = MKDEV(major, 0);
+               rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME);
+       } else {
+               rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME);
+               major = MAJOR(devid);
+       }
+
+       if (rc < 0) {
+               dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc);
+               goto undo_request_region;
+       }
+       if (!major) {
+               major = rc;
+               dev_dbg(&pdev->dev, "got dynamic major %d\n", major);
+       }
+
+       pc8736x_init_shadow();
+
+       /* ignore minor errs, and succeed */
+       cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops);
+       cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT);
+
+       return 0;
+
+undo_request_region:
+       release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
+undo_platform_dev_add:
+       platform_device_del(pdev);
+undo_platform_dev_alloc:
+       platform_device_put(pdev);
+
+       return rc;
+}
+
+static void __exit pc8736x_gpio_cleanup(void)
+{
+       dev_dbg(&pdev->dev, "cleanup\n");
+
+       cdev_del(&pc8736x_gpio_cdev);
+       unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT);
+       release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
+
+       platform_device_del(pdev);
+       platform_device_put(pdev);
+}
+
+module_init(pc8736x_gpio_init);
+module_exit(pc8736x_gpio_cleanup);
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
new file mode 100644 (file)
index 0000000..a522254
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_X86_CYCLONE_TIMER)        += cyclone.o
+obj-$(CONFIG_X86_PM_TIMER)     += acpi_pm.o
+obj-$(CONFIG_SCx200HR_TIMER)   += scx200_hrt.o
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
new file mode 100644 (file)
index 0000000..7ad3be8
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * linux/drivers/clocksource/acpi_pm.c
+ *
+ * This file contains the ACPI PM based clocksource.
+ *
+ * This code was largely moved from the i386 timer_pm.c file
+ * which was (C) Dominik Brodowski <linux@brodo.de> 2003
+ * and contained the following comments:
+ *
+ * Driver to use the Power Management Timer (PMTMR) available in some
+ * southbridges as primary timing source for the Linux kernel.
+ *
+ * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
+ * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
+ *
+ * This file is licensed under the GPL v2.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/* Number of PMTMR ticks expected during calibration run */
+#define PMTMR_TICKS_PER_SEC 3579545
+
+/*
+ * The I/O port the PMTMR resides at.
+ * The location is detected during setup_arch(),
+ * in arch/i386/acpi/boot.c
+ */
+u32 pmtmr_ioport __read_mostly;
+
+#define ACPI_PM_MASK CLOCKSOURCE_MASK(24) /* limit it to 24 bits */
+
+static inline u32 read_pmtmr(void)
+{
+       /* mask the output to 24 bits */
+       return inl(pmtmr_ioport) & ACPI_PM_MASK;
+}
+
+static cycle_t acpi_pm_read_verified(void)
+{
+       u32 v1 = 0, v2 = 0, v3 = 0;
+
+       /*
+        * It has been reported that because of various broken
+        * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM clock
+        * source is not latched, you must read it multiple
+        * times to ensure a safe value is read:
+        */
+       do {
+               v1 = read_pmtmr();
+               v2 = read_pmtmr();
+               v3 = read_pmtmr();
+       } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+                       || (v3 > v1 && v3 < v2));
+
+       return (cycle_t)v2;
+}
+
+static cycle_t acpi_pm_read(void)
+{
+       return (cycle_t)read_pmtmr();
+}
+
+static struct clocksource clocksource_acpi_pm = {
+       .name           = "acpi_pm",
+       .rating         = 200,
+       .read           = acpi_pm_read,
+       .mask           = (cycle_t)ACPI_PM_MASK,
+       .mult           = 0, /*to be caluclated*/
+       .shift          = 22,
+       .is_continuous  = 1,
+};
+
+
+#ifdef CONFIG_PCI
+static int acpi_pm_good;
+static int __init acpi_pm_good_setup(char *__str)
+{
+       acpi_pm_good = 1;
+       return 1;
+}
+__setup("acpi_pm_good", acpi_pm_good_setup);
+
+static inline void acpi_pm_need_workaround(void)
+{
+       clocksource_acpi_pm.read = acpi_pm_read_verified;
+       clocksource_acpi_pm.rating = 110;
+}
+
+/*
+ * PIIX4 Errata:
+ *
+ * The power management timer may return improper results when read.
+ * Although the timer value settles properly after incrementing,
+ * while incrementing there is a 3 ns window every 69.8 ns where the
+ * timer value is indeterminate (a 4.2% chance that the data will be
+ * incorrect when read). As a result, the ACPI free running count up
+ * timer specification is violated due to erroneous reads.
+ */
+static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
+{
+       u8 rev;
+
+       if (acpi_pm_good)
+               return;
+
+       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+       /* the bug has been fixed in PIIX4M */
+       if (rev < 3) {
+               printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
+                      " Due to workarounds for a bug,\n"
+                      "* this clock source is slow. Consider trying"
+                      " other clock sources\n");
+
+               acpi_pm_need_workaround();
+       }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+                       acpi_pm_check_blacklist);
+
+static void __devinit acpi_pm_check_graylist(struct pci_dev *dev)
+{
+       if (acpi_pm_good)
+               return;
+
+       printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to"
+              " workarounds for a bug,\n"
+              "* this clock source is slow. If you are sure your timer"
+              " does not have\n"
+              "* this bug, please use \"acpi_pm_good\" to disable the"
+              " workaround\n");
+
+       acpi_pm_need_workaround();
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
+                       acpi_pm_check_graylist);
+#endif
+
+
+static int __init init_acpi_pm_clocksource(void)
+{
+       u32 value1, value2;
+       unsigned int i;
+
+       if (!pmtmr_ioport)
+               return -ENODEV;
+
+       clocksource_acpi_pm.mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC,
+                                               clocksource_acpi_pm.shift);
+
+       /* "verify" this timing source: */
+       value1 = read_pmtmr();
+       for (i = 0; i < 10000; i++) {
+               value2 = read_pmtmr();
+               if (value2 == value1)
+                       continue;
+               if (value2 > value1)
+                       goto pm_good;
+               if ((value2 < value1) && ((value2) < 0xFFF))
+                       goto pm_good;
+               printk(KERN_INFO "PM-Timer had inconsistent results:"
+                       " 0x%#x, 0x%#x - aborting.\n", value1, value2);
+               return -EINVAL;
+       }
+       printk(KERN_INFO "PM-Timer had no reasonable result:"
+                       " 0x%#x - aborting.\n", value1);
+       return -ENODEV;
+
+pm_good:
+       return clocksource_register(&clocksource_acpi_pm);
+}
+
+module_init(init_acpi_pm_clocksource);
diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c
new file mode 100644 (file)
index 0000000..bf4d3d5
--- /dev/null
@@ -0,0 +1,119 @@
+#include <linux/clocksource.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/init.h>
+
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include "mach_timer.h"
+
+#define CYCLONE_CBAR_ADDR      0xFEB00CD0      /* base address ptr */
+#define CYCLONE_PMCC_OFFSET    0x51A0          /* offset to control register */
+#define CYCLONE_MPCS_OFFSET    0x51A8          /* offset to select register */
+#define CYCLONE_MPMC_OFFSET    0x51D0          /* offset to count register */
+#define CYCLONE_TIMER_FREQ     99780000        /* 100Mhz, but not really */
+#define CYCLONE_TIMER_MASK     CLOCKSOURCE_MASK(32) /* 32 bit mask */
+
+int use_cyclone = 0;
+static void __iomem *cyclone_ptr;
+
+static cycle_t read_cyclone(void)
+{
+       return (cycle_t)readl(cyclone_ptr);
+}
+
+static struct clocksource clocksource_cyclone = {
+       .name           = "cyclone",
+       .rating         = 250,
+       .read           = read_cyclone,
+       .mask           = CYCLONE_TIMER_MASK,
+       .mult           = 10,
+       .shift          = 0,
+       .is_continuous  = 1,
+};
+
+static int __init init_cyclone_clocksource(void)
+{
+       unsigned long base;     /* saved value from CBAR */
+       unsigned long offset;
+       u32 __iomem* volatile cyclone_timer;    /* Cyclone MPMC0 register */
+       u32 __iomem* reg;
+       int i;
+
+       /* make sure we're on a summit box: */
+       if (!use_cyclone)
+               return -ENODEV;
+
+       printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
+
+       /* find base address: */
+       offset = CYCLONE_CBAR_ADDR;
+       reg = ioremap_nocache(offset, sizeof(reg));
+       if (!reg) {
+               printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
+               return -ENODEV;
+       }
+       /* even on 64bit systems, this is only 32bits: */
+       base = readl(reg);
+       if (!base) {
+               printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
+               return -ENODEV;
+       }
+       iounmap(reg);
+
+       /* setup PMCC: */
+       offset = base + CYCLONE_PMCC_OFFSET;
+       reg = ioremap_nocache(offset, sizeof(reg));
+       if (!reg) {
+               printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
+               return -ENODEV;
+       }
+       writel(0x00000001,reg);
+       iounmap(reg);
+
+       /* setup MPCS: */
+       offset = base + CYCLONE_MPCS_OFFSET;
+       reg = ioremap_nocache(offset, sizeof(reg));
+       if (!reg) {
+               printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
+               return -ENODEV;
+       }
+       writel(0x00000001,reg);
+       iounmap(reg);
+
+       /* map in cyclone_timer: */
+       offset = base + CYCLONE_MPMC_OFFSET;
+       cyclone_timer = ioremap_nocache(offset, sizeof(u64));
+       if (!cyclone_timer) {
+               printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
+               return -ENODEV;
+       }
+
+       /* quick test to make sure its ticking: */
+       for (i = 0; i < 3; i++){
+               u32 old = readl(cyclone_timer);
+               int stall = 100;
+
+               while (stall--)
+                       barrier();
+
+               if (readl(cyclone_timer) == old) {
+                       printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
+                       iounmap(cyclone_timer);
+                       cyclone_timer = NULL;
+                       return -ENODEV;
+               }
+       }
+       cyclone_ptr = cyclone_timer;
+
+       /* sort out mult/shift values: */
+       clocksource_cyclone.shift = 22;
+       clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ,
+                                               clocksource_cyclone.shift);
+
+       return clocksource_register(&clocksource_cyclone);
+}
+
+module_init(init_cyclone_clocksource);
diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c
new file mode 100644 (file)
index 0000000..22915cc
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006 Jim Cromie
+ *
+ * This is a clocksource driver for the Geode SCx200's 1 or 27 MHz
+ * high-resolution timer.  The Geode SC-1100 (at least) has a buggy
+ * time stamp counter (TSC), which loses time unless 'idle=poll' is
+ * given as a boot-arg. In its absence, the Generic Timekeeping code
+ * will detect and de-rate the bad TSC, allowing this timer to take
+ * over timekeeping duties.
+ *
+ * Based on work by John Stultz, and Ted Phelps (in a 2.6.12-rc6 patch)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/clocksource.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/scx200.h>
+
+#define NAME "scx200_hrt"
+
+static int mhz27;
+module_param(mhz27, int, 0);   /* load time only */
+MODULE_PARM_DESC(mhz27, "count at 27.0 MHz (default is 1.0 MHz)");
+
+static int ppm;
+module_param(ppm, int, 0);     /* load time only */
+MODULE_PARM_DESC(ppm, "+-adjust to actual XO freq (ppm)");
+
+/* HiRes Timer configuration register address */
+#define SCx200_TMCNFG_OFFSET (SCx200_TIMER_OFFSET + 5)
+
+/* and config settings */
+#define HR_TMEN (1 << 0)       /* timer interrupt enable */
+#define HR_TMCLKSEL (1 << 1)   /* 1|0 counts at 27|1 MHz */
+#define HR_TM27MPD (1 << 2)    /* 1 turns off input clock (power-down) */
+
+/* The base timer frequency, * 27 if selected */
+#define HRT_FREQ   1000000
+
+static cycle_t read_hrt(void)
+{
+       /* Read the timer value */
+       return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET);
+}
+
+#define HRT_SHIFT_1    22
+#define HRT_SHIFT_27   26
+
+static struct clocksource cs_hrt = {
+       .name           = "scx200_hrt",
+       .rating         = 250,
+       .read           = read_hrt,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .is_continuous  = 1,
+       /* mult, shift are set based on mhz27 flag */
+};
+
+static int __init init_hrt_clocksource(void)
+{
+       /* Make sure scx200 has initialized the configuration block */
+       if (!scx200_cb_present())
+               return -ENODEV;
+
+       /* Reserve the timer's ISA io-region for ourselves */
+       if (!request_region(scx200_cb_base + SCx200_TIMER_OFFSET,
+                           SCx200_TIMER_SIZE,
+                           "NatSemi SCx200 High-Resolution Timer")) {
+               printk(KERN_WARNING NAME ": unable to lock timer region\n");
+               return -ENODEV;
+       }
+
+       /* write timer config */
+       outb(HR_TMEN | (mhz27 ? HR_TMCLKSEL : 0),
+            scx200_cb_base + SCx200_TMCNFG_OFFSET);
+
+       if (mhz27) {
+               cs_hrt.shift = HRT_SHIFT_27;
+               cs_hrt.mult = clocksource_hz2mult((HRT_FREQ + ppm) * 27,
+                                                 cs_hrt.shift);
+       } else {
+               cs_hrt.shift = HRT_SHIFT_1;
+               cs_hrt.mult = clocksource_hz2mult(HRT_FREQ + ppm,
+                                                 cs_hrt.shift);
+       }
+       printk(KERN_INFO "enabling scx200 high-res timer (%s MHz +%d ppm)\n",
+               mhz27 ? "27":"1", ppm);
+
+       return clocksource_register(&cs_hrt);
+}
+
+module_init(init_hrt_clocksource);
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_DESCRIPTION("clocksource on SCx200 HiRes Timer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
new file mode 100644 (file)
index 0000000..30d021d
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# DMA engine configuration
+#
+
+menu "DMA Engine support"
+
+config DMA_ENGINE
+       bool "Support for DMA engines"
+       ---help---
+         DMA engines offload copy operations from the CPU to dedicated
+         hardware, allowing the copies to happen asynchronously.
+
+comment "DMA Clients"
+
+config NET_DMA
+       bool "Network: TCP receive copy offload"
+       depends on DMA_ENGINE && NET
+       default y
+       ---help---
+         This enables the use of DMA engines in the network stack to
+         offload receive copy-to-user operations, freeing CPU cycles.
+         Since this is the main user of the DMA engine, it should be enabled;
+         say Y here.
+
+comment "DMA Devices"
+
+config INTEL_IOATDMA
+       tristate "Intel I/OAT DMA support"
+       depends on DMA_ENGINE && PCI
+       default m
+       ---help---
+         Enable support for the Intel(R) I/OAT DMA engine.
+
+endmenu
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
new file mode 100644 (file)
index 0000000..bdcfdbd
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
+obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
new file mode 100644 (file)
index 0000000..1527804
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This code implements the DMA subsystem. It provides a HW-neutral interface
+ * for other kernel code to use asynchronous memory copy capabilities,
+ * if present, and allows different HW DMA drivers to register as providing
+ * this capability.
+ *
+ * Due to the fact we are accelerating what is already a relatively fast
+ * operation, the code goes to great lengths to avoid additional overhead,
+ * such as locking.
+ *
+ * LOCKING:
+ *
+ * The subsystem keeps two global lists, dma_device_list and dma_client_list.
+ * Both of these are protected by a mutex, dma_list_mutex.
+ *
+ * Each device has a channels list, which runs unlocked but is never modified
+ * once the device is registered, it's just setup by the driver.
+ *
+ * Each client has a channels list, it's only modified under the client->lock
+ * and in an RCU callback, so it's safe to read under rcu_read_lock().
+ *
+ * Each device has a kref, which is initialized to 1 when the device is
+ * registered. A kref_put is done for each class_device registered.  When the
+ * class_device is released, the coresponding kref_put is done in the release
+ * method. Every time one of the device's channels is allocated to a client,
+ * a kref_get occurs.  When the channel is freed, the coresponding kref_put
+ * happens. The device's release function does a completion, so
+ * unregister_device does a remove event, class_device_unregister, a kref_put
+ * for the first reference, then waits on the completion for all other
+ * references to finish.
+ *
+ * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+ * with a kref and a per_cpu local_t.  A single reference is set when on an
+ * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
+ * extra reference per outstanding transaction.  The relase function does a
+ * kref_put on the device. -ChrisL
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/percpu.h>
+#include <linux/rcupdate.h>
+#include <linux/mutex.h>
+
+static DEFINE_MUTEX(dma_list_mutex);
+static LIST_HEAD(dma_device_list);
+static LIST_HEAD(dma_client_list);
+
+/* --- sysfs implementation --- */
+
+static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       unsigned long count = 0;
+       int i;
+
+       for_each_possible_cpu(i)
+               count += per_cpu_ptr(chan->local, i)->memcpy_count;
+
+       return sprintf(buf, "%lu\n", count);
+}
+
+static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       unsigned long count = 0;
+       int i;
+
+       for_each_possible_cpu(i)
+               count += per_cpu_ptr(chan->local, i)->bytes_transferred;
+
+       return sprintf(buf, "%lu\n", count);
+}
+
+static ssize_t show_in_use(struct class_device *cd, char *buf)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+
+       return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
+}
+
+static struct class_device_attribute dma_class_attrs[] = {
+       __ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
+       __ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
+       __ATTR(in_use, S_IRUGO, show_in_use, NULL),
+       __ATTR_NULL
+};
+
+static void dma_async_device_cleanup(struct kref *kref);
+
+static void dma_class_dev_release(struct class_device *cd)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       kref_put(&chan->device->refcount, dma_async_device_cleanup);
+}
+
+static struct class dma_devclass = {
+       .name            = "dma",
+       .class_dev_attrs = dma_class_attrs,
+       .release = dma_class_dev_release,
+};
+
+/* --- client and device registration --- */
+
+/**
+ * dma_client_chan_alloc - try to allocate a channel to a client
+ * @client: &dma_client
+ *
+ * Called with dma_list_mutex held.
+ */
+static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+{
+       struct dma_device *device;
+       struct dma_chan *chan;
+       unsigned long flags;
+       int desc;       /* allocated descriptor count */
+
+       /* Find a channel, any DMA engine will do */
+       list_for_each_entry(device, &dma_device_list, global_node) {
+               list_for_each_entry(chan, &device->channels, device_node) {
+                       if (chan->client)
+                               continue;
+
+                       desc = chan->device->device_alloc_chan_resources(chan);
+                       if (desc >= 0) {
+                               kref_get(&device->refcount);
+                               kref_init(&chan->refcount);
+                               chan->slow_ref = 0;
+                               INIT_RCU_HEAD(&chan->rcu);
+                               chan->client = client;
+                               spin_lock_irqsave(&client->lock, flags);
+                               list_add_tail_rcu(&chan->client_node,
+                                                 &client->channels);
+                               spin_unlock_irqrestore(&client->lock, flags);
+                               return chan;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+/**
+ * dma_chan_cleanup - release a DMA channel's resources
+ * @kref: kernel reference structure that contains the DMA channel device
+ */
+void dma_chan_cleanup(struct kref *kref)
+{
+       struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
+       chan->device->device_free_chan_resources(chan);
+       chan->client = NULL;
+       kref_put(&chan->device->refcount, dma_async_device_cleanup);
+}
+
+static void dma_chan_free_rcu(struct rcu_head *rcu)
+{
+       struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu);
+       int bias = 0x7FFFFFFF;
+       int i;
+       for_each_possible_cpu(i)
+               bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount);
+       atomic_sub(bias, &chan->refcount.refcount);
+       kref_put(&chan->refcount, dma_chan_cleanup);
+}
+
+static void dma_client_chan_free(struct dma_chan *chan)
+{
+       atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
+       chan->slow_ref = 1;
+       call_rcu(&chan->rcu, dma_chan_free_rcu);
+}
+
+/**
+ * dma_chans_rebalance - reallocate channels to clients
+ *
+ * When the number of DMA channel in the system changes,
+ * channels need to be rebalanced among clients.
+ */
+static void dma_chans_rebalance(void)
+{
+       struct dma_client *client;
+       struct dma_chan *chan;
+       unsigned long flags;
+
+       mutex_lock(&dma_list_mutex);
+
+       list_for_each_entry(client, &dma_client_list, global_node) {
+               while (client->chans_desired > client->chan_count) {
+                       chan = dma_client_chan_alloc(client);
+                       if (!chan)
+                               break;
+                       client->chan_count++;
+                       client->event_callback(client,
+                                              chan,
+                                              DMA_RESOURCE_ADDED);
+               }
+               while (client->chans_desired < client->chan_count) {
+                       spin_lock_irqsave(&client->lock, flags);
+                       chan = list_entry(client->channels.next,
+                                         struct dma_chan,
+                                         client_node);
+                       list_del_rcu(&chan->client_node);
+                       spin_unlock_irqrestore(&client->lock, flags);
+                       client->chan_count--;
+                       client->event_callback(client,
+                                              chan,
+                                              DMA_RESOURCE_REMOVED);
+                       dma_client_chan_free(chan);
+               }
+       }
+
+       mutex_unlock(&dma_list_mutex);
+}
+
+/**
+ * dma_async_client_register - allocate and register a &dma_client
+ * @event_callback: callback for notification of channel addition/removal
+ */
+struct dma_client *dma_async_client_register(dma_event_callback event_callback)
+{
+       struct dma_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (!client)
+               return NULL;
+
+       INIT_LIST_HEAD(&client->channels);
+       spin_lock_init(&client->lock);
+       client->chans_desired = 0;
+       client->chan_count = 0;
+       client->event_callback = event_callback;
+
+       mutex_lock(&dma_list_mutex);
+       list_add_tail(&client->global_node, &dma_client_list);
+       mutex_unlock(&dma_list_mutex);
+
+       return client;
+}
+
+/**
+ * dma_async_client_unregister - unregister a client and free the &dma_client
+ * @client: &dma_client to free
+ *
+ * Force frees any allocated DMA channels, frees the &dma_client memory
+ */
+void dma_async_client_unregister(struct dma_client *client)
+{
+       struct dma_chan *chan;
+
+       if (!client)
+               return;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(chan, &client->channels, client_node)
+               dma_client_chan_free(chan);
+       rcu_read_unlock();
+
+       mutex_lock(&dma_list_mutex);
+       list_del(&client->global_node);
+       mutex_unlock(&dma_list_mutex);
+
+       kfree(client);
+       dma_chans_rebalance();
+}
+
+/**
+ * dma_async_client_chan_request - request DMA channels
+ * @client: &dma_client
+ * @number: count of DMA channels requested
+ *
+ * Clients call dma_async_client_chan_request() to specify how many
+ * DMA channels they need, 0 to free all currently allocated.
+ * The resulting allocations/frees are indicated to the client via the
+ * event callback.
+ */
+void dma_async_client_chan_request(struct dma_client *client,
+                       unsigned int number)
+{
+       client->chans_desired = number;
+       dma_chans_rebalance();
+}
+
+/**
+ * dma_async_device_register - registers DMA devices found
+ * @device: &dma_device
+ */
+int dma_async_device_register(struct dma_device *device)
+{
+       static int id;
+       int chancnt = 0;
+       struct dma_chan* chan;
+
+       if (!device)
+               return -ENODEV;
+
+       init_completion(&device->done);
+       kref_init(&device->refcount);
+       device->dev_id = id++;
+
+       /* represent channels in sysfs. Probably want devs too */
+       list_for_each_entry(chan, &device->channels, device_node) {
+               chan->local = alloc_percpu(typeof(*chan->local));
+               if (chan->local == NULL)
+                       continue;
+
+               chan->chan_id = chancnt++;
+               chan->class_dev.class = &dma_devclass;
+               chan->class_dev.dev = NULL;
+               snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
+                        device->dev_id, chan->chan_id);
+
+               kref_get(&device->refcount);
+               class_device_register(&chan->class_dev);
+       }
+
+       mutex_lock(&dma_list_mutex);
+       list_add_tail(&device->global_node, &dma_device_list);
+       mutex_unlock(&dma_list_mutex);
+
+       dma_chans_rebalance();
+
+       return 0;
+}
+
+/**
+ * dma_async_device_cleanup - function called when all references are released
+ * @kref: kernel reference object
+ */
+static void dma_async_device_cleanup(struct kref *kref)
+{
+       struct dma_device *device;
+
+       device = container_of(kref, struct dma_device, refcount);
+       complete(&device->done);
+}
+
+/**
+ * dma_async_device_unregister - unregisters DMA devices
+ * @device: &dma_device
+ */
+void dma_async_device_unregister(struct dma_device *device)
+{
+       struct dma_chan *chan;
+       unsigned long flags;
+
+       mutex_lock(&dma_list_mutex);
+       list_del(&device->global_node);
+       mutex_unlock(&dma_list_mutex);
+
+       list_for_each_entry(chan, &device->channels, device_node) {
+               if (chan->client) {
+                       spin_lock_irqsave(&chan->client->lock, flags);
+                       list_del(&chan->client_node);
+                       chan->client->chan_count--;
+                       spin_unlock_irqrestore(&chan->client->lock, flags);
+                       chan->client->event_callback(chan->client,
+                                                    chan,
+                                                    DMA_RESOURCE_REMOVED);
+                       dma_client_chan_free(chan);
+               }
+               class_device_unregister(&chan->class_dev);
+       }
+       dma_chans_rebalance();
+
+       kref_put(&device->refcount, dma_async_device_cleanup);
+       wait_for_completion(&device->done);
+}
+
+static int __init dma_bus_init(void)
+{
+       mutex_init(&dma_list_mutex);
+       return class_register(&dma_devclass);
+}
+
+subsys_initcall(dma_bus_init);
+
+EXPORT_SYMBOL(dma_async_client_register);
+EXPORT_SYMBOL(dma_async_client_unregister);
+EXPORT_SYMBOL(dma_async_client_chan_request);
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+EXPORT_SYMBOL(dma_async_memcpy_complete);
+EXPORT_SYMBOL(dma_async_memcpy_issue_pending);
+EXPORT_SYMBOL(dma_async_device_register);
+EXPORT_SYMBOL(dma_async_device_unregister);
+EXPORT_SYMBOL(dma_chan_cleanup);
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
new file mode 100644 (file)
index 0000000..dbd4d6c
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous
+ * copy operations.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include "ioatdma.h"
+#include "ioatdma_io.h"
+#include "ioatdma_registers.h"
+#include "ioatdma_hw.h"
+
+#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
+#define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
+#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+
+/* internal functions */
+static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void __devexit ioat_remove(struct pci_dev *pdev);
+
+static int enumerate_dma_channels(struct ioat_device *device)
+{
+       u8 xfercap_scale;
+       u32 xfercap;
+       int i;
+       struct ioat_dma_chan *ioat_chan;
+
+       device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET);
+       xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET);
+       xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+
+       for (i = 0; i < device->common.chancnt; i++) {
+               ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
+               if (!ioat_chan) {
+                       device->common.chancnt = i;
+                       break;
+               }
+
+               ioat_chan->device = device;
+               ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
+               ioat_chan->xfercap = xfercap;
+               spin_lock_init(&ioat_chan->cleanup_lock);
+               spin_lock_init(&ioat_chan->desc_lock);
+               INIT_LIST_HEAD(&ioat_chan->free_desc);
+               INIT_LIST_HEAD(&ioat_chan->used_desc);
+               /* This should be made common somewhere in dmaengine.c */
+               ioat_chan->common.device = &device->common;
+               ioat_chan->common.client = NULL;
+               list_add_tail(&ioat_chan->common.device_node,
+                             &device->common.channels);
+       }
+       return device->common.chancnt;
+}
+
+static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
+       struct ioat_dma_chan *ioat_chan,
+       int flags)
+{
+       struct ioat_dma_descriptor *desc;
+       struct ioat_desc_sw *desc_sw;
+       struct ioat_device *ioat_device;
+       dma_addr_t phys;
+
+       ioat_device = to_ioat_device(ioat_chan->common.device);
+       desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys);
+       if (unlikely(!desc))
+               return NULL;
+
+       desc_sw = kzalloc(sizeof(*desc_sw), flags);
+       if (unlikely(!desc_sw)) {
+               pci_pool_free(ioat_device->dma_pool, desc, phys);
+               return NULL;
+       }
+
+       memset(desc, 0, sizeof(*desc));
+       desc_sw->hw = desc;
+       desc_sw->phys = phys;
+
+       return desc_sw;
+}
+
+#define INITIAL_IOAT_DESC_COUNT 128
+
+static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan);
+
+/* returns the actual number of allocated descriptors */
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       struct ioat_desc_sw *desc = NULL;
+       u16 chanctrl;
+       u32 chanerr;
+       int i;
+       LIST_HEAD(tmp_list);
+
+       /*
+        * In-use bit automatically set by reading chanctrl
+        * If 0, we got it, if 1, someone else did
+        */
+       chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+       if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE)
+               return -EBUSY;
+
+        /* Setup register to interrupt and write completion status on error */
+       chanctrl = IOAT_CHANCTRL_CHANNEL_IN_USE |
+               IOAT_CHANCTRL_ERR_INT_EN |
+               IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
+               IOAT_CHANCTRL_ERR_COMPLETION_EN;
+        ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+
+       chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET);
+       if (chanerr) {
+               printk("IOAT: CHANERR = %x, clearing\n", chanerr);
+               ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr);
+       }
+
+       /* Allocate descriptors */
+       for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) {
+               desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+               if (!desc) {
+                       printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i);
+                       break;
+               }
+               list_add_tail(&desc->node, &tmp_list);
+       }
+       spin_lock_bh(&ioat_chan->desc_lock);
+       list_splice(&tmp_list, &ioat_chan->free_desc);
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       /* allocate a completion writeback area */
+       /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
+       ioat_chan->completion_virt =
+               pci_pool_alloc(ioat_chan->device->completion_pool,
+                              GFP_KERNEL,
+                              &ioat_chan->completion_addr);
+       memset(ioat_chan->completion_virt, 0,
+              sizeof(*ioat_chan->completion_virt));
+       ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW,
+                      ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF);
+       ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH,
+                      ((u64) ioat_chan->completion_addr) >> 32);
+
+       ioat_start_null_desc(ioat_chan);
+       return i;
+}
+
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
+
+static void ioat_dma_free_chan_resources(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       struct ioat_device *ioat_device = to_ioat_device(chan->device);
+       struct ioat_desc_sw *desc, *_desc;
+       u16 chanctrl;
+       int in_use_descs = 0;
+
+       ioat_dma_memcpy_cleanup(ioat_chan);
+
+       ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
+
+       spin_lock_bh(&ioat_chan->desc_lock);
+       list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
+               in_use_descs++;
+               list_del(&desc->node);
+               pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+               kfree(desc);
+       }
+       list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
+               list_del(&desc->node);
+               pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+               kfree(desc);
+       }
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       pci_pool_free(ioat_device->completion_pool,
+                     ioat_chan->completion_virt,
+                     ioat_chan->completion_addr);
+
+       /* one is ok since we left it on there on purpose */
+       if (in_use_descs > 1)
+               printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n",
+                       in_use_descs - 1);
+
+       ioat_chan->last_completion = ioat_chan->completion_addr = 0;
+
+       /* Tell hw the chan is free */
+       chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+       chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE;
+       ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+}
+
+/**
+ * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
+ * @ioat_chan: IOAT DMA channel handle
+ * @dest: DMA destination address
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
+                                       dma_addr_t dest,
+                                       dma_addr_t src,
+                                       size_t len)
+{
+       struct ioat_desc_sw *first;
+       struct ioat_desc_sw *prev;
+       struct ioat_desc_sw *new;
+       dma_cookie_t cookie;
+       LIST_HEAD(new_chain);
+       u32 copy;
+       size_t orig_len;
+       dma_addr_t orig_src, orig_dst;
+       unsigned int desc_count = 0;
+       unsigned int append = 0;
+
+       if (!ioat_chan || !dest || !src)
+               return -EFAULT;
+
+       if (!len)
+               return ioat_chan->common.cookie;
+
+       orig_len = len;
+       orig_src = src;
+       orig_dst = dest;
+
+       first = NULL;
+       prev = NULL;
+
+       spin_lock_bh(&ioat_chan->desc_lock);
+
+       while (len) {
+               if (!list_empty(&ioat_chan->free_desc)) {
+                       new = to_ioat_desc(ioat_chan->free_desc.next);
+                       list_del(&new->node);
+               } else {
+                       /* try to get another desc */
+                       new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+                       /* will this ever happen? */
+                       /* TODO add upper limit on these */
+                       BUG_ON(!new);
+               }
+
+               copy = min((u32) len, ioat_chan->xfercap);
+
+               new->hw->size = copy;
+               new->hw->ctl = 0;
+               new->hw->src_addr = src;
+               new->hw->dst_addr = dest;
+               new->cookie = 0;
+
+               /* chain together the physical address list for the HW */
+               if (!first)
+                       first = new;
+               else
+                       prev->hw->next = (u64) new->phys;
+
+               prev = new;
+
+               len  -= copy;
+               dest += copy;
+               src  += copy;
+
+               list_add_tail(&new->node, &new_chain);
+               desc_count++;
+       }
+       new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+       new->hw->next = 0;
+
+       /* cookie incr and addition to used_list must be atomic */
+
+       cookie = ioat_chan->common.cookie;
+       cookie++;
+       if (cookie < 0)
+               cookie = 1;
+       ioat_chan->common.cookie = new->cookie = cookie;
+
+       pci_unmap_addr_set(new, src, orig_src);
+       pci_unmap_addr_set(new, dst, orig_dst);
+       pci_unmap_len_set(new, src_len, orig_len);
+       pci_unmap_len_set(new, dst_len, orig_len);
+
+       /* write address into NextDescriptor field of last desc in chain */
+       to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
+       list_splice_init(&new_chain, ioat_chan->used_desc.prev);
+
+       ioat_chan->pending += desc_count;
+       if (ioat_chan->pending >= 20) {
+               append = 1;
+               ioat_chan->pending = 0;
+       }
+
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       if (append)
+               ioatdma_chan_write8(ioat_chan,
+                                   IOAT_CHANCMD_OFFSET,
+                                   IOAT_CHANCMD_APPEND);
+       return cookie;
+}
+
+/**
+ * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
+ * @chan: IOAT DMA channel handle
+ * @dest: DMA destination address
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
+                                               void *dest,
+                                               void *src,
+                                               size_t len)
+{
+       dma_addr_t dest_addr;
+       dma_addr_t src_addr;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       dest_addr = pci_map_single(ioat_chan->device->pdev,
+               dest, len, PCI_DMA_FROMDEVICE);
+       src_addr = pci_map_single(ioat_chan->device->pdev,
+               src, len, PCI_DMA_TODEVICE);
+
+       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
+ * @chan: IOAT DMA channel handle
+ * @page: pointer to the page to copy to
+ * @offset: offset into that page
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
+                                              struct page *page,
+                                              unsigned int offset,
+                                              void *src,
+                                              size_t len)
+{
+       dma_addr_t dest_addr;
+       dma_addr_t src_addr;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       dest_addr = pci_map_page(ioat_chan->device->pdev,
+               page, offset, len, PCI_DMA_FROMDEVICE);
+       src_addr = pci_map_single(ioat_chan->device->pdev,
+               src, len, PCI_DMA_TODEVICE);
+
+       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
+ * @chan: IOAT DMA channel handle
+ * @dest_pg: pointer to the page to copy to
+ * @dest_off: offset into that page
+ * @src_pg: pointer to the page to copy from
+ * @src_off: offset into that page
+ * @len: transaction length in bytes. This is guaranteed not to make a copy
+ *      across a page boundary.
+ */
+
+static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
+                                             struct page *dest_pg,
+                                             unsigned int dest_off,
+                                             struct page *src_pg,
+                                             unsigned int src_off,
+                                             size_t len)
+{
+       dma_addr_t dest_addr;
+       dma_addr_t src_addr;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       dest_addr = pci_map_page(ioat_chan->device->pdev,
+               dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
+       src_addr = pci_map_page(ioat_chan->device->pdev,
+               src_pg, src_off, len, PCI_DMA_TODEVICE);
+
+       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
+ * @chan: DMA channel handle
+ */
+
+static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       if (ioat_chan->pending != 0) {
+               ioat_chan->pending = 0;
+               ioatdma_chan_write8(ioat_chan,
+                                   IOAT_CHANCMD_OFFSET,
+                                   IOAT_CHANCMD_APPEND);
+       }
+}
+
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
+{
+       unsigned long phys_complete;
+       struct ioat_desc_sw *desc, *_desc;
+       dma_cookie_t cookie = 0;
+
+       prefetch(chan->completion_virt);
+
+       if (!spin_trylock(&chan->cleanup_lock))
+               return;
+
+       /* The completion writeback can happen at any time,
+          so reads by the driver need to be atomic operations
+          The descriptor physical addresses are limited to 32-bits
+          when the CPU can only do a 32-bit mov */
+
+#if (BITS_PER_LONG == 64)
+       phys_complete =
+       chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+       phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+       if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
+               IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
+               printk("IOAT: Channel halted, chanerr = %x\n",
+                       ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET));
+
+               /* TODO do something to salvage the situation */
+       }
+
+       if (phys_complete == chan->last_completion) {
+               spin_unlock(&chan->cleanup_lock);
+               return;
+       }
+
+       spin_lock_bh(&chan->desc_lock);
+       list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) {
+
+               /*
+                * Incoming DMA requests may use multiple descriptors, due to
+                * exceeding xfercap, perhaps. If so, only the last one will
+                * have a cookie, and require unmapping.
+                */
+               if (desc->cookie) {
+                       cookie = desc->cookie;
+
+                       /* yes we are unmapping both _page and _single alloc'd
+                          regions with unmap_page. Is this *really* that bad?
+                       */
+                       pci_unmap_page(chan->device->pdev,
+                                       pci_unmap_addr(desc, dst),
+                                       pci_unmap_len(desc, dst_len),
+                                       PCI_DMA_FROMDEVICE);
+                       pci_unmap_page(chan->device->pdev,
+                                       pci_unmap_addr(desc, src),
+                                       pci_unmap_len(desc, src_len),
+                                       PCI_DMA_TODEVICE);
+               }
+
+               if (desc->phys != phys_complete) {
+                       /* a completed entry, but not the last, so cleanup */
+                       list_del(&desc->node);
+                       list_add_tail(&desc->node, &chan->free_desc);
+               } else {
+                       /* last used desc. Do not remove, so we can append from
+                          it, but don't look at it next time, either */
+                       desc->cookie = 0;
+
+                       /* TODO check status bits? */
+                       break;
+               }
+       }
+
+       spin_unlock_bh(&chan->desc_lock);
+
+       chan->last_completion = phys_complete;
+       if (cookie != 0)
+               chan->completed_cookie = cookie;
+
+       spin_unlock(&chan->cleanup_lock);
+}
+
+/**
+ * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+ * @cookie: DMA transaction identifier
+ * @done: if not %NULL, updated with last completed transaction
+ * @used: if not %NULL, updated with last used transaction
+ */
+
+static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
+                                            dma_cookie_t cookie,
+                                            dma_cookie_t *done,
+                                            dma_cookie_t *used)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       dma_cookie_t last_used;
+       dma_cookie_t last_complete;
+       enum dma_status ret;
+
+       last_used = chan->cookie;
+       last_complete = ioat_chan->completed_cookie;
+
+       if (done)
+               *done= last_complete;
+       if (used)
+               *used = last_used;
+
+       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       if (ret == DMA_SUCCESS)
+               return ret;
+
+       ioat_dma_memcpy_cleanup(ioat_chan);
+
+       last_used = chan->cookie;
+       last_complete = ioat_chan->completed_cookie;
+
+       if (done)
+               *done= last_complete;
+       if (used)
+               *used = last_used;
+
+       return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/* PCI API */
+
+static struct pci_device_id ioat_pci_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+       { 0, }
+};
+
+static struct pci_driver ioat_pci_drv = {
+       .name   = "ioatdma",
+       .id_table = ioat_pci_tbl,
+       .probe  = ioat_probe,
+       .remove = __devexit_p(ioat_remove),
+};
+
+static irqreturn_t ioat_do_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+       struct ioat_device *instance = data;
+       unsigned long attnstatus;
+       u8 intrctrl;
+
+       intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET);
+
+       if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
+               return IRQ_NONE;
+
+       if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
+               ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+               return IRQ_NONE;
+       }
+
+       attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET);
+
+       printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
+
+       ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+       return IRQ_HANDLED;
+}
+
+static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan)
+{
+       struct ioat_desc_sw *desc;
+
+       spin_lock_bh(&ioat_chan->desc_lock);
+
+       if (!list_empty(&ioat_chan->free_desc)) {
+               desc = to_ioat_desc(ioat_chan->free_desc.next);
+               list_del(&desc->node);
+       } else {
+               /* try to get another desc */
+               spin_unlock_bh(&ioat_chan->desc_lock);
+               desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+               spin_lock_bh(&ioat_chan->desc_lock);
+               /* will this ever happen? */
+               BUG_ON(!desc);
+       }
+
+       desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+       desc->hw->next = 0;
+
+       list_add_tail(&desc->node, &ioat_chan->used_desc);
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+#if (BITS_PER_LONG == 64)
+       ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys);
+#else
+       ioatdma_chan_write32(ioat_chan,
+                            IOAT_CHAINADDR_OFFSET_LOW,
+                            (u32) desc->phys);
+       ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0);
+#endif
+       ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START);
+}
+
+/*
+ * Perform a IOAT transaction to verify the HW works.
+ */
+#define IOAT_TEST_SIZE 2000
+
+static int ioat_self_test(struct ioat_device *device)
+{
+       int i;
+       u8 *src;
+       u8 *dest;
+       struct dma_chan *dma_chan;
+       dma_cookie_t cookie;
+       int err = 0;
+
+       src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+       if (!src)
+               return -ENOMEM;
+       dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+       if (!dest) {
+               kfree(src);
+               return -ENOMEM;
+       }
+
+       /* Fill in src buffer */
+       for (i = 0; i < IOAT_TEST_SIZE; i++)
+               src[i] = (u8)i;
+
+       /* Start copy, using first DMA channel */
+       dma_chan = container_of(device->common.channels.next,
+                               struct dma_chan,
+                               device_node);
+       if (ioat_dma_alloc_chan_resources(dma_chan) < 1) {
+               err = -ENODEV;
+               goto out;
+       }
+
+       cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+       ioat_dma_memcpy_issue_pending(dma_chan);
+       msleep(1);
+
+       if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+               printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+       if (memcmp(src, dest, IOAT_TEST_SIZE)) {
+               printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+free_resources:
+       ioat_dma_free_chan_resources(dma_chan);
+out:
+       kfree(src);
+       kfree(dest);
+       return err;
+}
+
+static int __devinit ioat_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+       int err;
+       unsigned long mmio_start, mmio_len;
+       void *reg_base;
+       struct ioat_device *device;
+
+       err = pci_enable_device(pdev);
+       if (err)
+               goto err_enable_device;
+
+       err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+       if (err)
+               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (err)
+               goto err_set_dma_mask;
+
+       err = pci_request_regions(pdev, ioat_pci_drv.name);
+       if (err)
+               goto err_request_regions;
+
+       mmio_start = pci_resource_start(pdev, 0);
+       mmio_len = pci_resource_len(pdev, 0);
+
+       reg_base = ioremap(mmio_start, mmio_len);
+       if (!reg_base) {
+               err = -ENOMEM;
+               goto err_ioremap;
+       }
+
+       device = kzalloc(sizeof(*device), GFP_KERNEL);
+       if (!device) {
+               err = -ENOMEM;
+               goto err_kzalloc;
+       }
+
+       /* DMA coherent memory pool for DMA descriptor allocations */
+       device->dma_pool = pci_pool_create("dma_desc_pool", pdev,
+               sizeof(struct ioat_dma_descriptor), 64, 0);
+       if (!device->dma_pool) {
+               err = -ENOMEM;
+               goto err_dma_pool;
+       }
+
+       device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES);
+       if (!device->completion_pool) {
+               err = -ENOMEM;
+               goto err_completion_pool;
+       }
+
+       device->pdev = pdev;
+       pci_set_drvdata(pdev, device);
+#ifdef CONFIG_PCI_MSI
+       if (pci_enable_msi(pdev) == 0) {
+               device->msi = 1;
+       } else {
+               device->msi = 0;
+       }
+#endif
+       err = request_irq(pdev->irq, &ioat_do_interrupt, IRQF_SHARED, "ioat",
+               device);
+       if (err)
+               goto err_irq;
+
+       device->reg_base = reg_base;
+
+       ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN);
+       pci_set_master(pdev);
+
+       INIT_LIST_HEAD(&device->common.channels);
+       enumerate_dma_channels(device);
+
+       device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
+       device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
+       device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
+       device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
+       device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
+       device->common.device_memcpy_complete = ioat_dma_is_complete;
+       device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+       printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
+               device->common.chancnt);
+
+       err = ioat_self_test(device);
+       if (err)
+               goto err_self_test;
+
+       dma_async_device_register(&device->common);
+
+       return 0;
+
+err_self_test:
+err_irq:
+       pci_pool_destroy(device->completion_pool);
+err_completion_pool:
+       pci_pool_destroy(device->dma_pool);
+err_dma_pool:
+       kfree(device);
+err_kzalloc:
+       iounmap(reg_base);
+err_ioremap:
+       pci_release_regions(pdev);
+err_request_regions:
+err_set_dma_mask:
+       pci_disable_device(pdev);
+err_enable_device:
+       return err;
+}
+
+static void __devexit ioat_remove(struct pci_dev *pdev)
+{
+       struct ioat_device *device;
+       struct dma_chan *chan, *_chan;
+       struct ioat_dma_chan *ioat_chan;
+
+       device = pci_get_drvdata(pdev);
+       dma_async_device_unregister(&device->common);
+
+       free_irq(device->pdev->irq, device);
+#ifdef CONFIG_PCI_MSI
+       if (device->msi)
+               pci_disable_msi(device->pdev);
+#endif
+       pci_pool_destroy(device->dma_pool);
+       pci_pool_destroy(device->completion_pool);
+       iounmap(device->reg_base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) {
+               ioat_chan = to_ioat_chan(chan);
+               list_del(&chan->device_node);
+               kfree(ioat_chan);
+       }
+       kfree(device);
+}
+
+/* MODULE API */
+MODULE_VERSION("1.7");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
+
+static int __init ioat_init_module(void)
+{
+       /* it's currently unsafe to unload this module */
+       /* if forced, worst case is that rmmod hangs */
+       __unsafe(THIS_MODULE);
+
+       return pci_register_driver(&ioat_pci_drv);
+}
+
+module_init(ioat_init_module);
+
+static void __exit ioat_exit_module(void)
+{
+       pci_unregister_driver(&ioat_pci_drv);
+}
+
+module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
new file mode 100644 (file)
index 0000000..a5d3b36
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef IOATDMA_H
+#define IOATDMA_H
+
+#include <linux/dmaengine.h>
+#include "ioatdma_hw.h"
+#include <linux/init.h>
+#include <linux/dmapool.h>
+#include <linux/cache.h>
+#include <linux/pci_ids.h>
+
+#define IOAT_LOW_COMPLETION_MASK       0xffffffc0
+
+extern struct list_head dma_device_list;
+extern struct list_head dma_client_list;
+
+/**
+ * struct ioat_device - internal representation of a IOAT device
+ * @pdev: PCI-Express device
+ * @reg_base: MMIO register space base address
+ * @dma_pool: for allocating DMA descriptors
+ * @common: embedded struct dma_device
+ * @msi: Message Signaled Interrupt number
+ */
+
+struct ioat_device {
+       struct pci_dev *pdev;
+       void *reg_base;
+       struct pci_pool *dma_pool;
+       struct pci_pool *completion_pool;
+
+       struct dma_device common;
+       u8 msi;
+};
+
+/**
+ * struct ioat_dma_chan - internal representation of a DMA channel
+ * @device:
+ * @reg_base:
+ * @sw_in_use:
+ * @completion:
+ * @completion_low:
+ * @completion_high:
+ * @completed_cookie: last cookie seen completed on cleanup
+ * @cookie: value of last cookie given to client
+ * @last_completion:
+ * @xfercap:
+ * @desc_lock:
+ * @free_desc:
+ * @used_desc:
+ * @resource:
+ * @device_node:
+ */
+
+struct ioat_dma_chan {
+
+       void *reg_base;
+
+       dma_cookie_t completed_cookie;
+       unsigned long last_completion;
+
+       u32 xfercap;    /* XFERCAP register value expanded out */
+
+       spinlock_t cleanup_lock;
+       spinlock_t desc_lock;
+       struct list_head free_desc;
+       struct list_head used_desc;
+
+       int pending;
+
+       struct ioat_device *device;
+       struct dma_chan common;
+
+       dma_addr_t completion_addr;
+       union {
+               u64 full; /* HW completion writeback */
+               struct {
+                       u32 low;
+                       u32 high;
+               };
+       } *completion_virt;
+};
+
+/* wrapper around hardware descriptor format + additional software fields */
+
+/**
+ * struct ioat_desc_sw - wrapper around hardware descriptor
+ * @hw: hardware DMA descriptor
+ * @node:
+ * @cookie:
+ * @phys:
+ */
+
+struct ioat_desc_sw {
+       struct ioat_dma_descriptor *hw;
+       struct list_head node;
+       dma_cookie_t cookie;
+       dma_addr_t phys;
+       DECLARE_PCI_UNMAP_ADDR(src)
+       DECLARE_PCI_UNMAP_LEN(src_len)
+       DECLARE_PCI_UNMAP_ADDR(dst)
+       DECLARE_PCI_UNMAP_LEN(dst_len)
+};
+
+#endif /* IOATDMA_H */
+
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
new file mode 100644 (file)
index 0000000..4d7a128
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef _IOAT_HW_H_
+#define _IOAT_HW_H_
+
+/* PCI Configuration Space Values */
+#define IOAT_PCI_VID                   0x8086
+#define IOAT_PCI_DID                   0x1A38
+#define IOAT_PCI_RID                   0x00
+#define IOAT_PCI_SVID                  0x8086
+#define IOAT_PCI_SID                   0x8086
+#define IOAT_VER                       0x12    /* Version 1.2 */
+
+struct ioat_dma_descriptor {
+       uint32_t        size;
+       uint32_t        ctl;
+       uint64_t        src_addr;
+       uint64_t        dst_addr;
+       uint64_t        next;
+       uint64_t        rsv1;
+       uint64_t        rsv2;
+       uint64_t        user1;
+       uint64_t        user2;
+};
+
+#define IOAT_DMA_DESCRIPTOR_CTL_INT_GN 0x00000001
+#define IOAT_DMA_DESCRIPTOR_CTL_SRC_SN 0x00000002
+#define IOAT_DMA_DESCRIPTOR_CTL_DST_SN 0x00000004
+#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008
+#define IOAT_DMA_DESCRIPTOR_CTL_FRAME  0x00000010
+#define IOAT_DMA_DESCRIPTOR_NUL                0x00000020
+#define IOAT_DMA_DESCRIPTOR_OPCODE     0xFF000000
+
+#endif
diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h
new file mode 100644 (file)
index 0000000..c0b4bf6
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef IOATDMA_IO_H
+#define IOATDMA_IO_H
+
+#include <asm/io.h>
+
+/*
+ * device and per-channel MMIO register read and write functions
+ * this is a lot of anoying inline functions, but it's typesafe
+ */
+
+static inline u8 ioatdma_read8(struct ioat_device *device,
+                               unsigned int offset)
+{
+       return readb(device->reg_base + offset);
+}
+
+static inline u16 ioatdma_read16(struct ioat_device *device,
+                                 unsigned int offset)
+{
+       return readw(device->reg_base + offset);
+}
+
+static inline u32 ioatdma_read32(struct ioat_device *device,
+                                 unsigned int offset)
+{
+       return readl(device->reg_base + offset);
+}
+
+static inline void ioatdma_write8(struct ioat_device *device,
+                                  unsigned int offset, u8 value)
+{
+       writeb(value, device->reg_base + offset);
+}
+
+static inline void ioatdma_write16(struct ioat_device *device,
+                                   unsigned int offset, u16 value)
+{
+       writew(value, device->reg_base + offset);
+}
+
+static inline void ioatdma_write32(struct ioat_device *device,
+                                   unsigned int offset, u32 value)
+{
+       writel(value, device->reg_base + offset);
+}
+
+static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan,
+                                    unsigned int offset)
+{
+       return readb(chan->reg_base + offset);
+}
+
+static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+       return readw(chan->reg_base + offset);
+}
+
+static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+       return readl(chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan,
+                                       unsigned int offset, u8 value)
+{
+       writeb(value, chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u16 value)
+{
+       writew(value, chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u32 value)
+{
+       writel(value, chan->reg_base + offset);
+}
+
+#if (BITS_PER_LONG == 64)
+static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+       return readq(chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u64 value)
+{
+       writeq(value, chan->reg_base + offset);
+}
+#endif
+
+#endif /* IOATDMA_IO_H */
+
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
new file mode 100644 (file)
index 0000000..a30c734
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef _IOAT_REGISTERS_H_
+#define _IOAT_REGISTERS_H_
+
+
+/* MMIO Device Registers */
+#define IOAT_CHANCNT_OFFSET                    0x00    /*  8-bit */
+
+#define IOAT_XFERCAP_OFFSET                    0x01    /*  8-bit */
+#define IOAT_XFERCAP_4KB                       12
+#define IOAT_XFERCAP_8KB                       13
+#define IOAT_XFERCAP_16KB                      14
+#define IOAT_XFERCAP_32KB                      15
+#define IOAT_XFERCAP_32GB                      0
+
+#define IOAT_GENCTRL_OFFSET                    0x02    /*  8-bit */
+#define IOAT_GENCTRL_DEBUG_EN                  0x01
+
+#define IOAT_INTRCTRL_OFFSET                   0x03    /*  8-bit */
+#define IOAT_INTRCTRL_MASTER_INT_EN            0x01    /* Master Interrupt Enable */
+#define IOAT_INTRCTRL_INT_STATUS               0x02    /* ATTNSTATUS -or- Channel Int */
+#define IOAT_INTRCTRL_INT                      0x04    /* INT_STATUS -and- MASTER_INT_EN */
+
+#define IOAT_ATTNSTATUS_OFFSET                 0x04    /* Each bit is a channel */
+
+#define IOAT_VER_OFFSET                                0x08    /*  8-bit */
+#define IOAT_VER_MAJOR_MASK                    0xF0
+#define IOAT_VER_MINOR_MASK                    0x0F
+#define GET_IOAT_VER_MAJOR(x)                  ((x) & IOAT_VER_MAJOR_MASK)
+#define GET_IOAT_VER_MINOR(x)                  ((x) & IOAT_VER_MINOR_MASK)
+
+#define IOAT_PERPORTOFFSET_OFFSET              0x0A    /* 16-bit */
+
+#define IOAT_INTRDELAY_OFFSET                  0x0C    /* 16-bit */
+#define IOAT_INTRDELAY_INT_DELAY_MASK          0x3FFF  /* Interrupt Delay Time */
+#define IOAT_INTRDELAY_COALESE_SUPPORT         0x8000  /* Interrupt Coalesing Supported */
+
+#define IOAT_DEVICE_STATUS_OFFSET              0x0E    /* 16-bit */
+#define IOAT_DEVICE_STATUS_DEGRADED_MODE       0x0001
+
+
+#define IOAT_CHANNEL_MMIO_SIZE                 0x80    /* Each Channel MMIO space is this size */
+
+/* DMA Channel Registers */
+#define IOAT_CHANCTRL_OFFSET                   0x00    /* 16-bit Channel Control Register */
+#define IOAT_CHANCTRL_CHANNEL_PRIORITY_MASK    0xF000
+#define IOAT_CHANCTRL_CHANNEL_IN_USE           0x0100
+#define IOAT_CHANCTRL_DESCRIPTOR_ADDR_SNOOP_CONTROL    0x0020
+#define IOAT_CHANCTRL_ERR_INT_EN               0x0010
+#define IOAT_CHANCTRL_ANY_ERR_ABORT_EN         0x0008
+#define IOAT_CHANCTRL_ERR_COMPLETION_EN                0x0004
+#define IOAT_CHANCTRL_INT_DISABLE              0x0001
+
+#define IOAT_DMA_COMP_OFFSET                   0x02    /* 16-bit DMA channel compatability */
+#define IOAT_DMA_COMP_V1                       0x0001  /* Compatability with DMA version 1 */
+
+#define IOAT_CHANSTS_OFFSET                    0x04    /* 64-bit Channel Status Register */
+#define IOAT_CHANSTS_OFFSET_LOW                        0x04
+#define IOAT_CHANSTS_OFFSET_HIGH               0x08
+#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL
+#define IOAT_CHANSTS_SOFT_ERR                  0x0000000000000010
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS       0x0000000000000007
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE        0x0
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE  0x1
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED     0x2
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED        0x3
+
+#define IOAT_CHAINADDR_OFFSET                  0x0C    /* 64-bit Descriptor Chain Address Register */
+#define IOAT_CHAINADDR_OFFSET_LOW              0x0C
+#define IOAT_CHAINADDR_OFFSET_HIGH             0x10
+
+#define IOAT_CHANCMD_OFFSET                    0x14    /*  8-bit DMA Channel Command Register */
+#define IOAT_CHANCMD_RESET                     0x20
+#define IOAT_CHANCMD_RESUME                    0x10
+#define IOAT_CHANCMD_ABORT                     0x08
+#define IOAT_CHANCMD_SUSPEND                   0x04
+#define IOAT_CHANCMD_APPEND                    0x02
+#define IOAT_CHANCMD_START                     0x01
+
+#define IOAT_CHANCMP_OFFSET                    0x18    /* 64-bit Channel Completion Address Register */
+#define IOAT_CHANCMP_OFFSET_LOW                        0x18
+#define IOAT_CHANCMP_OFFSET_HIGH               0x1C
+
+#define IOAT_CDAR_OFFSET                       0x20    /* 64-bit Current Descriptor Address Register */
+#define IOAT_CDAR_OFFSET_LOW                   0x20
+#define IOAT_CDAR_OFFSET_HIGH                  0x24
+
+#define IOAT_CHANERR_OFFSET                    0x28    /* 32-bit Channel Error Register */
+#define IOAT_CHANERR_DMA_TRANSFER_SRC_ADDR_ERR 0x0001
+#define IOAT_CHANERR_DMA_TRANSFER_DEST_ADDR_ERR        0x0002
+#define IOAT_CHANERR_NEXT_DESCRIPTOR_ADDR_ERR  0x0004
+#define IOAT_CHANERR_NEXT_DESCRIPTOR_ALIGNMENT_ERR     0x0008
+#define IOAT_CHANERR_CHAIN_ADDR_VALUE_ERR      0x0010
+#define IOAT_CHANERR_CHANCMD_ERR               0x0020
+#define IOAT_CHANERR_CHIPSET_UNCORRECTABLE_DATA_INTEGRITY_ERR  0x0040
+#define IOAT_CHANERR_DMA_UNCORRECTABLE_DATA_INTEGRITY_ERR      0x0080
+#define IOAT_CHANERR_READ_DATA_ERR             0x0100
+#define IOAT_CHANERR_WRITE_DATA_ERR            0x0200
+#define IOAT_CHANERR_DESCRIPTOR_CONTROL_ERR    0x0400
+#define IOAT_CHANERR_DESCRIPTOR_LENGTH_ERR     0x0800
+#define IOAT_CHANERR_COMPLETION_ADDR_ERR       0x1000
+#define IOAT_CHANERR_INT_CONFIGURATION_ERR     0x2000
+#define IOAT_CHANERR_SOFT_ERR                  0x4000
+
+#define IOAT_CHANERR_MASK_OFFSET               0x2C    /* 32-bit Channel Error Register */
+
+#endif /* _IOAT_REGISTERS_H_ */
diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c
new file mode 100644 (file)
index 0000000..d637555
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Portions based on net/core/datagram.c and copyrighted by their authors.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This code allows the net stack to make use of a DMA engine for
+ * skb to iovec copies.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/pagemap.h>
+#include <net/tcp.h> /* for memcpy_toiovec */
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+static int num_pages_spanned(struct iovec *iov)
+{
+       return
+       ((PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) -
+       ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT);
+}
+
+/*
+ * Pin down all the iovec pages needed for len bytes.
+ * Return a struct dma_pinned_list to keep track of pages pinned down.
+ *
+ * We are allocating a single chunk of memory, and then carving it up into
+ * 3 sections, the latter 2 whose size depends on the number of iovecs and the
+ * total number of pages, respectively.
+ */
+struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
+{
+       struct dma_pinned_list *local_list;
+       struct page **pages;
+       int i;
+       int ret;
+       int nr_iovecs = 0;
+       int iovec_len_used = 0;
+       int iovec_pages_used = 0;
+       long err;
+
+       /* don't pin down non-user-based iovecs */
+       if (segment_eq(get_fs(), KERNEL_DS))
+               return NULL;
+
+       /* determine how many iovecs/pages there are, up front */
+       do {
+               iovec_len_used += iov[nr_iovecs].iov_len;
+               iovec_pages_used += num_pages_spanned(&iov[nr_iovecs]);
+               nr_iovecs++;
+       } while (iovec_len_used < len);
+
+       /* single kmalloc for pinned list, page_list[], and the page arrays */
+       local_list = kmalloc(sizeof(*local_list)
+               + (nr_iovecs * sizeof (struct dma_page_list))
+               + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL);
+       if (!local_list) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* list of pages starts right after the page list array */
+       pages = (struct page **) &local_list->page_list[nr_iovecs];
+
+       for (i = 0; i < nr_iovecs; i++) {
+               struct dma_page_list *page_list = &local_list->page_list[i];
+
+               len -= iov[i].iov_len;
+
+               if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) {
+                       err = -EFAULT;
+                       goto unpin;
+               }
+
+               page_list->nr_pages = num_pages_spanned(&iov[i]);
+               page_list->base_address = iov[i].iov_base;
+
+               page_list->pages = pages;
+               pages += page_list->nr_pages;
+
+               /* pin pages down */
+               down_read(&current->mm->mmap_sem);
+               ret = get_user_pages(
+                       current,
+                       current->mm,
+                       (unsigned long) iov[i].iov_base,
+                       page_list->nr_pages,
+                       1,      /* write */
+                       0,      /* force */
+                       page_list->pages,
+                       NULL);
+               up_read(&current->mm->mmap_sem);
+
+               if (ret != page_list->nr_pages) {
+                       err = -ENOMEM;
+                       goto unpin;
+               }
+
+               local_list->nr_iovecs = i + 1;
+       }
+
+       return local_list;
+
+unpin:
+       dma_unpin_iovec_pages(local_list);
+out:
+       return ERR_PTR(err);
+}
+
+void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list)
+{
+       int i, j;
+
+       if (!pinned_list)
+               return;
+
+       for (i = 0; i < pinned_list->nr_iovecs; i++) {
+               struct dma_page_list *page_list = &pinned_list->page_list[i];
+               for (j = 0; j < page_list->nr_pages; j++) {
+                       set_page_dirty_lock(page_list->pages[j]);
+                       page_cache_release(page_list->pages[j]);
+               }
+       }
+
+       kfree(pinned_list);
+}
+
+static dma_cookie_t dma_memcpy_to_kernel_iovec(struct dma_chan *chan, struct
+       iovec *iov, unsigned char *kdata, size_t len)
+{
+       dma_cookie_t dma_cookie = 0;
+
+       while (len > 0) {
+               if (iov->iov_len) {
+                       int copy = min_t(unsigned int, iov->iov_len, len);
+                       dma_cookie = dma_async_memcpy_buf_to_buf(
+                                       chan,
+                                       iov->iov_base,
+                                       kdata,
+                                       copy);
+                       kdata += copy;
+                       len -= copy;
+                       iov->iov_len -= copy;
+                       iov->iov_base += copy;
+               }
+               iov++;
+       }
+
+       return dma_cookie;
+}
+
+/*
+ * We have already pinned down the pages we will be using in the iovecs.
+ * Each entry in iov array has corresponding entry in pinned_list->page_list.
+ * Using array indexing to keep iov[] and page_list[] in sync.
+ * Initial elements in iov array's iov->iov_len will be 0 if already copied into
+ *   by another call.
+ * iov array length remaining guaranteed to be bigger than len.
+ */
+dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len)
+{
+       int iov_byte_offset;
+       int copy;
+       dma_cookie_t dma_cookie = 0;
+       int iovec_idx;
+       int page_idx;
+
+       if (!chan)
+               return memcpy_toiovec(iov, kdata, len);
+
+       /* -> kernel copies (e.g. smbfs) */
+       if (!pinned_list)
+               return dma_memcpy_to_kernel_iovec(chan, iov, kdata, len);
+
+       iovec_idx = 0;
+       while (iovec_idx < pinned_list->nr_iovecs) {
+               struct dma_page_list *page_list;
+
+               /* skip already used-up iovecs */
+               while (!iov[iovec_idx].iov_len)
+                       iovec_idx++;
+
+               page_list = &pinned_list->page_list[iovec_idx];
+
+               iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK);
+               page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK)
+                        - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT;
+
+               /* break up copies to not cross page boundary */
+               while (iov[iovec_idx].iov_len) {
+                       copy = min_t(int, PAGE_SIZE - iov_byte_offset, len);
+                       copy = min_t(int, copy, iov[iovec_idx].iov_len);
+
+                       dma_cookie = dma_async_memcpy_buf_to_pg(chan,
+                                       page_list->pages[page_idx],
+                                       iov_byte_offset,
+                                       kdata,
+                                       copy);
+
+                       len -= copy;
+                       iov[iovec_idx].iov_len -= copy;
+                       iov[iovec_idx].iov_base += copy;
+
+                       if (!len)
+                               return dma_cookie;
+
+                       kdata += copy;
+                       iov_byte_offset = 0;
+                       page_idx++;
+               }
+               iovec_idx++;
+       }
+
+       /* really bad if we ever run out of iovecs */
+       BUG();
+       return -EFAULT;
+}
+
+dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, struct page *page,
+       unsigned int offset, size_t len)
+{
+       int iov_byte_offset;
+       int copy;
+       dma_cookie_t dma_cookie = 0;
+       int iovec_idx;
+       int page_idx;
+       int err;
+
+       /* this needs as-yet-unimplemented buf-to-buff, so punt. */
+       /* TODO: use dma for this */
+       if (!chan || !pinned_list) {
+               u8 *vaddr = kmap(page);
+               err = memcpy_toiovec(iov, vaddr + offset, len);
+               kunmap(page);
+               return err;
+       }
+
+       iovec_idx = 0;
+       while (iovec_idx < pinned_list->nr_iovecs) {
+               struct dma_page_list *page_list;
+
+               /* skip already used-up iovecs */
+               while (!iov[iovec_idx].iov_len)
+                       iovec_idx++;
+
+               page_list = &pinned_list->page_list[iovec_idx];
+
+               iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK);
+               page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK)
+                        - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT;
+
+               /* break up copies to not cross page boundary */
+               while (iov[iovec_idx].iov_len) {
+                       copy = min_t(int, PAGE_SIZE - iov_byte_offset, len);
+                       copy = min_t(int, copy, iov[iovec_idx].iov_len);
+
+                       dma_cookie = dma_async_memcpy_pg_to_pg(chan,
+                                       page_list->pages[page_idx],
+                                       iov_byte_offset,
+                                       page,
+                                       offset,
+                                       copy);
+
+                       len -= copy;
+                       iov[iovec_idx].iov_len -= copy;
+                       iov[iovec_idx].iov_base += copy;
+
+                       if (!len)
+                               return dma_cookie;
+
+                       offset += copy;
+                       iov_byte_offset = 0;
+                       page_idx++;
+               }
+               iovec_idx++;
+       }
+
+       /* really bad if we ever run out of iovecs */
+       BUG();
+       return -EFAULT;
+}
diff --git a/drivers/edac/k8_edac.c b/drivers/edac/k8_edac.c
new file mode 100644 (file)
index 0000000..d55f112
--- /dev/null
@@ -0,0 +1,1881 @@
+/*
+ * AMD K8 class Memory Controller kernel module
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh Linux Networx (http://lnxi.com)
+ *
+ *      Changes by Douglas "norsk" Thompson  <norsk5@xmission.com>:
+ *          - K8 CPU Revision D and greater support
+ *
+ *      Changes by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>:
+ *          - Module largely rewritten, with new (and hopefully correct)
+ *            code for dealing with node and chip select interleaving, various
+ *            code cleanup, and bug fixes
+ *          - Added support for memory hoisting using DRAM hole address
+ *            register
+ *
+ * This module is based on the following document (available from
+ * http://www.amd.com/):
+ *
+ *     Title: BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD
+ *            Opteron Processors
+ *     AMD publication #: 26094
+ *     Revision: 3.26
+ *
+ * Unless otherwise stated, section numbers mentioned in the comments below
+ * refer to this document.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <asm/mmzone.h>
+#include "edac_mc.h"
+
+#define k8_printk(level, fmt, arg...) \
+       edac_printk(level, "k8", fmt, ##arg)
+
+#define k8_mc_printk(mci, level, fmt, arg...) \
+       edac_mc_chipset_printk(mci, level, "k8", fmt, ##arg)
+
+/* Throughout the comments in this code, the terms SysAddr, DramAddr, and
+ * InputAddr are used.  These terms come directly from the k8 documentation
+ * (AMD publication #26094).  They are defined as follows:
+ *
+ *     SysAddr:
+ *         This is a physical address generated by a CPU core or a device
+ *         doing DMA.  If generated by a CPU core, a SysAddr is the result of
+ *         a virtual to physical address translation by the CPU core's address
+ *         translation mechanism (MMU).
+ *
+ *     DramAddr:
+ *         A DramAddr is derived from a SysAddr by subtracting an offset that
+ *         depends on which node the SysAddr maps to and whether the SysAddr
+ *         is within a range affected by memory hoisting.  The DRAM Base
+ *         (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers
+ *         determine which node a SysAddr maps to.
+ *
+ *         If the DRAM Hole Address Register (DHAR) is enabled and the SysAddr
+ *         is within the range of addresses specified by this register, then
+ *         a value x from the DHAR is subtracted from the SysAddr to produce a
+ *         DramAddr.  Here, x represents the base address for the node that
+ *         the SysAddr maps to plus an offset due to memory hoisting.  See
+ *         section 3.4.8 and the comments in get_dram_hole_info() and
+ *         sys_addr_to_dram_addr() below for more information.
+ *
+ *         If the SysAddr is not affected by the DHAR then a value y is
+ *         subtracted from the SysAddr to produce a DramAddr.  Here, y is the
+ *         base address for the node that the SysAddr maps to.  See section
+ *         3.4.4 and the comments in sys_addr_to_dram_addr() below for more
+ *         information.
+ *
+ *     InputAddr:
+ *         A DramAddr is translated to an InputAddr before being passed to the
+ *         memory controller for the node that the DramAddr is associated
+ *         with.  The memory controller then maps the InputAddr to a csrow.
+ *         If node interleaving is not in use, then the InputAddr has the same
+ *         value as the DramAddr.  Otherwise, the InputAddr is produced by
+ *         discarding the bits used for node interleaving from the DramAddr.
+ *         See section 3.4.4 for more information.
+ *
+ *         The memory controller for a given node uses its DRAM CS Base and
+ *         DRAM CS Mask registers to map an InputAddr to a csrow.  See
+ *         sections 3.5.4 and 3.5.5 for more information.
+ */
+
+/*
+ * Alter this version for the K8 module when modifications are made
+ */
+#define EDAC_K8_VERSION    " Ver: 2.0.0 " __DATE__
+#define EDAC_MOD_STR   "k8_edac"
+
+#ifndef PCI_DEVICE_ID_AMD_OPT_0_HT
+#define PCI_DEVICE_ID_AMD_OPT_0_HT     0x1100
+#endif                         /* PCI_DEVICE_ID_AMD_OPT_0_HT */
+
+#ifndef PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP
+#define PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP        0x1101
+#endif                         /* PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP */
+
+#ifndef PCI_DEVICE_ID_AMD_OPT_2_MEMCTL
+#define PCI_DEVICE_ID_AMD_OPT_2_MEMCTL 0x1102
+#endif                         /* PCI_DEVICE_ID_AMD_OPT_2_MEMCTL */
+
+#ifndef PCI_DEVICE_ID_AMD_OPT_3_MISCCTL
+#define PCI_DEVICE_ID_AMD_OPT_3_MISCCTL        0x1103
+#endif                         /* PCI_DEVICE_ID_AMD_OPT_3_MISCCTL */
+
+/* Extended Model from CPUID, for CPU Revision numbers */
+#define OPTERON_CPU_LE_REV_C    0
+#define OPTERON_CPU_REV_D       1
+#define OPTERON_CPU_REV_E       2
+
+#define K8_NR_CSROWS 8
+#define MAX_K8_NODES 8
+
+/* K8 register addresses - device 0 function 1 - Address Map */
+#define K8_DBR         0x40    /* DRAM Base Register (8 x 32b
+                                * interlaced with K8_DLR)
+                                *
+                                * 31:16 DRAM Base addr 39:24
+                                * 15:11 reserved
+                                * 10:8  interleave enable
+                                *  7:2  reserved
+                                *  1    write enable
+                                *  0    read enable
+                                */
+
+#define K8_DLR         0x44    /* DRAM Limit Register (8 x 32b
+                                * interlaced with K8_DBR)
+                                *
+                                * 31:16 DRAM Limit addr 32:24
+                                * 15:11 reserved
+                                * 10:8  interleave select
+                                *  7:3  reserved
+                                *  2:0  destination node ID
+                                */
+
+#define K8_DHAR         0xf0    /* DRAM Hole Address Register
+                                *
+                                * 31:24 DramHoleBase
+                                * 23:16 reserved
+                                * 15:8  DramHoleOffset
+                                *  7:1  reserved
+                                *    0  DramHoleValid
+                                */
+
+/* K8 register addresses - device 0 function 2 - DRAM controller */
+#define K8_DCSB                0x40    /* DRAM Chip-Select Base (8 x 32b)
+                                *
+                                * 31:21 Base addr high 35:25
+                                * 20:16 reserved
+                                * 15:9  Base addr low 19:13 (interlvd)
+                                *  8:1  reserved
+                                *  0    chip-select bank enable
+                                */
+
+#define K8_DCSM                0x60    /* DRAM Chip-Select Mask (8 x 32b)
+                                *
+                                * 31:30 reserved
+                                * 29:21 addr mask high 33:25
+                                * 20:16 reserved
+                                * 15:9  addr mask low  19:13
+                                *  8:0  reserved
+                                */
+
+/* selects bits 29-21 and 15-9 from DCSM */
+#define DCSM_MASK_BITS 0x3fe0fe00
+
+#define K8_DBAM                0x80    /* DRAM Base Addr Mapping (32b) */
+
+#define K8_DCL         0x90    /* DRAM configuration low reg (32b)
+                                *
+                                * 31:28 reserved
+                                * 27:25 Bypass Max: 000b=respect
+                                * 24    Dissable receivers - no sockets
+                                * 23:20 x4 DIMMS
+                                * 19    32byte chunks
+                                * 18    Unbuffered
+                                * 17    ECC enabled
+                                * 16    128/64 bit (dual/single chan)
+                                * 15:14 R/W Queue bypass count
+                                * 13    Self refresh
+                                * 12    exit self refresh
+                                * 11    mem clear status
+                                * 10    DRAM enable
+                                *  9    reserved
+                                *  8    DRAM init
+                                *  7:4  reserved
+                                *  3    dis DQS hysteresis
+                                *  2    QFC enabled
+                                *  1    DRAM drive strength
+                                *  0    Digital Locked Loop disable
+                                */
+
+/* K8 register addresses - device 0 function 3 - Misc Control */
+#define K8_NBCTL       0x40    /* MCA NB Control (32b)
+                                *
+                                *  1    MCA UE Reporting
+                                *  0    MCA CE Reporting
+                                */
+
+#define K8_NBCFG       0x44    /* MCA NB Config (32b)
+                                *
+                                * 23    Chip-kill x4 ECC enable
+                                * 22    ECC enable
+                                *  1    CPU ECC enable
+                                */
+
+#define K8_NBSL                0x48    /* MCA NB Status Low (32b)
+                                *
+                                * 31:24 Syndrome 15:8 chip-kill x4
+                                * 23:20 reserved
+                                * 19:16 Extended err code
+                                * 15:0  Err code
+                                */
+
+#define K8_NBSH                0x4C    /* MCA NB Status High (32b)
+                                *
+                                * 31    Err valid
+                                * 30    Err overflow
+                                * 29    Uncorrected err
+                                * 28    Err enable
+                                * 27    Misc err reg valid
+                                * 26    Err addr valid
+                                * 25    proc context corrupt
+                                * 24:23 reserved
+                                * 22:15 Syndrome 7:0
+                                * 14    CE
+                                * 13    UE
+                                * 12:9  reserved
+                                *  8    err found by scrubber
+                                *  7    reserved
+                                *  6:4  Hyper-transport link number
+                                *  3:2  reserved
+                                *  1    Err CPU 1
+                                *  0    Err CPU 0
+                                */
+
+#define K8_NBSH_VALID_BIT BIT(31)
+
+#define K8_NBEAL       0x50    /* MCA NB err addr low (32b)
+                                *
+                                * 31:3  Err addr low 31:3
+                                *  2:0  reserved
+                                */
+
+#define K8_NBEAH       0x54    /* MCA NB err addr high (32b)
+                                *
+                                * 31:8  reserved
+                                *  7:0  Err addr high 39:32
+                                */
+
+#define K8_NBCAP       0xE8    /* MCA NB capabilities (32b)
+                                *
+                                * 31:9  reserved
+                                *  4    S4ECD4ED capable
+                                *  3    SECDED capable
+                                */
+
+                               /* MSR's */
+
+                               /*
+                                * K8_MSR_MCxCTL (64b)
+                                * (0x400,404,408,40C,410)
+                                * 63    Enable reporting source 63
+                                *  .
+                                *  .
+                                *  .
+                                *  2    Enable error source 2
+                                *  1    Enable error source 1
+                                *  0    Enable error source 0
+                                */
+
+                               /*
+                                * K8_MSR_MCxSTAT (64b)
+                                * (0x401,405,409,40D,411)
+                                * 63    Error valid
+                                * 62    Status overflow
+                                * 61    UE
+                                * 60    Enabled error condition
+                                * 59    Misc register valid (not used)
+                                * 58    Err addr register valid
+                                * 57    Processor context corrupt
+                                * 56:32 Other information
+                                * 31:16 Model specific error code
+                                * 15:0  MCA err code
+                                */
+
+                               /*
+                                * K8_MSR_MCxADDR (64b)
+                                * (0x402,406,40A,40E,412)
+                                * 63:48 reserved
+                                * 47:0  Address
+                                */
+
+                               /*
+                                * K8_MSR_MCxMISC (64b)
+                                * (0x403,407,40B,40F,413)
+                                * Unused on Athlon64 and K8
+                                */
+
+#define K8_MSR_MCGCTL  0x017b  /* Machine Chk Global report ctl (64b)
+                                *
+                                * 31:5  reserved
+                                *  4    North Bridge
+                                *  3    Load/Store
+                                *  2    Bus Unit
+                                *  1    Instruction Cache
+                                *  0    Data Cache
+                                */
+
+#define K8_MSR_MC4CTL  0x0410  /* North Bridge Check report ctl (64b) */
+#define K8_MSR_MC4STAT 0x0411  /* North Bridge status (64b) */
+#define K8_MSR_MC4ADDR 0x0412  /* North Bridge Address (64b) */
+
+static inline int MCI_TO_NODE_ID(struct mem_ctl_info *mci)
+{
+       return PCI_SLOT(to_pci_dev(mci->dev)->devfn) - 0x18;
+}
+
+/* Ugly hack that allows module to compile when built as part of a 32-bit
+ * kernel.  Just in case anyone wants to run a 32-bit kernel on their Opteron.
+ */
+#ifndef MAXNODE
+#define MAXNODE 8
+#endif
+
+/* Each entry holds the CPU revision of all CPU cores for the given node. */
+static int k8_node_revision_table[MAXNODE] = { 0 };
+
+static inline int node_rev(int node_id)
+{
+       return k8_node_revision_table[node_id];
+}
+
+static void store_node_revision(void *param)
+{
+       int node_id, revision;
+
+       /* Multiple CPU cores on the same node will all write their revision
+        * number to the same array entry.  This is ok.  For a given node, all
+        * CPU cores are on the same piece of silicon and share the same
+        * revision number.
+        */
+       node_id = (cpuid_ebx(1) >> 24) & 0x07;
+       revision = (cpuid_eax(1) >> 16) & 0x0f;
+       k8_node_revision_table[node_id] = revision;
+}
+
+/* Initialize k8_node_revision_table. */
+static void build_node_revision_table(void)
+{
+       static int initialized = 0;
+
+       if (initialized)
+               return;
+
+       on_each_cpu(store_node_revision, NULL, 1, 1);
+       initialized = 1;
+}
+
+enum k8_chips {
+       OPTERON = 0,
+};
+
+struct k8_pvt {
+       struct pci_dev *addr_map;
+       struct pci_dev *misc_ctl;
+
+       int node_id;  /* ID of this node */
+
+       /* The values of these registers will remain constant so we might as
+        * well cache them here.
+        */
+       u32 dcl;
+       u32 dbr[MAX_K8_NODES];
+       u32 dlr[MAX_K8_NODES];
+       u32 nbcap;
+       u32 dcsb[K8_NR_CSROWS];
+       u32 dcsm[K8_NR_CSROWS];
+       u32 dhar;
+       u32 dbam;
+};
+
+struct k8_error_info_regs {
+       u32 nbsh;
+       u32 nbsl;
+       u32 nbeah;
+       u32 nbeal;
+};
+
+struct k8_error_info {
+       struct k8_error_info_regs error_info;
+       u32 nbcfg;
+       int race_condition_detected;
+};
+
+struct k8_dev_info {
+       const char *ctl_name;
+       u16 addr_map;
+       u16 misc_ctl;
+};
+
+static const struct k8_dev_info k8_devs[] = {
+       [OPTERON] = {
+                    .ctl_name = "Athlon64/Opteron",
+                    .addr_map = PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP,
+                    .misc_ctl = PCI_DEVICE_ID_AMD_OPT_3_MISCCTL},
+};
+
+static struct pci_dev * pci_get_related_function(unsigned int vendor,
+               unsigned int device, struct pci_dev *related)
+{
+       struct pci_dev *dev;
+
+       dev = NULL;
+
+       while ((dev = pci_get_device(vendor, device, dev)) != NULL) {
+               if ((dev->bus->number == related->bus->number) &&
+                   (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn)))
+                       break;
+       }
+
+       return dev;
+}
+
+/* FIXME - stolen from msr.c - the calls in msr.c could be exported */
+struct msr_command {
+       int cpu;
+       int err;
+       u32 reg;
+       u32 data[2];
+};
+
+static void smp_wrmsr(void *cmd_block)
+{
+       struct msr_command *cmd = cmd_block;
+       wrmsr(cmd->reg, cmd->data[0], cmd->data[1]);
+}
+
+static void smp_rdmsr(void *cmd_block)
+{
+       struct msr_command *cmd = cmd_block;
+       rdmsr(cmd->reg, cmd->data[0], cmd->data[1]);
+}
+
+static void do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
+{
+       struct msr_command cmd;
+
+       cmd.cpu = raw_smp_processor_id();
+       cmd.reg = reg;
+       cmd.data[0] = eax;
+       cmd.data[1] = edx;
+       on_each_cpu(smp_wrmsr, &cmd, 1, 1);
+}
+
+static void do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
+{
+       struct msr_command cmd;
+
+       cmd.cpu = raw_smp_processor_id();
+       cmd.reg = reg;
+       on_each_cpu(smp_rdmsr, &cmd, 1, 1);
+       *eax = cmd.data[0];
+       *edx = cmd.data[1];
+}
+
+/*
+ * FIXME - This is a large chunk of memory to suck up just to decode the
+ * syndrome.  It would be nice to discover a pattern in the syndromes that
+ * could be used to quickly identify the channel.  The big problems with
+ * this table is memory usage, lookup speed (could sort and binary search),
+ * correctness (there could be a transcription error).  A zero in any nibble
+ * for a syndrom is always channel 0, but that only decodes some of the
+ * syndromes.  Can anyone find any other patterns?
+ *
+ * The comment in the left column is the nibble that is in error.  The least
+ * significant nibble of the syndrome is the mask for the bits that are
+ * in error (need to be toggled) for the particular nibble.
+ */
+#define SYNDROME_TABLE_SIZE 270
+static const unsigned long syndromes_chan0[SYNDROME_TABLE_SIZE] = {
+       /*0 */ 0xe821, 0x7c32, 0x9413, 0xbb44, 0x5365, 0xc776, 0x2f57,
+       0xdd88, 0x35a9, 0xa1ba, 0x499b, 0x66cc, 0x8eed, 0x1afe, 0xf2df,
+       /*1 */ 0x5d31, 0xa612, 0xfb23, 0x9584, 0xc8b5, 0x3396, 0x6ea7,
+       0xeac8, 0xb7f9, 0x4cda, 0x11eb, 0x7f4c, 0x227d, 0xd95e, 0x846f,
+       /*2 */ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+       0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+       /*3 */ 0x2021, 0x3032, 0x1013, 0x4044, 0x6065, 0x7076, 0x5057,
+       0x8088, 0xa0a9, 0xb0ba, 0x909b, 0xc0cc, 0xe0ed, 0xf0fe, 0xd0df,
+       /*4 */ 0x5041, 0xa082, 0xf0c3, 0x9054, 0xc015, 0x30d6, 0x6097,
+       0xe0a8, 0xb0e9, 0x402a, 0x106b, 0x70fc, 0x20bd, 0xd07e, 0x803f,
+       /*5 */ 0xbe21, 0xd732, 0x6913, 0x2144, 0x9f65, 0xf676, 0x4857,
+       0x3288, 0x8ca9, 0xe5ba, 0x5b9b, 0x13cc, 0xaded, 0xc4fe, 0x7adf,
+       /*6 */ 0x4951, 0x8ea2, 0xc7f3, 0x5394, 0x1ac5, 0xdd36, 0x9467,
+       0xa1e8, 0xe8b9, 0x2f4a, 0x661b, 0xf27c, 0xbb2d, 0x7cde, 0x358f,
+       /*7 */ 0x74e1, 0x9872, 0xec93, 0xd6b4, 0xa255, 0x4ec6, 0x3a27,
+       0x6bd8, 0x1f39, 0xf3aa, 0x874b, 0xbd6c, 0xc98d, 0x251e, 0x51ff,
+       /*8 */ 0x15c1, 0x2a42, 0x3f83, 0xcef4, 0xdb35, 0xe4b6, 0xf177,
+       0x4758, 0x5299, 0x6d1a, 0x78db, 0x89ac, 0x9c6d, 0xa3ee, 0xb62f,
+       /*9 */ 0x3d01, 0x1602, 0x2b03, 0x8504, 0xb805, 0x9306, 0xae07,
+       0xca08, 0xf709, 0xdc0a, 0xe10b, 0x4f0c, 0x720d, 0x590e, 0x640f,
+       /*a */ 0x9801, 0xec02, 0x7403, 0x6b04, 0xf305, 0x8706, 0x1f07,
+       0xbd08, 0x2509, 0x510a, 0xc90b, 0xd60c, 0x4e0d, 0x3a0e, 0xa20f,
+       /*b */ 0xd131, 0x6212, 0xb323, 0x3884, 0xe9b5, 0x5a96, 0x8ba7,
+       0x1cc8, 0xcdf9, 0x7eda, 0xafeb, 0x244c, 0xf57d, 0x465e, 0x976f,
+       /*c */ 0xe1d1, 0x7262, 0x93b3, 0xb834, 0x59e5, 0xca56, 0x2b87,
+       0xdc18, 0x3dc9, 0xae7a, 0x4fab, 0x542c, 0x85fd, 0x164e, 0xf79f,
+       /*d */ 0x6051, 0xb0a2, 0xd0f3, 0x1094, 0x70c5, 0xa036, 0xc067,
+       0x20e8, 0x40b9, 0x904a, 0x601b, 0x307c, 0x502d, 0x80de, 0xe08f,
+       /*e */ 0xa4c1, 0xf842, 0x5c83, 0xe6f4, 0x4235, 0x1eb6, 0xba77,
+       0x7b58, 0xdf99, 0x831a, 0x27db, 0x9dac, 0x396d, 0x65ee, 0xc12f,
+       /*f */ 0x11c1, 0x2242, 0x3383, 0xc8f4, 0xd935, 0xeab6, 0xfb77,
+       0x4c58, 0x5d99, 0x6e1a, 0x7fdb, 0x84ac, 0x9562, 0xa6ee, 0xb72f,
+
+       /*20 */ 0xbe01, 0xd702, 0x6903, 0x2104, 0x9f05, 0xf606, 0x4807,
+       0x3208, 0x8c09, 0xe50a, 0x5b0b, 0x130c, 0xad0d, 0xc40e, 0x7a0f,
+       /*21 */ 0x4101, 0x8202, 0xc303, 0x5804, 0x1905, 0xda06, 0x9b07,
+       0xac08, 0xed09, 0x2e0a, 0x6f0b, 0x640c, 0xb50d, 0x760e, 0x370f
+};
+
+static const unsigned long syndromes_chan1[SYNDROME_TABLE_SIZE] = {
+       /*10 */ 0x45d1, 0x8a62, 0xcfb3, 0x5e34, 0x1be5, 0xd456, 0x9187,
+       0xa718, 0xe2c9, 0x2d7a, 0x68ab, 0xf92c, 0xbcfd, 0x734e, 0x369f,
+       /*11 */ 0x63e1, 0xb172, 0xd293, 0x14b4, 0x7755, 0xa5c6, 0xc627,
+       0x28d8, 0x4b39, 0x99aa, 0xfa4b, 0x3c6c, 0x5f8d, 0x8d1e, 0xeeff,
+       /*12 */ 0xb741, 0xd982, 0x6ec3, 0x2254, 0x9515, 0xfbd6, 0x4c97,
+       0x33a8, 0x84e9, 0xea2a, 0x5d6b, 0x11fc, 0xa6bd, 0xc87e, 0x7f3f,
+       /*13 */ 0xdd41, 0x6682, 0xbbc3, 0x3554, 0xe815, 0x53d6, 0xce97,
+       0x1aa8, 0xc7e9, 0x7c2a, 0xa1fb, 0x2ffc, 0xf2bd, 0x497e, 0x943f,
+       /*14 */ 0x2bd1, 0x3d62, 0x16b3, 0x4f34, 0x64e5, 0x7256, 0x5987,
+       0x8518, 0xaec9, 0xb87a, 0x93ab, 0xca2c, 0xe1fd, 0xf74e, 0xdc9f,
+       /*15 */ 0x83c1, 0xc142, 0x4283, 0xa4f4, 0x2735, 0x65b6, 0xe677,
+       0xf858, 0x7b99, 0x391a, 0xbadb, 0x5cac, 0xdf6d, 0x9dee, 0x1e2f,
+       /*16 */ 0x8fd1, 0xc562, 0x4ab3, 0xa934, 0x26e5, 0x6c56, 0xe387,
+       0xfe18, 0x71c9, 0x3b7a, 0xb4ab, 0x572c, 0xd8fd, 0x924e, 0x1d9f,
+       /*17 */ 0x4791, 0x89e2, 0xce73, 0x5264, 0x15f5, 0xdb86, 0x9c17,
+       0xa3b8, 0xe429, 0x2a5a, 0x6dcb, 0xf1dc, 0xb64d, 0x783e, 0x3faf,
+       /*18 */ 0x5781, 0xa9c2, 0xfe43, 0x92a4, 0xc525, 0x3b66, 0x6ce7,
+       0xe3f8, 0xb479, 0x4a3a, 0x1dbb, 0x715c, 0x26dd, 0xd89e, 0x8f1f,
+       /*19 */ 0xbf41, 0xd582, 0x6ac3, 0x2954, 0x9615, 0xfcd6, 0x4397,
+       0x3ea8, 0x81e9, 0xeb2a, 0x546b, 0x17fc, 0xa8bd, 0xc27e, 0x7d3f,
+       /*1a */ 0x9891, 0xe1e2, 0x7273, 0x6464, 0xf7f5, 0x8586, 0x1617,
+       0xb8b8, 0x2b29, 0x595a, 0xcacb, 0xdcdc, 0x4f4d, 0x3d3e, 0xaeaf,
+       /*1b */ 0xcce1, 0x4472, 0x8893, 0xfdb4, 0x3f55, 0xb9c6, 0x7527,
+       0x56d8, 0x9a39, 0x12aa, 0xde4b, 0xab6c, 0x678d, 0xef1e, 0x23ff,
+       /*1c */ 0xa761, 0xf9b2, 0x5ed3, 0xe214, 0x4575, 0x1ba6, 0xbcc7,
+       0x7328, 0xd449, 0x8a9a, 0x2dfb, 0x913c, 0x365d, 0x688e, 0xcfef,
+       /*1d */ 0xff61, 0x55b2, 0xaad3, 0x7914, 0x8675, 0x2ca6, 0xd3c7,
+       0x9e28, 0x6149, 0xcb9a, 0x34fb, 0xe73c, 0x185d, 0xb28e, 0x4def,
+       /*1e */ 0x5451, 0xa8a2, 0xfcf3, 0x9694, 0xc2c5, 0x3e36, 0x6a67,
+       0xebe8, 0xbfb9, 0x434a, 0x171b, 0x7d7c, 0x292d, 0xd5de, 0x818f,
+       /*1f */ 0x6fc1, 0xb542, 0xda83, 0x19f4, 0x7635, 0xacb6, 0xc377,
+       0x2e58, 0x4199, 0x9b1a, 0xf4db, 0x37ac, 0x586d, 0x82ee, 0xed2f,
+
+       /*22 */ 0xc441, 0x4882, 0x8cc3, 0xf654, 0x3215, 0xbed6, 0x7a97,
+       0x5ba8, 0x9fe9, 0x132a, 0xd76b, 0xadfc, 0x69bd, 0xe57e, 0x213f,
+       /*23 */ 0x7621, 0x9b32, 0xed13, 0xda44, 0xac65, 0x4176, 0x3757,
+       0x6f88, 0x19a9, 0xf4ba, 0x829b, 0xb5cc, 0xc3ed, 0x2efe, 0x58df
+};
+
+static int chan_from_chipkill_syndrome(unsigned long syndrome)
+{
+       int i;
+
+       debugf0("%s()\n", __func__);
+
+       for (i = 0; i < SYNDROME_TABLE_SIZE; i++) {
+               if (syndromes_chan0[i] == syndrome)
+                       return 0;
+               if (syndromes_chan1[i] == syndrome)
+                       return 1;
+       }
+
+       debugf0("%s(): syndrome(%lx) not found\n", __func__, syndrome);
+       return -1;
+}
+
+static const char *tt_msgs[] = {       /* transaction type */
+       "inst",
+       "data",
+       "generic",
+       "reserved"
+};
+
+static const char *ll_msgs[] = {       /* cache level */
+       "0",
+       "1",
+       "2",
+       "generic"
+};
+
+static const char *memtt_msgs[] = {
+       "generic",
+       "generic read",
+       "generic write",
+       "data read",
+       "data write",
+       "inst fetch",
+       "prefetch",
+       "evict",
+       "snoop",
+       "unknown error 9",
+       "unknown error 10",
+       "unknown error 11",
+       "unknown error 12",
+       "unknown error 13",
+       "unknown error 14",
+       "unknown error 15"
+};
+
+static const char *pp_msgs[] = {       /* participating processor */
+       "local node origin",
+       "local node response",
+       "local node observed",
+       "generic"
+};
+
+static const char *to_msgs[] = {
+       "no timeout",
+       "timed out"
+};
+
+static const char *ii_msgs[] = {       /* memory or i/o */
+       "mem access",
+       "reserved",
+       "i/o access",
+       "generic"
+};
+
+static const char *ext_msgs[] = {      /* extended error */
+       "ECC error",
+       "CRC error",
+       "sync error",
+       "mst abort",
+       "tgt abort",
+       "GART error",
+       "RMW error",
+       "watchdog error",
+       "ECC chipkill x4 error",
+       "unknown error 9",
+       "unknown error 10",
+       "unknown error 11",
+       "unknown error 12",
+       "unknown error 13",
+       "unknown error 14",
+       "unknown error 15"
+};
+
+static const char *htlink_msgs[] = {
+       "none",
+       "1",
+       "2",
+       "1 2",
+       "3",
+       "1 3",
+       "2 3",
+       "1 2 3"
+};
+
+static inline u64 base_from_dcsb(u32 dcsb)
+{
+       /* 0xffe0fe00 selects bits 31-21 and 15-9 of a DRAM CS Base Address
+        * Register (section 3.5.4).  Shifting the bits left 4 puts them in
+        * their proper bit positions of 35-25 and 19-13.
+        */
+       return ((u64) (dcsb & 0xffe0fe00)) << 4;
+}
+
+static u64 mask_from_dcsm(u32 dcsm)
+{
+       u64 dcsm_bits, other_bits;
+
+       /* Extract bits bits 29-21 and 15-9 from DCSM (section 3.5.5). */
+       dcsm_bits = dcsm & DCSM_MASK_BITS;
+
+       /* Set all bits except bits 33-25 and 19-13. */
+       other_bits = DCSM_MASK_BITS;
+       other_bits = ~(other_bits << 4);
+
+       /* The extracted bits from DCSM belong in the spaces represented by
+        * the cleared bits in other_bits.
+        */
+       return (dcsm_bits << 4) | other_bits;
+}
+
+/* In *base and *limit, pass back the full 40-bit base and limit physical
+ * addresses for the node given by node_id.  This information is obtained from
+ * DRAM Base (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers. The
+ * base and limit addresses are of type SysAddr, as defined at the start of
+ * section 3.4.4 (p. 70).  They are the lowest and highest physical addresses
+ * in the address range they represent.
+ */
+static void get_base_and_limit(struct k8_pvt *pvt, int node_id,
+               u64 *base, u64 *limit)
+{
+       *base = ((u64) (pvt->dbr[node_id] & 0xffff0000)) << 8;
+
+       /* Since the limit represents the highest address in the range, we
+        * must set its lowest 24 bits to 1.
+        */
+       *limit = (((u64) (pvt->dlr[node_id] & 0xffff0000)) << 8) | 0xffffff;
+}
+
+/* Return 1 if the SysAddr given by sys_addr matches the base/limit associated
+ * with node_id
+ */
+static int base_limit_match(struct k8_pvt *pvt, u64 sys_addr, int node_id)
+{
+       u64 base, limit, addr;
+
+       get_base_and_limit(pvt, node_id, &base, &limit);
+
+       /* The k8 treats this as a 40-bit value.  However, bits 63-40 will be
+        * all ones if the most significant implemented address bit is 1.
+        * Here we discard bits 63-40.  See section 3.4.2 of AMD publication
+        * 24592: AMD x86-64 Architecture Programmer's Manual Volume 1
+        * Application Programming.
+        */
+       addr = sys_addr & 0x000000ffffffffffull;
+
+       return (addr >= base) && (addr <= limit);
+}
+
+/* Attempt to map a SysAddr to a node.  On success, return a pointer to the
+ * mem_ctl_info structure for the node that the SysAddr maps to.  On failure,
+ * return NULL.
+ */
+static struct mem_ctl_info * find_mc_by_sys_addr(struct mem_ctl_info *mci,
+                                               u64 sys_addr)
+{
+       struct k8_pvt *pvt;
+       int node_id;
+       u32 intlv_en, bits;
+
+       /* Here we use the DRAM Base (section 3.4.4.1) and DRAM Limit (section
+        * 3.4.4.2) registers to map the SysAddr to a node ID.
+        */
+
+       pvt = mci->pvt_info;
+
+       /* The value of this field should be the same for all DRAM Base
+        * registers.  Therefore we arbitrarily choose to read it from the
+        * register for node 0.
+        */
+       intlv_en = pvt->dbr[0] & (0x07 << 8);
+
+       if (intlv_en == 0) {  /* node interleaving is disabled */
+               debugf2("%s(): node interleaving disabled\n", __func__);
+               for (node_id = 0; ; ) {
+                       if (base_limit_match(pvt, sys_addr, node_id))
+                               break;
+
+                       if (++node_id == MAX_K8_NODES) {
+                               debugf2("%s(): sys_addr 0x%lx "
+                                       "does not match any node\n", __func__,
+                                       (unsigned long) sys_addr);
+                               return NULL;
+                       }
+               }
+
+               goto found;
+       }
+
+       if (unlikely((intlv_en != (0x01 << 8)) &&
+                    (intlv_en != (0x03 << 8)) &&
+                    (intlv_en != (0x07 << 8)))) {
+               k8_printk(KERN_WARNING,
+                         "%s(): junk value of 0x%x extracted from IntlvEn "
+                         "field of DRAM Base Register for node 0: This "
+                         "probably indicates a BIOS bug.\n", __func__,
+                         intlv_en);
+               return NULL;
+       }
+
+       /* If we get this far, node interleaving is enabled. */
+       debugf2("%s(): node interleaving enabled\n", __func__);
+       bits = (((u32) sys_addr) >> 12) & intlv_en;
+
+       for (node_id = 0; ; ) {
+               if ((pvt->dlr[node_id] & intlv_en) == bits)
+                       break;  /* intlv_sel field matches */
+
+               if (++node_id == MAX_K8_NODES) {
+                       debugf2("%s(): sys_addr 0x%lx does not match any "
+                               "node\n", __func__, (unsigned long) sys_addr);
+                       return NULL;
+               }
+       }
+
+       /* sanity test for sys_addr */
+       if (unlikely(!base_limit_match(pvt, sys_addr, node_id))) {
+               k8_printk(KERN_WARNING,
+                         "%s(): sys_addr 0x%lx falls outside base/limit "
+                         "address range for node %d with node interleaving "
+                         "enabled.\n", __func__, (unsigned long) sys_addr,
+                         node_id);
+               return NULL;
+       }
+
+found:
+       debugf2("%s(): sys_addr 0x%lx matches node %d\n", __func__,
+               (unsigned long) sys_addr, node_id);
+       return edac_mc_find(node_id);
+}
+
+/* Return the base value defined by the DRAM Base register for the node
+ * represented by mci.  This function returns the full 40-bit value despite
+ * the fact that the register only stores bits 39-24 of the value.  See
+ * section 3.4.4.1.
+ */
+static inline u64 get_dram_base(struct mem_ctl_info *mci)
+{
+       struct k8_pvt *pvt;
+
+       pvt = mci->pvt_info;
+       return ((u64) (pvt->dbr[pvt->node_id] & 0xffff0000)) << 8;
+}
+
+/* Obtain info from the DRAM Hole Address Register (section 3.4.8) for the
+ * node represented by mci.  Info is passed back in *hole_base, *hole_offset,
+ * and *hole_size.  Function returns 0 if info is valid or 1 if info is
+ * invalid.  Info may be invalid for either of the following reasons:
+ *
+ *     - The revision of the node is not E or greater.  In this case, the DRAM
+ *       Hole Address Register does not exist.
+ *     - The DramHoleValid bit is cleared in the DRAM Hole Address Register,
+ *       indicating that its contents are not valid.
+ *
+ * The values passed back in *hole_base, *hole_offset, and *hole_size are
+ * complete 32-bit values despite the fact that the bitfields in the DHAR
+ * only represent bits 31-24 of the base and offset values.
+ */
+static int get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
+               u64 *hole_offset, u64 *hole_size)
+{
+       struct k8_pvt *pvt;
+       u64 base;
+
+       pvt = mci->pvt_info;
+
+       if (node_rev(pvt->node_id) < OPTERON_CPU_REV_E) {
+               debugf2("revision %d for node %d does not support DHAR\n",
+                       node_rev(pvt->node_id), pvt->node_id);
+               return 1;
+       }
+
+       if ((pvt->dhar & 0x01) == 0) {
+               debugf2("DramHoleValid bit cleared in DHAR for node %d\n",
+                       pvt->node_id);
+               return 1;  /* DramHoleValid bit is cleared */
+       }
+
+       /* +------------------+--------------------+--------------------+-----
+        * | memory           | DRAM hole          | relocated          |
+        * | [0, (x - 1)]     | [x, 0xffffffff]    | addresses from     |
+        * |                  |                    | DRAM hole          |
+        * |                  |                    | [0x100000000,      |
+        * |                  |                    |  (0x100000000+     |
+        * |                  |                    |   (0xffffffff-x))] |
+        * +------------------+--------------------+--------------------+-----
+        *
+        * Above is a diagram of physical memory showing the DRAM hole and the
+        * relocated addresses from the DRAM hole.  As shown, the DRAM hole
+        * starts at address x (the base address) and extends through address
+        * 0xffffffff.  The DRAM Hole Address Register (DHAR) relocates the
+        * addresses in the hole so that they start at 0x100000000.
+        */
+
+       base = pvt->dhar & 0xff000000;
+       *hole_base = base;
+       *hole_offset = (pvt->dhar & 0x0000ff00) << 16;
+       *hole_size = (0x1ull << 32) - base;
+       debugf2("DHAR info for node %d: base 0x%lx offset 0x%lx size 0x%lx\n",
+               pvt->node_id, (unsigned long) *hole_base,
+               (unsigned long) *hole_offset, (unsigned long) *hole_size);
+       return 0;
+}
+
+/* Return the DramAddr that the SysAddr given by sys_addr maps to.  It is
+ * assumed that sys_addr maps to the node given by mci.
+ */
+static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
+{
+       u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
+
+       /* The first part of section 3.4.4 (p. 70) shows how the DRAM Base
+        * (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers are
+        * used to translate a SysAddr to a DramAddr.  If the DRAM Hole
+        * Address Register (DHAR) is enabled, then it is also involved in
+        * translating a SysAddr to a DramAddr.  Sections 3.4.8 and 3.5.8.2
+        * describe the DHAR and how it is used for memory hoisting.  These
+        * parts of the documentation are unclear.  I interpret them as
+        * follows:
+        *
+        *     When node n receives a SysAddr, it processes the SysAddr as
+        *     follows:
+        *
+        *         1.  It extracts the DRAMBase and DRAMLimit values from the
+        *             DRAM Base and DRAM Limit registers for node n.  If the
+        *             SysAddr is not within the range specified by the base
+        *             and limit values, then node n ignores the Sysaddr
+        *             (since it does not map to node n).  Otherwise continue
+        *             to step 2 below.
+        *
+        *         2.  If the DramHoleValid bit of the DHAR for node n is
+        *             clear, the DHAR is disabled so skip to step 3 below.
+        *             Otherwise see if the SysAddr is within the range of
+        *             relocated addresses (starting at 0x100000000) from the
+        *             DRAM hole.  If not, skip to step 3 below.  Else get the
+        *             value of the DramHoleOffset field from the DHAR.  To
+        *             obtain the DramAddr, subtract the offset defined by
+        *             this value from the SysAddr.
+        *
+        *         3.  Obtain the base address for node n from the DRAMBase
+        *             field of the DRAM Base register for node n.  To obtain
+        *             the DramAddr, subtract the base address from the
+        *             SysAddr, as shown near the start of section 3.4.4
+        *             (p. 70).
+        */
+
+       dram_base = get_dram_base(mci);
+
+       if (!get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size)) {
+               if ((sys_addr >= (1ull << 32)) &&
+                   (sys_addr < ((1ull << 32) + hole_size))) {
+                       /* use DHAR to translate SysAddr to DramAddr */
+                       dram_addr = sys_addr - hole_offset;
+                       debugf2("using DHAR to translate SysAddr 0x%lx to "
+                               "DramAddr 0x%lx\n",
+                               (unsigned long) sys_addr,
+                               (unsigned long) dram_addr);
+                       return dram_addr;
+               }
+       }
+
+       /* Translate the SysAddr to a DramAddr as shown near the start of
+        * section 3.4.4 (p. 70).  Although sys_addr is a 64-bit value, the k8
+        * only deals with 40-bit values.  Therefore we discard bits 63-40 of
+        * sys_addr below.  If bit 39 of sys_addr is 1 then the bits we
+        * discard are all 1s.  Otherwise the bits we discard are all 0s.  See
+        * section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture
+        * Programmer's Manual Volume 1 Application Programming.
+        */
+       dram_addr = (sys_addr & 0xffffffffffull) - dram_base;
+
+       debugf2("using DRAM Base register to translate SysAddr 0x%lx to "
+               "DramAddr 0x%lx\n", (unsigned long) sys_addr,
+               (unsigned long) dram_addr);
+       return dram_addr;
+}
+
+/* Parameter intlv_en is the value of the IntlvEn field from a DRAM Base
+ * register (section 3.4.4.1).  Return the number of bits from a SysAddr that
+ * are used for node interleaving.
+ */
+static int num_node_interleave_bits(unsigned intlv_en)
+{
+       static const int intlv_shift_table[] = { 0, 1, 0, 2, 0, 0, 0, 3 };
+       int n;
+
+       BUG_ON(intlv_en > 7);
+       n = intlv_shift_table[intlv_en];
+       debugf2("using %d bits for node interleave\n", n);
+       return n;
+}
+
+/* Translate the DramAddr given by dram_addr to an InputAddr and return the
+ * result.
+ */
+static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr)
+{
+       struct k8_pvt *pvt;
+       int intlv_shift;
+       u64 input_addr;
+
+       pvt = mci->pvt_info;
+
+       /* Near the start of section 3.4.4 (p. 70), the k8 documentation gives
+        * instructions for translating a DramAddr to an InputAddr.  Here we
+        * are following these instructions.
+        */
+       intlv_shift = num_node_interleave_bits((pvt->dbr[0] >> 8) & 0x07);
+       input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) +
+           (dram_addr & 0xfff);
+
+       debugf2("DramAddr 0x%lx translates to InputAddr 0x%lx\n",
+               (unsigned long) dram_addr, (unsigned long) input_addr);
+       return input_addr;
+}
+
+/* Translate the SysAddr represented by sys_addr to an InputAddr and return
+ * the result.  It is assumed that sys_addr maps to the node given by mci.
+ */
+static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr)
+{
+       u64 input_addr;
+
+       input_addr = dram_addr_to_input_addr(
+                               mci, sys_addr_to_dram_addr(mci, sys_addr));
+       debugf2("%s(): SysAdddr 0x%lx translates to InputAddr 0x%lx\n",
+               __func__, (unsigned long) sys_addr,
+               (unsigned long) input_addr);
+       return input_addr;
+}
+
+/* input_addr is an InputAddr associated with the node given by mci.  Return
+ * the csrow that input_addr maps to, or -1 on failure (no csrow claims
+ * input_addr).
+ */
+static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr)
+{
+       struct k8_pvt *pvt;
+       int i;
+       u32 dcsb, dcsm;
+       u64 base, mask;
+
+       pvt = mci->pvt_info;
+
+       /* Here we use the DRAM CS Base (section 3.5.4) and DRAM CS Mask
+        * (section 3.5.5) registers.  For each CS base/mask register pair,
+        * test the condition shown near the start of section 3.5.4 (p. 84).
+        */
+
+       for (i = 0; i < K8_NR_CSROWS; i++) {
+               dcsb = pvt->dcsb[i];
+               dcsm = pvt->dcsm[i];
+
+               if ((dcsb & 0x01) == 0) {
+                       debugf2("input_addr_to_csrow: CSBE bit is cleared "
+                               "for csrow %d (node %d)\n", i,
+                               pvt->node_id);
+                       continue;  /* CSBE bit is cleared */
+               }
+
+               base = base_from_dcsb(dcsb);
+               mask = ~mask_from_dcsm(dcsm);
+
+               if ((input_addr & mask) == (base & mask)) {
+                       debugf2("InputAddr 0x%lx matches csrow %d "
+                               "(node %d)\n", (unsigned long) input_addr, i,
+                               pvt->node_id);
+                       return i;  /* success: csrow i matches */
+               }
+       }
+
+       debugf2("no matching csrow for InputAddr 0x%lx (node %d)\n",
+               (unsigned long) input_addr, pvt->node_id);
+       return -1;  /* failed to find matching csrow */
+}
+
+/* input_addr is an InputAddr associated with the node represented by mci.
+ * Translate input_addr to a DramAddr and return the result.
+ */
+static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
+{
+       struct k8_pvt *pvt;
+       int node_id, intlv_shift;
+       u64 bits, dram_addr;
+       u32 intlv_sel;
+
+       /* Near the start of section 3.4.4 (p. 70), the k8 documentation shows
+        * how to translate a DramAddr to an InputAddr.  Here we reverse this
+        * procedure.  When translating from a DramAddr to an InputAddr, the
+        * bits used for node interleaving are discarded.  Here we recover
+        * these bits from the IntlvSel field of the DRAM Limit register
+        * (section 3.4.4.2) for the node that input_addr is associated with.
+        */
+
+       pvt = mci->pvt_info;
+       node_id = pvt->node_id;
+       BUG_ON((node_id < 0) || (node_id > 7));
+       intlv_shift = num_node_interleave_bits((pvt->dbr[0] >> 8) & 0x07);
+
+       if (intlv_shift == 0) {
+               debugf1("node interleaving disabled: InputAddr 0x%lx "
+                       "translates to DramAddr of same value\n",
+                       (unsigned long) input_addr);
+               return input_addr;
+       }
+
+       bits = ((input_addr & 0xffffff000ull) << intlv_shift) +
+              (input_addr & 0xfff);
+       intlv_sel = pvt->dlr[node_id] & (((1 << intlv_shift) - 1) << 8);
+       dram_addr = bits + (intlv_sel << 4);
+       debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx "
+               "(%d node interleave bits)\n", (unsigned long) input_addr,
+               (unsigned long) dram_addr, intlv_shift);
+       return dram_addr;
+}
+
+/* dram_addr is a DramAddr that maps to the node represented by mci.  Convert
+ * dram_addr to a SysAddr and return the result.
+ */
+static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr)
+{
+       struct k8_pvt *pvt;
+       u64 hole_base, hole_offset, hole_size, base, limit, sys_addr;
+
+       pvt = mci->pvt_info;
+
+       if (!get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size)) {
+               if ((dram_addr >= hole_base) &&
+                   (dram_addr < (hole_base + hole_size))) {
+                       /* use DHAR to translate DramAddr to SysAddr */
+                       sys_addr = dram_addr + hole_offset;
+                       debugf1("using DHAR to translate DramAddr 0x%lx to "
+                               "SysAddr 0x%lx\n", (unsigned long) dram_addr,
+                               (unsigned long) sys_addr);
+                       return sys_addr;
+               }
+       }
+
+       get_base_and_limit(pvt, pvt->node_id, &base, &limit);
+       sys_addr = dram_addr + base;
+
+       /* The sys_addr we have computed up to this point is a 40-bit value
+        * because the k8 deals with 40-bit values.  However, the value we are
+        * supposed to return is a full 64-bit physical address.  The AMD
+        * x86-64 architecture specifies that the most significant implemented
+        * address bit through bit 63 of a physical address must be either all
+        * 0s or all 1s.  Therefore we sign-extend the 40-bit sys_addr to a
+        * 64-bit value below.  See section 3.4.2 of AMD publication 24592:
+        * AMD x86-64 Architecture Programmer's Manual Volume 1 Application
+        * Programming.
+        */
+       sys_addr |= ~((sys_addr & (1ull << 39)) - 1);
+
+       debugf1("Using DRAM Base register for node %d to translate "
+               "DramAddr 0x%lx to SysAddr 0x%lx\n", pvt->node_id,
+               (unsigned long) dram_addr, (unsigned long) sys_addr);
+       return sys_addr;
+}
+
+/* input_addr is an InputAddr associated with the node given by mci.
+ * Translate input_addr to a SysAddr and return the result.
+ */
+static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci,
+               u64 input_addr)
+{
+       return dram_addr_to_sys_addr(
+                       mci, input_addr_to_dram_addr(mci, input_addr));
+}
+
+/* Find the minimum and maximum InputAddr values that map to the given csrow.
+ * Pass back these values in *input_addr_min and *input_addr_max.
+ */
+static void find_csrow_limits(struct mem_ctl_info *mci, int csrow,
+               u64 *input_addr_min, u64 *input_addr_max)
+{
+       struct k8_pvt *pvt;
+       u64 base, mask;
+
+       pvt = mci->pvt_info;
+       BUG_ON((csrow < 0) || (csrow >= K8_NR_CSROWS));
+       base = base_from_dcsb(pvt->dcsb[csrow]);
+       mask = mask_from_dcsm(pvt->dcsm[csrow]);
+       *input_addr_min = base & ~mask;
+
+       /* To find the max InputAddr for the csrow, start with the base
+        * address and set all bits that are "don't care" bits in the test at
+        * the start of section 3.5.4 (p. 84).  The "don't care" bits are all
+        * set bits in the mask and all bits in the gaps between bit ranges
+        * [35-25] and [19-13].  The value 0x1f01fff represents bits [24-20]
+        * and [12-0], which are all bits in the above-mentioned gaps.
+        */
+       *input_addr_max = base | mask | 0x1f01fff;
+}
+
+/* Extract error address from MCA NB Address Low (section 3.6.4.5) and
+ * MCA NB Address High (section 3.6.4.6) register values and return the
+ * result.
+ */
+static inline u64 error_address_from_k8_error_info(
+               struct k8_error_info *info)
+{
+       return (((u64) (info->error_info.nbeah & 0xff)) << 32) +
+              (info->error_info.nbeal & ~0x03);
+}
+
+static inline void error_address_to_page_and_offset(u64 error_address,
+               u32 *page, u32 *offset)
+{
+       *page = (u32) (error_address >> PAGE_SHIFT);
+       *offset = ((u32) error_address) & ~PAGE_MASK;
+}
+
+/* Return 1 if registers contain valid error information.  Else return 0. */
+static inline int k8_error_info_valid(struct k8_error_info_regs *regs)
+{
+       return ((regs->nbsh & K8_NBSH_VALID_BIT) != 0);
+}
+
+/* return 0 if regs contains valid error info; else return 1 */
+static int k8_get_error_info_regs(struct mem_ctl_info *mci,
+               struct k8_error_info_regs *regs)
+{
+       struct k8_pvt *pvt;
+
+       pvt = mci->pvt_info;
+       pci_read_config_dword(pvt->misc_ctl, K8_NBSH, &regs->nbsh);
+
+       if (!k8_error_info_valid(regs))
+               return 1;
+
+       pci_read_config_dword(pvt->misc_ctl, K8_NBSL, &regs->nbsl);
+       pci_read_config_dword(pvt->misc_ctl, K8_NBEAH, &regs->nbeah);
+       pci_read_config_dword(pvt->misc_ctl, K8_NBEAL, &regs->nbeal);
+       return 0;
+}
+
+static void k8_get_error_info(struct mem_ctl_info *mci,
+               struct k8_error_info *info)
+{
+       struct k8_pvt *pvt;
+       struct k8_error_info_regs regs;
+
+       pvt = mci->pvt_info;
+       info->race_condition_detected = 0;
+
+       if (k8_get_error_info_regs(mci, &info->error_info))
+               return;
+
+       /*
+        * Here's the problem with the K8's EDAC reporting:
+        * There are four registers which report pieces of error
+        * information.  These four registers are shared between
+        * CEs and UEs.  Furthermore, contrary to what is stated in
+        * the OBKG, the overflow bit is never used!  Every error
+        * always updates the reporting registers.
+        *
+        * Can you see the race condition?  All four error reporting
+        * registers must be read before a new error updates them!
+        * There is no way to read all four registers atomically.  The
+        * best than can be done is to detect that a race has occured
+        * and then report the error without any kind of precision.
+        *
+        * What is still positive is that errors are
+        * still reported and thus problems can still be detected -
+        * just not localized because the syndrome and address are
+        * spread out across registers.
+        *
+        * Grrrrr!!!!!  Here's hoping that AMD fixes this in some
+        * future K8 rev. UEs and CEs should have separate
+        * register sets with proper overflow bits that are used!
+        * At very least the problem can be fixed by honoring the
+        * ErrValid bit in nbsh and not updating registers - just
+        * set the overflow bit - unless the current error is CE
+        * and the new error is UE which would be the only situation
+        * for overwriting the current values.
+        */
+
+       regs = info->error_info;
+
+       /* Use info from the second read - most current */
+       if (unlikely(k8_get_error_info_regs(mci, &info->error_info)))
+               return;
+
+       /* clear the error */
+       pci_write_bits32(pvt->misc_ctl, K8_NBSH, 0, K8_NBSH_VALID_BIT);
+
+       pci_read_config_dword(pvt->misc_ctl, K8_NBCFG, &info->nbcfg);
+       info->race_condition_detected =
+           ((regs.nbsh != info->error_info.nbsh) ||
+            (regs.nbsl != info->error_info.nbsl) ||
+            (regs.nbeah != info->error_info.nbeah) ||
+            (regs.nbeal != info->error_info.nbeal));
+}
+
+static inline void decode_gart_tlb_error(struct mem_ctl_info *mci,
+                                        struct k8_error_info *info)
+{
+       u32 err_code;
+       u32 ec_tt;              /* error code transaction type (2b) */
+       u32 ec_ll;              /* error code cache level (2b) */
+
+       err_code = info->error_info.nbsl & 0xffffUL;
+       ec_tt = (err_code >> 2) & 0x03UL;
+       ec_ll = (err_code >> 0) & 0x03UL;
+       k8_mc_printk(mci, KERN_ERR,
+                    "GART TLB errorr: transaction type(%s), "
+                    "cache level(%s)\n", tt_msgs[ec_tt], ll_msgs[ec_ll]);
+}
+
+static inline void decode_cache_error(struct mem_ctl_info *mci,
+                                     struct k8_error_info *info)
+{
+       u32 err_code;
+       u32 ec_rrrr;            /* error code memory transaction (4b) */
+       u32 ec_tt;              /* error code transaction type (2b) */
+       u32 ec_ll;              /* error code cache level (2b) */
+
+       err_code = info->error_info.nbsl & 0xffffUL;
+       ec_rrrr = (err_code >> 4) & 0x0fUL;
+       ec_tt = (err_code >> 2) & 0x03UL;
+       ec_ll = (err_code >> 0) & 0x03UL;
+       k8_mc_printk(mci, KERN_ERR,
+                    "cache heirarchy error: memory transaction type(%s), "
+                    "transaction type(%s), cache level(%s)\n",
+                    memtt_msgs[ec_rrrr], tt_msgs[ec_tt], ll_msgs[ec_ll]);
+}
+
+/* sys_addr is an error address (a SysAddr) extracted from the MCA NB Address
+ * Low (section 3.6.4.5) and MCA NB Address High (section 3.6.4.6) registers
+ * of a node that detected an ECC memory error.  mci represents the node that
+ * the error address maps to (possibly different from the node that detected
+ * the error).  Return the number of the csrow that sys_addr maps to, or -1 on
+ * error.
+ */
+static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr)
+{
+       int csrow;
+
+       csrow = input_addr_to_csrow(mci,
+                                   sys_addr_to_input_addr(mci, sys_addr));
+
+       if (csrow == -1)
+               k8_mc_printk(mci, KERN_ERR,
+                            "Failed to translate InputAddr to csrow for "
+                            "address 0x%lx\n", (unsigned long) sys_addr);
+
+       return csrow;
+}
+
+static void k8_handle_ce(struct mem_ctl_info *mci, struct k8_error_info *info)
+{
+       struct k8_pvt *pvt;
+       unsigned syndrome;
+       u64 error_address;
+       u32 page, offset;
+       int channel, csrow;
+       struct mem_ctl_info *log_mci, *src_mci;
+
+       log_mci = mci;
+       pvt = mci->pvt_info;
+
+       if ((info->error_info.nbsh & BIT(26)) == 0)
+               goto no_info;  /* error address not valid */
+
+       error_address = error_address_from_k8_error_info(info);
+       syndrome = ((info->error_info.nbsh >> 15) & 0xff);
+
+       if (info->nbcfg & BIT(23)) {
+               /* chipkill ecc mode */
+               syndrome += (info->error_info.nbsl >> 16) & 0xff00;
+               channel = chan_from_chipkill_syndrome(syndrome);
+
+               if (channel < 0) {
+                       /* If the syndrome couldn't be found then the race
+                        * condition for error reporting registers likely
+                        * occurred.  There's alot more in doubt than just the
+                        * channel.  Might as well just log the error without
+                        * any info.
+                        */
+                       k8_mc_printk(mci, KERN_WARNING,
+                                    "unknown syndrome 0x%x - possible error "
+                                    "reporting race\n", syndrome);
+                       goto no_info;
+               }
+       } else
+               /* non-chipkill ecc mode
+                *
+                * The k8 documentation is unclear about how to determine the
+                * channel number when using non-chipkill memory.  This method
+                * was obtained from email communication with someone at AMD.
+                */
+               channel = ((error_address & BIT(3)) != 0);
+
+       /* Find out which node the error address belongs to.  This may be
+        * different from the node that detected the error.
+        */
+       if ((src_mci = find_mc_by_sys_addr(mci, error_address)) == NULL) {
+               k8_mc_printk(mci, KERN_ERR,
+                            "failed to map error address 0x%lx to a node\n",
+                            (unsigned long) error_address);
+               goto no_info;
+       }
+
+       log_mci = src_mci;
+
+       if ((csrow = sys_addr_to_csrow(log_mci, error_address)) < 0)
+               goto no_info;
+
+       error_address_to_page_and_offset(error_address, &page, &offset);
+       edac_mc_handle_ce(log_mci, page, offset, syndrome, csrow, channel,
+                         EDAC_MOD_STR);
+       return;
+
+no_info:
+       edac_mc_handle_ce_no_info(log_mci,EDAC_MOD_STR);
+}
+
+static void k8_handle_ue(struct mem_ctl_info *mci, struct k8_error_info *info)
+{
+       int csrow;
+       u64 error_address;
+       u32 page, offset;
+       struct mem_ctl_info *log_mci, *src_mci;
+
+       log_mci = mci;
+
+       if ((info->error_info.nbsh & BIT(26)) == 0)
+               goto no_info;  /* error address not valid */
+
+       error_address = error_address_from_k8_error_info(info);
+
+       /* Find out which node the error address belongs to.  This may be
+        * different from the node that detected the error.
+        */
+       if ((src_mci = find_mc_by_sys_addr(mci, error_address)) == NULL) {
+               k8_mc_printk(mci, KERN_ERR,
+                            "failed to map error address 0x%lx to a node\n",
+                            (unsigned long) error_address);
+               goto no_info;
+       }
+
+       log_mci = src_mci;
+
+       if ((csrow = sys_addr_to_csrow(log_mci, error_address)) < 0)
+               goto no_info;
+
+       error_address_to_page_and_offset(error_address, &page, &offset);
+       edac_mc_handle_ue(log_mci, page, offset, csrow, EDAC_MOD_STR);
+       return;
+
+no_info:
+       edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
+}
+
+static void decode_bus_error(struct mem_ctl_info *mci,
+               struct k8_error_info *info)
+{
+       u32 err_code, ext_ec;
+       u32 ec_pp;    /* error code participating processor (2p) */
+       u32 ec_to;    /* error code timed out (1b) */
+       u32 ec_rrrr;  /* error code memory transaction (4b) */
+       u32 ec_ii;    /* error code memory or I/O (2b) */
+       u32 ec_ll;    /* error code cache level (2b) */
+
+       debugf0("MC%d: %s()\n", mci->mc_idx, __func__);
+       err_code = info->error_info.nbsl & 0xffffUL;
+       ec_pp = (err_code >> 9) & 0x03UL;
+       ec_to = (err_code >> 8) & 0x01UL;
+       ec_rrrr = (err_code >> 4) & 0x0fUL;
+       ec_ii = (err_code >> 2) & 0x03UL;
+       ec_ll = (err_code >> 0) & 0x03UL;
+       ext_ec = (info->error_info.nbsl >> 16) & 0xfUL;
+
+       /* FIXME - these should report through EDAC channels */
+       k8_mc_printk(mci, KERN_ERR, "general bus error: participating "
+                    "processor(%s), time-out(%s) memory transaction "
+                    "type(%s), mem or i/o(%s), cache level(%s)\n",
+                    pp_msgs[ec_pp], to_msgs[ec_to], memtt_msgs[ec_rrrr],
+                    ii_msgs[ec_ii], ll_msgs[ec_ll]);
+
+       if (ec_pp & 0x02)
+               return;  /* We aren't the node involved */
+
+       /* FIXME - other errors should have other error handling mechanisms */
+       if (ext_ec && (ext_ec != 0x8)) {
+               k8_mc_printk(mci, KERN_ERR,
+                            "no special error handling for this error\n");
+               return;
+       }
+
+       if (info->error_info.nbsh & BIT(14))
+               k8_handle_ce(mci, info);
+       else if (info->error_info.nbsh & BIT(13))
+               k8_handle_ue(mci, info);
+
+       /* If main error is CE then overflow must be CE.  If main error is UE
+        * then overflow is unknown.  We'll call the overflow a CE - if
+        * panic_on_ue is set then we're already panic'ed and won't arrive
+        * here.  If panic_on_ue is not set then apparently someone doesn't
+        * think that UE's are catastrophic.
+        */
+       if (info->error_info.nbsh & BIT(30))
+               edac_mc_handle_ce_no_info(mci,
+                   EDAC_MOD_STR " Error Overflow set");
+}
+
+/* return 1 if error found or 0 if error not found */
+static int k8_process_error_info(struct mem_ctl_info *mci,
+               struct k8_error_info *info, int handle_errors)
+{
+       struct k8_pvt *pvt;
+       struct k8_error_info_regs *regs;
+       u32 err_code, ext_ec;
+       int gart_tlb_error;
+
+       pvt = mci->pvt_info;
+
+       /* check for an error */
+       if (!k8_error_info_valid(&info->error_info))
+               return 0;
+
+       if (!handle_errors)
+               return 1;
+
+       if (info->race_condition_detected)
+               k8_mc_printk(mci, KERN_WARNING, "race condition detected!\n");
+
+       gart_tlb_error = 0;
+       regs = &info->error_info;
+       err_code = info->error_info.nbsl & 0xffffUL;
+       ext_ec = (info->error_info.nbsl >> 16) & 0x0fUL;
+       debugf1("NorthBridge ERROR: mci(0x%p) node(%d) ErrAddr(0x%.8x-%.8x) "
+               "nbsh(0x%.8x) nbsl(0x%.8x)\n", mci, pvt->node_id, regs->nbeah,
+               regs->nbeal, regs->nbsh, regs->nbsl);
+
+       if ((err_code & 0xfff0UL) == 0x0010UL) {
+               debugf1("GART TLB error\n");
+               gart_tlb_error = 1;
+               decode_gart_tlb_error(mci, info);
+       } else if ((err_code & 0xff00UL) == 0x0100UL) {
+               debugf1("Cache error\n");
+               decode_cache_error(mci, info);
+       } else if ((err_code & 0xf800UL) == 0x0800UL) {
+               debugf1("Bus error\n");
+               decode_bus_error(mci, info);
+       } else
+               /* shouldn't reach here! */
+               k8_mc_printk(mci, KERN_WARNING,
+                            "%s(): unknown MCE error 0x%x\n", __func__,
+                            err_code);
+
+       k8_mc_printk(mci, KERN_ERR, "extended error code: %s\n",
+                    ext_msgs[ext_ec]);
+
+       if (((ext_ec >= 1 && ext_ec <= 4) || (ext_ec == 6)) &&
+           ((info->error_info.nbsh >> 4) & 0x07UL))
+               k8_mc_printk(mci, KERN_ERR,
+                   "Error on hypertransport link: %s\n",
+                   htlink_msgs[(info->error_info.nbsh >> 4) & 0x07UL]);
+
+       /* GART errors are benign as per AMD, do not panic on them */
+       if (!gart_tlb_error && (regs->nbsh & BIT(29))) {
+               k8_mc_printk(mci, KERN_CRIT, "uncorrected error\n");
+               edac_mc_handle_ue_no_info(mci, "UE bit is set\n");
+       }
+
+       if (regs->nbsh & BIT(25))
+               panic("MC%d: processor context corrupt", mci->mc_idx);
+
+       return 1;
+}
+
+static void k8_check(struct mem_ctl_info *mci)
+{
+       struct k8_error_info info;
+
+       debugf3("%s()\n", __func__);
+       k8_get_error_info(mci, &info);
+       k8_process_error_info(mci, &info, 1);
+}
+
+static int k8_get_devs(struct mem_ctl_info *mci, int dev_idx)
+{
+       const struct k8_dev_info *k8_dev = &k8_devs[dev_idx];
+       struct k8_pvt *pvt;
+       struct pci_dev *pdev;
+
+       pdev = to_pci_dev(mci->dev);
+       pvt = mci->pvt_info;
+
+       /* The address mapping device provides a table that indicates which
+        * physical address ranges are owned by which node.  Each node's
+        * memory controller has memory controller addresses that begin at
+        * 0x0.
+        */
+       pvt->addr_map = pci_get_related_function(PCI_VENDOR_ID_AMD,
+                                                k8_dev->addr_map, pdev);
+
+       if (pvt->addr_map == NULL) {
+               k8_printk(KERN_ERR, "error address map device not found: "
+                         "vendor %x device 0x%x (broken BIOS?)\n",
+                         PCI_VENDOR_ID_AMD, k8_dev->addr_map);
+               return 1;
+       }
+
+       debugf1("Addr Map device PCI Bus ID:\t%s\n",
+               pci_name(pvt->addr_map));
+
+       pvt->misc_ctl = pci_get_related_function(PCI_VENDOR_ID_AMD,
+                                                k8_dev->misc_ctl, pdev);
+
+       if (pvt->misc_ctl == NULL) {
+               pci_dev_put(pvt->addr_map);
+               pvt->addr_map = NULL;
+               k8_printk(KERN_ERR, "error miscellaneous device not found: "
+                         "vendor %x device 0x%x (broken BIOS?)\n",
+                         PCI_VENDOR_ID_AMD, k8_dev->misc_ctl);
+               return 1;
+       }
+
+       debugf1("Misc device PCI Bus ID:\t\t%s\n",
+               pci_name(pvt->misc_ctl));
+
+       return 0;
+}
+
+static void k8_get_mc_regs(struct mem_ctl_info *mci)
+{
+       struct k8_pvt *pvt;
+       struct pci_dev *pdev;
+       int i;
+
+       pdev = to_pci_dev(mci->dev);
+       pvt = mci->pvt_info;
+       debugf1("k8 regs:\n");
+
+       for (i = 0; i < MAX_K8_NODES; i++) {
+               pci_read_config_dword(pvt->addr_map, K8_DBR + (i * 8),
+                                     &pvt->dbr[i]);
+               pci_read_config_dword(pvt->addr_map, K8_DLR + (i * 8),
+                                     &pvt->dlr[i]);
+               debugf1("    dbr[%d]: 0x%x\n", i, pvt->dbr[i]);
+               debugf1("    dlr[%d]: 0x%x\n", i, pvt->dlr[i]);
+       }
+
+       pci_read_config_dword(pvt->misc_ctl, K8_NBCAP, &pvt->nbcap);
+       debugf1("    nbcap: %u\n", pvt->nbcap);
+
+       for (i = 0; i < K8_NR_CSROWS; i++) {
+               pci_read_config_dword(pdev, K8_DCSB + (i * 4), &pvt->dcsb[i]);
+               pci_read_config_dword(pdev, K8_DCSM + (i * 4), &pvt->dcsm[i]);
+               debugf1("    dcsb[%d]: 0x%x\n", i, pvt->dcsb[i]);
+               debugf1("    dcsm[%d]: 0x%x\n", i, pvt->dcsm[i]);
+       }
+
+       pci_read_config_dword(pvt->addr_map, K8_DHAR, &pvt->dhar);
+       pci_read_config_dword(pdev, K8_DBAM, &pvt->dbam);
+       debugf1("    dhar: 0x%x\n", pvt->dhar);
+       debugf1("    dbam: 0x%x\n", pvt->dbam);
+}
+
+/* Return 1 if dual channel mode is active.  Else return 0. */
+static inline int dual_channel_active(u32 dcl)
+{
+       return (dcl >> 16) & 0x1;
+}
+
+static u32 csrow_nr_pages(int csrow_nr, struct k8_pvt *pvt)
+{
+       u32 cs;
+
+       /* The math on this doesn't look right on the surface because x/2*4
+        * can be simplified to x*2 but this expression makes use of the fact
+        * that it is integral math where 1/2=0
+        */
+       cs = (pvt->dbam >> ((csrow_nr / 2) * 4)) & 0xF;  /* PG88 */
+
+       /* This line is tricky. It collapses the table used by revision D and
+        * later to one that matches revision CG and earlier
+        */
+       cs -= (node_rev(pvt->node_id) >= OPTERON_CPU_REV_D) ?
+             (cs > 8 ? 4 : (cs > 5 ? 3 : (cs > 2 ? 1 : 0))) : 0;
+
+       /* 25 is 32MiB minimum DIMM size */
+       return 1 << (cs + 25 - PAGE_SHIFT + dual_channel_active(pvt->dcl));
+}
+
+static int k8_init_csrows(struct mem_ctl_info *mci)
+{
+       struct csrow_info *csrow;
+       struct k8_pvt *pvt;
+       int i, empty;
+       u64 input_addr_min, input_addr_max, sys_addr;
+       u32 nbcfg;
+
+       pvt = mci->pvt_info;
+       pci_read_config_dword(pvt->misc_ctl, K8_NBCFG, &nbcfg);
+       empty = 1;
+
+       for (i = 0; i < K8_NR_CSROWS; i++) {
+               csrow = &mci->csrows[i];
+
+               if ((pvt->dcsb[i] & 0x01) == 0) {
+                       debugf1("csrow %d empty for node %d\n", i,
+                               pvt->node_id);
+                       continue;  /* empty */
+               }
+
+               debugf1("revision for this node (%d) is %d\n",
+                       pvt->node_id, node_rev(pvt->node_id));
+               empty = 0;
+               csrow->nr_pages = csrow_nr_pages(i, pvt);
+               find_csrow_limits(mci, i, &input_addr_min, &input_addr_max);
+               sys_addr = input_addr_to_sys_addr(mci, input_addr_min);
+               csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT);
+               sys_addr = input_addr_to_sys_addr(mci, input_addr_max);
+               csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT);
+               csrow->page_mask = ~mask_from_dcsm(pvt->dcsm[i]);
+               csrow->grain = 8;  /* 8 bytes of resolution */
+               csrow->mtype = ((pvt->dcl >> 18) & 0x1) ? MEM_DDR : MEM_RDDR;
+               csrow->dtype = ((pvt->dcl >> (20 + (i / 2))) & 0x01) ?
+                              DEV_X4 : DEV_UNKNOWN;
+               debugf1("for node %d csrow %d:\n    nr_pages: %u "
+                       "input_addr_min: 0x%lx input_addr_max: 0x%lx "
+                       "sys_addr: 0x%lx first_page: 0x%lx last_page: 0x%lx "
+                       "page_mask: 0x%lx\n", pvt->node_id, i,
+                       (unsigned) csrow->nr_pages,
+                       (unsigned long) input_addr_min,
+                       (unsigned long) input_addr_max,
+                       (unsigned long) sys_addr,
+                       csrow->first_page, csrow->last_page,
+                       csrow->page_mask);
+
+               if (nbcfg & BIT(22))
+                       csrow->edac_mode = (nbcfg & BIT(23)) ?
+                                          EDAC_S4ECD4ED : EDAC_SECDED;
+               else
+                       csrow->edac_mode = EDAC_NONE;
+       }
+
+       return empty;
+}
+
+static void k8_enable_error_reporting(struct mem_ctl_info *mci)
+{
+       struct k8_pvt *pvt;
+       u32 mc4ctl_l=0, mc4ctl_h=0, mcgctl_l=0, mcgctl_h=0;
+
+       pvt = mci->pvt_info;
+       pci_write_bits32(pvt->misc_ctl, K8_NBCTL, 0x3UL, 0x3UL);
+       do_rdmsr(pvt->node_id, K8_MSR_MC4CTL, &mc4ctl_l, &mc4ctl_h);
+       mc4ctl_l |= BIT(0) | BIT(1);
+       do_wrmsr(pvt->node_id, K8_MSR_MC4CTL, mc4ctl_l, mc4ctl_h);
+       do_rdmsr(pvt->node_id, K8_MSR_MC4CTL, &mc4ctl_l, &mc4ctl_h);
+       do_rdmsr(pvt->node_id, K8_MSR_MCGCTL, &mcgctl_l, &mcgctl_h);
+       mcgctl_l |= BIT(4);
+       do_wrmsr(pvt->node_id, K8_MSR_MCGCTL, mcgctl_l, mcgctl_h);
+       do_rdmsr(pvt->node_id, K8_MSR_MCGCTL, &mcgctl_l, &mcgctl_h);
+}
+
+static int k8_probe1(struct pci_dev *pdev, int dev_idx)
+{
+       struct mem_ctl_info *mci;
+       struct k8_pvt *pvt;
+       u32 dcl, dual_channel;
+
+       debugf0("%s()\n", __func__);
+       build_node_revision_table();
+       debugf1("pdev bus %u devfn %u\n", pdev->bus->number, pdev->devfn);
+       pci_read_config_dword(pdev, K8_DCL, &dcl);
+       dual_channel = dual_channel_active(dcl);
+       debugf1("dual_channel is %u (dcl is 0x%x)\n", dual_channel, dcl);
+       mci = edac_mc_alloc(sizeof(*pvt), K8_NR_CSROWS, dual_channel + 1);
+
+       if (mci == NULL)
+               return -ENOMEM;
+
+       debugf0("%s(): mci = %p\n", __func__, mci);
+       pvt = mci->pvt_info;
+       pvt->dcl = dcl;
+       mci->dev = &pdev->dev;
+       pvt->node_id = MCI_TO_NODE_ID(mci);
+
+       if (k8_get_devs(mci, dev_idx))
+               goto fail0;
+
+       k8_get_mc_regs(mci);
+       mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR;
+       mci->edac_ctl_cap = EDAC_FLAG_NONE;
+       debugf1("Initializing mci->edac_cap to EDAC_FLAG_NONE\n");
+       mci->edac_cap = EDAC_FLAG_NONE;
+
+       if ((pvt->nbcap >> 3) & 0x1)
+               mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+
+       if ((pvt->nbcap >> 4) & 0x1)
+               mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+
+       if ((pvt->dcl >> 17) & 0x1) {
+               debugf1("setting EDAC_FLAG_SECDED in mci->edac_cap\n");
+               mci->edac_cap |= EDAC_FLAG_SECDED;
+
+               if (dual_channel) {
+                       debugf1("setting EDAC_FLAG_S4ECD4ED in "
+                               "mci->edac_cap\n");
+                       mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+               }
+       }
+
+       mci->mod_name = EDAC_MOD_STR;
+       mci->mod_ver = EDAC_K8_VERSION;
+       mci->ctl_name = k8_devs[dev_idx].ctl_name;
+       mci->edac_check = k8_check;
+       mci->ctl_page_to_phys = NULL;
+
+       if (k8_init_csrows(mci)) {
+               debugf1("Setting mci->edac_cap to EDAC_FLAG_NONE "
+                       "because k8_init_csrows() returned nonzero "
+                       "value\n");
+               mci->edac_cap = EDAC_FLAG_NONE;  /* no csrows found */
+       } else
+               k8_enable_error_reporting(mci);
+
+       if (edac_mc_add_mc(mci, pvt->node_id)) {
+               debugf1("%s(): failed edac_mc_add_mc()\n", __func__);
+               /* FIXME: perhaps some code should go here that disables error
+                * reporting if we just enabled it
+                */
+               goto fail1;
+       }
+
+       debugf1("%s(): success\n", __func__);
+       return 0;
+
+fail1:
+       pci_dev_put(pvt->addr_map);
+       pci_dev_put(pvt->misc_ctl);
+
+fail0:
+       edac_mc_free(mci);
+       return -ENODEV;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit k8_init_one(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+       debugf0("%s()\n", __func__);
+
+       /* wake up and enable device */
+       return pci_enable_device(pdev) ?
+           -EIO : k8_probe1(pdev, ent->driver_data);
+}
+
+static void __devexit k8_remove_one(struct pci_dev *pdev)
+{
+       struct mem_ctl_info *mci;
+       struct k8_pvt *pvt;
+
+       debugf0("%s()\n", __func__);
+
+       if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
+               return;
+
+       pvt = mci->pvt_info;
+       pci_dev_put(pvt->addr_map);
+       pci_dev_put(pvt->misc_ctl);
+       edac_mc_free(mci);
+}
+
+static const struct pci_device_id k8_pci_tbl[] __devinitdata = {
+       {PCI_VEND_DEV(AMD, OPT_2_MEMCTL), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+        OPTERON},
+       {0,}                    /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, k8_pci_tbl);
+
+static struct pci_driver k8_driver = {
+       .name = EDAC_MOD_STR,
+       .probe = k8_init_one,
+       .remove = __devexit_p(k8_remove_one),
+       .id_table = k8_pci_tbl,
+};
+
+int __init k8_init(void)
+{
+       return pci_module_init(&k8_driver);
+}
+
+static void __exit k8_exit(void)
+{
+       pci_unregister_driver(&k8_driver);
+}
+
+module_init(k8_init);
+module_exit(k8_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for AMD K8 memory controllers - " EDAC_K8_VERSION );
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
new file mode 100644 (file)
index 0000000..35ad1b0
--- /dev/null
@@ -0,0 +1,1455 @@
+/*
+    abituguru.c Copyright (c) 2005-2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU 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.
+*/
+/*
+    This driver supports the sensor part of the custom Abit uGuru chip found
+    on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM /
+    etc voltage & frequency control is not supported!
+*/
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <asm/io.h>
+
+/* Banks */
+#define ABIT_UGURU_ALARM_BANK                  0x20 /* 1x 3 bytes */
+#define ABIT_UGURU_SENSOR_BANK1                        0x21 /* 16x volt and temp */
+#define ABIT_UGURU_FAN_PWM                     0x24 /* 3x 5 bytes */
+#define ABIT_UGURU_SENSOR_BANK2                        0x26 /* fans */
+/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */
+#define ABIT_UGURU_MAX_BANK1_SENSORS           16
+/* Warning if you increase one of the 2 MAX defines below to 10 or higher you
+   should adjust the belonging _NAMES_LENGTH macro for the 2 digit number! */
+/* max nr of sensors in bank2, currently mb's with max 6 fans are known */
+#define ABIT_UGURU_MAX_BANK2_SENSORS           6
+/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */
+#define ABIT_UGURU_MAX_PWMS                    5
+/* uGuru sensor bank 1 flags */                             /* Alarm if: */
+#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE      0x01 /*  temp over warn */
+#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE      0x02 /*  volt over max */
+#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE       0x04 /*  volt under min */
+#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG                0x10 /* temp is over warn */
+#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG                0x20 /* volt is over max */
+#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG         0x40 /* volt is under min */
+/* uGuru sensor bank 2 flags */                             /* Alarm if: */
+#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE                0x01 /*   fan under min */
+/* uGuru sensor bank common flags */
+#define ABIT_UGURU_BEEP_ENABLE                 0x08 /* beep if alarm */
+#define ABIT_UGURU_SHUTDOWN_ENABLE             0x80 /* shutdown if alarm */
+/* uGuru fan PWM (speed control) flags */
+#define ABIT_UGURU_FAN_PWM_ENABLE              0x80 /* enable speed control */
+/* Values used for conversion */
+#define ABIT_UGURU_FAN_MAX                     15300 /* RPM */
+/* Bank1 sensor types */
+#define ABIT_UGURU_IN_SENSOR                   0
+#define ABIT_UGURU_TEMP_SENSOR                 1
+#define ABIT_UGURU_NC                          2
+/* In many cases we need to wait for the uGuru to reach a certain status, most
+   of the time it will reach this status within 30 - 90 ISA reads, and thus we
+   can best busy wait. This define gives the total amount of reads to try. */
+#define ABIT_UGURU_WAIT_TIMEOUT                        125
+/* However sometimes older versions of the uGuru seem to be distracted and they
+   do not respond for a long time. To handle this we sleep before each of the
+   last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. */
+#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP          5
+/* Normally all expected status in abituguru_ready, are reported after the
+   first read, but sometimes not and we need to poll. */
+#define ABIT_UGURU_READY_TIMEOUT               5
+/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */
+#define ABIT_UGURU_MAX_RETRIES                 3
+#define ABIT_UGURU_RETRY_DELAY                 (HZ/5)
+/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */
+#define ABIT_UGURU_MAX_TIMEOUTS                        2
+/* utility macros */
+#define ABIT_UGURU_NAME                                "abituguru"
+#define ABIT_UGURU_DEBUG(level, format, arg...)                                \
+       if (level <= verbose)                                           \
+               printk(KERN_DEBUG ABIT_UGURU_NAME ": "  format , ## arg)
+/* Macros to help calculate the sysfs_names array length */
+/* sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
+   in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0 */
+#define ABITUGURU_IN_NAMES_LENGTH      (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14)
+/* sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0,
+   temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0 */
+#define ABITUGURU_TEMP_NAMES_LENGTH    (13 + 11 + 12 + 13 + 20 + 12 + 16)
+/* sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0,
+   fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0 */
+#define ABITUGURU_FAN_NAMES_LENGTH     (11 + 9 + 11 + 18 + 10 + 14)
+/* sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0,
+   pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0 */
+#define ABITUGURU_PWM_NAMES_LENGTH     (12 + 24 + 2 * 21 + 2 * 22)
+/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */
+#define ABITUGURU_SYSFS_NAMES_LENGTH   ( \
+       ABIT_UGURU_MAX_BANK1_SENSORS * ABITUGURU_IN_NAMES_LENGTH + \
+       ABIT_UGURU_MAX_BANK2_SENSORS * ABITUGURU_FAN_NAMES_LENGTH + \
+       ABIT_UGURU_MAX_PWMS * ABITUGURU_PWM_NAMES_LENGTH)
+
+/* All the macros below are named identical to the oguru and oguru2 programs
+   reverse engineered by Olle Sandberg, hence the names might not be 100%
+   logical. I could come up with better names, but I prefer keeping the names
+   identical so that this driver can be compared with his work more easily. */
+/* Two i/o-ports are used by uGuru */
+#define ABIT_UGURU_BASE                                0x00E0
+/* Used to tell uGuru what to read and to read the actual data */
+#define ABIT_UGURU_CMD                         0x00
+/* Mostly used to check if uGuru is busy */
+#define ABIT_UGURU_DATA                                0x04
+#define ABIT_UGURU_REGION_LENGTH               5
+/* uGuru status' */
+#define ABIT_UGURU_STATUS_WRITE                        0x00 /* Ready to be written */
+#define ABIT_UGURU_STATUS_READ                 0x01 /* Ready to be read */
+#define ABIT_UGURU_STATUS_INPUT                        0x08 /* More input */
+#define ABIT_UGURU_STATUS_READY                        0x09 /* Ready to be written */
+
+/* Constants */
+/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */
+static const int abituguru_bank1_max_value[2] = { 3494, 255000 };
+/* Min / Max allowed values for sensor2 (fan) alarm threshold, these values
+   correspond to 300-3000 RPM */
+static const u8 abituguru_bank2_min_threshold = 5;
+static const u8 abituguru_bank2_max_threshold = 50;
+/* Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4
+   are temperature trip points. */
+static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 };
+/* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a
+   special case the minium allowed pwm% setting for this is 30% (77) on
+   some MB's this special case is handled in the code! */
+static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 };
+static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 };
+
+
+/* Insmod parameters */
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Set to one to force detection.");
+static int bank1_types[ABIT_UGURU_MAX_BANK1_SENSORS] = { -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+module_param_array(bank1_types, int, NULL, 0);
+MODULE_PARM_DESC(bank1_types, "Bank1 sensortype autodetection override:\n"
+       "   -1 autodetect\n"
+       "    0 volt sensor\n"
+       "    1 temp sensor\n"
+       "    2 not connected");
+static int fan_sensors;
+module_param(fan_sensors, int, 0);
+MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru "
+       "(0 = autodetect)");
+static int pwms;
+module_param(pwms, int, 0);
+MODULE_PARM_DESC(pwms, "Number of PWMs on the uGuru "
+       "(0 = autodetect)");
+
+/* Default verbose is 2, since this driver is still in the testing phase */
+static int verbose = 2;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n"
+       "   0 normal output\n"
+       "   1 + verbose error reporting\n"
+       "   2 + sensors type probing info\n"
+       "   3 + retryable error reporting");
+
+
+/* For the Abit uGuru, we need to keep some data in memory.
+   The structure is dynamically allocated, at the same time when a new
+   abituguru device is allocated. */
+struct abituguru_data {
+       struct class_device *class_dev; /* hwmon registered device */
+       struct mutex update_lock;       /* protect access to data and uGuru */
+       unsigned long last_updated;     /* In jiffies */
+       unsigned short addr;            /* uguru base address */
+       char uguru_ready;               /* is the uguru in ready state? */
+       unsigned char update_timeouts;  /* number of update timeouts since last
+                                          successful update */
+
+       /* The sysfs attr and their names are generated automatically, for bank1
+          we cannot use a predefined array because we don't know beforehand
+          of a sensor is a volt or a temp sensor, for bank2 and the pwms its
+          easier todo things the same way.  For in sensors we have 9 (temp 7)
+          sysfs entries per sensor, for bank2 and pwms 6. */
+       struct sensor_device_attribute_2 sysfs_attr[
+               ABIT_UGURU_MAX_BANK1_SENSORS * 9 +
+               ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6];
+       /* Buffer to store the dynamically generated sysfs names */
+       char sysfs_names[ABITUGURU_SYSFS_NAMES_LENGTH];
+
+       /* Bank 1 data */
+       /* number of and addresses of [0] in, [1] temp sensors */
+       u8 bank1_sensors[2];
+       u8 bank1_address[2][ABIT_UGURU_MAX_BANK1_SENSORS];
+       u8 bank1_value[ABIT_UGURU_MAX_BANK1_SENSORS];
+       /* This array holds 3 entries per sensor for the bank 1 sensor settings
+          (flags, min, max for voltage / flags, warn, shutdown for temp). */
+       u8 bank1_settings[ABIT_UGURU_MAX_BANK1_SENSORS][3];
+       /* Maximum value for each sensor used for scaling in mV/millidegrees
+          Celsius. */
+       int bank1_max_value[ABIT_UGURU_MAX_BANK1_SENSORS];
+
+       /* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */
+       u8 bank2_sensors; /* actual number of bank2 sensors found */
+       u8 bank2_value[ABIT_UGURU_MAX_BANK2_SENSORS];
+       u8 bank2_settings[ABIT_UGURU_MAX_BANK2_SENSORS][2]; /* flags, min */
+
+       /* Alarms 2 bytes for bank1, 1 byte for bank2 */
+       u8 alarms[3];
+
+       /* Fan PWM (speed control) 5 bytes per PWM */
+       u8 pwms; /* actual number of pwms found */
+       u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5];
+};
+
+/* wait till the uguru is in the specified state */
+static int abituguru_wait(struct abituguru_data *data, u8 state)
+{
+       int timeout = ABIT_UGURU_WAIT_TIMEOUT;
+
+       while (inb_p(data->addr + ABIT_UGURU_DATA) != state) {
+               timeout--;
+               if (timeout == 0)
+                       return -EBUSY;
+               /* sleep a bit before our last few tries, see the comment on
+                  this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. */
+               if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP)
+                       msleep(0);
+       }
+       return 0;
+}
+
+/* Put the uguru in ready for input state */
+static int abituguru_ready(struct abituguru_data *data)
+{
+       int timeout = ABIT_UGURU_READY_TIMEOUT;
+
+       if (data->uguru_ready)
+               return 0;
+
+       /* Reset? / Prepare for next read/write cycle */
+       outb(0x00, data->addr + ABIT_UGURU_DATA);
+
+       /* Wait till the uguru is ready */
+       if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) {
+               ABIT_UGURU_DEBUG(1,
+                       "timeout exceeded waiting for ready state\n");
+               return -EIO;
+       }
+
+       /* Cmd port MUST be read now and should contain 0xAC */
+       while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+               timeout--;
+               if (timeout == 0) {
+                       ABIT_UGURU_DEBUG(1,
+                          "CMD reg does not hold 0xAC after ready command\n");
+                       return -EIO;
+               }
+               msleep(0);
+       }
+
+       /* After this the ABIT_UGURU_DATA port should contain
+          ABIT_UGURU_STATUS_INPUT */
+       timeout = ABIT_UGURU_READY_TIMEOUT;
+       while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) {
+               timeout--;
+               if (timeout == 0) {
+                       ABIT_UGURU_DEBUG(1,
+                               "state != more input after ready command\n");
+                       return -EIO;
+               }
+               msleep(0);
+       }
+
+       data->uguru_ready = 1;
+       return 0;
+}
+
+/* Send the bank and then sensor address to the uGuru for the next read/write
+   cycle. This function gets called as the first part of a read/write by
+   abituguru_read and abituguru_write. This function should never be
+   called by any other function. */
+static int abituguru_send_address(struct abituguru_data *data,
+       u8 bank_addr, u8 sensor_addr, int retries)
+{
+       /* assume the caller does error handling itself if it has not requested
+          any retries, and thus be quiet. */
+       int report_errors = retries;
+
+       for (;;) {
+               /* Make sure the uguru is ready and then send the bank address,
+                  after this the uguru is no longer "ready". */
+               if (abituguru_ready(data) != 0)
+                       return -EIO;
+               outb(bank_addr, data->addr + ABIT_UGURU_DATA);
+               data->uguru_ready = 0;
+
+               /* Wait till the uguru is ABIT_UGURU_STATUS_INPUT state again
+                  and send the sensor addr */
+               if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) {
+                       if (retries) {
+                               ABIT_UGURU_DEBUG(3, "timeout exceeded "
+                                       "waiting for more input state, %d "
+                                       "tries remaining\n", retries);
+                               set_current_state(TASK_UNINTERRUPTIBLE);
+                               schedule_timeout(ABIT_UGURU_RETRY_DELAY);
+                               retries--;
+                               continue;
+                       }
+                       if (report_errors)
+                               ABIT_UGURU_DEBUG(1, "timeout exceeded "
+                                       "waiting for more input state "
+                                       "(bank: %d)\n", (int)bank_addr);
+                       return -EBUSY;
+               }
+               outb(sensor_addr, data->addr + ABIT_UGURU_CMD);
+               return 0;
+       }
+}
+
+/* Read count bytes from sensor sensor_addr in bank bank_addr and store the
+   result in buf, retry the send address part of the read retries times. */
+static int abituguru_read(struct abituguru_data *data,
+       u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries)
+{
+       int i;
+
+       /* Send the address */
+       i = abituguru_send_address(data, bank_addr, sensor_addr, retries);
+       if (i)
+               return i;
+
+       /* And read the data */
+       for (i = 0; i < count; i++) {
+               if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
+                       ABIT_UGURU_DEBUG(retries ? 1 : 3,
+                               "timeout exceeded waiting for "
+                               "read state (bank: %d, sensor: %d)\n",
+                               (int)bank_addr, (int)sensor_addr);
+                       break;
+               }
+               buf[i] = inb(data->addr + ABIT_UGURU_CMD);
+       }
+
+       /* Last put the chip back in ready state */
+       abituguru_ready(data);
+
+       return i;
+}
+
+/* Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send
+   address part of the write is always retried ABIT_UGURU_MAX_RETRIES times. */
+static int abituguru_write(struct abituguru_data *data,
+       u8 bank_addr, u8 sensor_addr, u8 *buf, int count)
+{
+       /* We use the ready timeout as we have to wait for 0xAC just like the
+          ready function */
+       int i, timeout = ABIT_UGURU_READY_TIMEOUT;
+
+       /* Send the address */
+       i = abituguru_send_address(data, bank_addr, sensor_addr,
+               ABIT_UGURU_MAX_RETRIES);
+       if (i)
+               return i;
+
+       /* And write the data */
+       for (i = 0; i < count; i++) {
+               if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) {
+                       ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for "
+                               "write state (bank: %d, sensor: %d)\n",
+                               (int)bank_addr, (int)sensor_addr);
+                       break;
+               }
+               outb(buf[i], data->addr + ABIT_UGURU_CMD);
+       }
+
+       /* Now we need to wait till the chip is ready to be read again,
+          so that we can read 0xAC as confirmation that our write has
+          succeeded. */
+       if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
+               ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state "
+                       "after write (bank: %d, sensor: %d)\n", (int)bank_addr,
+                       (int)sensor_addr);
+               return -EIO;
+       }
+
+       /* Cmd port MUST be read now and should contain 0xAC */
+       while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+               timeout--;
+               if (timeout == 0) {
+                       ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after "
+                               "write (bank: %d, sensor: %d)\n",
+                               (int)bank_addr, (int)sensor_addr);
+                       return -EIO;
+               }
+               msleep(0);
+       }
+
+       /* Last put the chip back in ready state */
+       abituguru_ready(data);
+
+       return i;
+}
+
+/* Detect sensor type. Temp and Volt sensors are enabled with
+   different masks and will ignore enable masks not meant for them.
+   This enables us to test what kind of sensor we're dealing with.
+   By setting the alarm thresholds so that we will always get an
+   alarm for sensor type X and then enabling the sensor as sensor type
+   X, if we then get an alarm it is a sensor of type X. */
+static int __devinit
+abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
+                                  u8 sensor_addr)
+{
+       u8 val, buf[3];
+       int i, ret = -ENODEV; /* error is the most common used retval :| */
+
+       /* If overriden by the user return the user selected type */
+       if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR &&
+                       bank1_types[sensor_addr] <= ABIT_UGURU_NC) {
+               ABIT_UGURU_DEBUG(2, "assuming sensor type %d for bank1 sensor "
+                       "%d because of \"bank1_types\" module param\n",
+                       bank1_types[sensor_addr], (int)sensor_addr);
+               return bank1_types[sensor_addr];
+       }
+
+       /* First read the sensor and the current settings */
+       if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val,
+                       1, ABIT_UGURU_MAX_RETRIES) != 1)
+               return -ENODEV;
+
+       /* Test val is sane / usable for sensor type detection. */
+       if ((val < 10u) || (val > 240u)) {
+               printk(KERN_WARNING ABIT_UGURU_NAME
+                       ": bank1-sensor: %d reading (%d) too close to limits, "
+                       "unable to determine sensor type, skipping sensor\n",
+                       (int)sensor_addr, (int)val);
+               /* assume no sensor is there for sensors for which we can't
+                  determine the sensor type because their reading is too close
+                  to their limits, this usually means no sensor is there. */
+               return ABIT_UGURU_NC;
+       }
+
+       ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
+       /* Volt sensor test, enable volt low alarm, set min value ridicously
+          high. If its a volt sensor this should always give us an alarm. */
+       buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE;
+       buf[1] = 245;
+       buf[2] = 250;
+       if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
+                       buf, 3) != 3)
+               goto abituguru_detect_bank1_sensor_type_exit;
+       /* Now we need 20 ms to give the uguru time to read the sensors
+          and raise a voltage alarm */
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(HZ/50);
+       /* Check for alarm and check the alarm is a volt low alarm. */
+       if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
+                       ABIT_UGURU_MAX_RETRIES) != 3)
+               goto abituguru_detect_bank1_sensor_type_exit;
+       if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
+               if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
+                               sensor_addr, buf, 3,
+                               ABIT_UGURU_MAX_RETRIES) != 3)
+                       goto abituguru_detect_bank1_sensor_type_exit;
+               if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) {
+                       ABIT_UGURU_DEBUG(2, "  found volt sensor\n");
+                       ret = ABIT_UGURU_IN_SENSOR;
+                       goto abituguru_detect_bank1_sensor_type_exit;
+               } else
+                       ABIT_UGURU_DEBUG(2, "  alarm raised during volt "
+                               "sensor test, but volt low flag not set\n");
+       } else
+               ABIT_UGURU_DEBUG(2, "  alarm not raised during volt sensor "
+                       "test\n");
+
+       /* Temp sensor test, enable sensor as a temp sensor, set beep value
+          ridicously low (but not too low, otherwise uguru ignores it).
+          If its a temp sensor this should always give us an alarm. */
+       buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE;
+       buf[1] = 5;
+       buf[2] = 10;
+       if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
+                       buf, 3) != 3)
+               goto abituguru_detect_bank1_sensor_type_exit;
+       /* Now we need 50 ms to give the uguru time to read the sensors
+          and raise a temp alarm */
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout(HZ/20);
+       /* Check for alarm and check the alarm is a temp high alarm. */
+       if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
+                       ABIT_UGURU_MAX_RETRIES) != 3)
+               goto abituguru_detect_bank1_sensor_type_exit;
+       if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
+               if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
+                               sensor_addr, buf, 3,
+                               ABIT_UGURU_MAX_RETRIES) != 3)
+                       goto abituguru_detect_bank1_sensor_type_exit;
+               if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) {
+                       ABIT_UGURU_DEBUG(2, "  found temp sensor\n");
+                       ret = ABIT_UGURU_TEMP_SENSOR;
+                       goto abituguru_detect_bank1_sensor_type_exit;
+               } else
+                       ABIT_UGURU_DEBUG(2, "  alarm raised during temp "
+                               "sensor test, but temp high flag not set\n");
+       } else
+               ABIT_UGURU_DEBUG(2, "  alarm not raised during temp sensor "
+                       "test\n");
+
+       ret = ABIT_UGURU_NC;
+abituguru_detect_bank1_sensor_type_exit:
+       /* Restore original settings, failing here is really BAD, it has been
+          reported that some BIOS-es hang when entering the uGuru menu with
+          invalid settings present in the uGuru, so we try this 3 times. */
+       for (i = 0; i < 3; i++)
+               if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+                               sensor_addr, data->bank1_settings[sensor_addr],
+                               3) == 3)
+                       break;
+       if (i == 3) {
+               printk(KERN_ERR ABIT_UGURU_NAME
+                       ": Fatal error could not restore original settings. "
+                       "This should never happen please report this to the "
+                       "abituguru maintainer (see MAINTAINERS)\n");
+               return -ENODEV;
+       }
+       return ret;
+}
+
+/* These functions try to find out how many sensors there are in bank2 and how
+   many pwms there are. The purpose of this is to make sure that we don't give
+   the user the possibility to change settings for non-existent sensors / pwm.
+   The uGuru will happily read / write whatever memory happens to be after the
+   memory storing the PWM settings when reading/writing to a PWM which is not
+   there. Notice even if we detect a PWM which doesn't exist we normally won't
+   write to it, unless the user tries to change the settings.
+
+   Although the uGuru allows reading (settings) from non existing bank2
+   sensors, my version of the uGuru does seem to stop writing to them, the
+   write function above aborts in this case with:
+   "CMD reg does not hold 0xAC after write"
+
+   Notice these 2 tests are non destructive iow read-only tests, otherwise
+   they would defeat their purpose. Although for the bank2_sensors detection a
+   read/write test would be feasible because of the reaction above, I've
+   however opted to stay on the safe side. */
+static void __devinit
+abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
+{
+       int i;
+
+       if (fan_sensors > 0 && fan_sensors <= ABIT_UGURU_MAX_BANK2_SENSORS) {
+               data->bank2_sensors = fan_sensors;
+               ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of "
+                       "\"fan_sensors\" module param\n",
+                       (int)data->bank2_sensors);
+               return;
+       }
+
+       ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n");
+       for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) {
+               /* 0x89 are the known used bits:
+                  -0x80 enable shutdown
+                  -0x08 enable beep
+                  -0x01 enable alarm
+                  All other bits should be 0, but on some motherboards
+                  0x40 (bit 6) is also high for some of the fans?? */
+               if (data->bank2_settings[i][0] & ~0xC9) {
+                       ABIT_UGURU_DEBUG(2, "  bank2 sensor %d does not seem "
+                               "to be a fan sensor: settings[0] = %02X\n",
+                               i, (unsigned int)data->bank2_settings[i][0]);
+                       break;
+               }
+
+               /* check if the threshold is within the allowed range */
+               if (data->bank2_settings[i][1] <
+                               abituguru_bank2_min_threshold) {
+                       ABIT_UGURU_DEBUG(2, "  bank2 sensor %d does not seem "
+                               "to be a fan sensor: the threshold (%d) is "
+                               "below the minimum (%d)\n", i,
+                               (int)data->bank2_settings[i][1],
+                               (int)abituguru_bank2_min_threshold);
+                       break;
+               }
+               if (data->bank2_settings[i][1] >
+                               abituguru_bank2_max_threshold) {
+                       ABIT_UGURU_DEBUG(2, "  bank2 sensor %d does not seem "
+                               "to be a fan sensor: the threshold (%d) is "
+                               "above the maximum (%d)\n", i,
+                               (int)data->bank2_settings[i][1],
+                               (int)abituguru_bank2_max_threshold);
+                       break;
+               }
+       }
+
+       data->bank2_sensors = i;
+       ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n",
+               (int)data->bank2_sensors);
+}
+
+static void __devinit
+abituguru_detect_no_pwms(struct abituguru_data *data)
+{
+       int i, j;
+
+       if (pwms > 0 && pwms <= ABIT_UGURU_MAX_PWMS) {
+               data->pwms = pwms;
+               ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of "
+                       "\"pwms\" module param\n", (int)data->pwms);
+               return;
+       }
+
+       ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n");
+       for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) {
+               /* 0x80 is the enable bit and the low
+                  nibble is which temp sensor to use,
+                  the other bits should be 0 */
+               if (data->pwm_settings[i][0] & ~0x8F) {
+                       ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+                               "to be a pwm channel: settings[0] = %02X\n",
+                               i, (unsigned int)data->pwm_settings[i][0]);
+                       break;
+               }
+
+               /* the low nibble must correspond to one of the temp sensors
+                  we've found */
+               for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR];
+                               j++) {
+                       if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] ==
+                                       (data->pwm_settings[i][0] & 0x0F))
+                               break;
+               }
+               if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) {
+                       ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+                               "to be a pwm channel: %d is not a valid temp "
+                               "sensor address\n", i,
+                               data->pwm_settings[i][0] & 0x0F);
+                       break;
+               }
+
+               /* check if all other settings are within the allowed range */
+               for (j = 1; j < 5; j++) {
+                       u8 min;
+                       /* special case pwm1 min pwm% */
+                       if ((i == 0) && ((j == 1) || (j == 2)))
+                               min = 77;
+                       else
+                               min = abituguru_pwm_min[j];
+                       if (data->pwm_settings[i][j] < min) {
+                               ABIT_UGURU_DEBUG(2, "  pwm channel %d does "
+                                       "not seem to be a pwm channel: "
+                                       "setting %d (%d) is below the minimum "
+                                       "value (%d)\n", i, j,
+                                       (int)data->pwm_settings[i][j],
+                                       (int)min);
+                               goto abituguru_detect_no_pwms_exit;
+                       }
+                       if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) {
+                               ABIT_UGURU_DEBUG(2, "  pwm channel %d does "
+                                       "not seem to be a pwm channel: "
+                                       "setting %d (%d) is above the maximum "
+                                       "value (%d)\n", i, j,
+                                       (int)data->pwm_settings[i][j],
+                                       (int)abituguru_pwm_max[j]);
+                               goto abituguru_detect_no_pwms_exit;
+                       }
+               }
+
+               /* check that min temp < max temp and min pwm < max pwm */
+               if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) {
+                       ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+                               "to be a pwm channel: min pwm (%d) >= "
+                               "max pwm (%d)\n", i,
+                               (int)data->pwm_settings[i][1],
+                               (int)data->pwm_settings[i][2]);
+                       break;
+               }
+               if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) {
+                       ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+                               "to be a pwm channel: min temp (%d) >= "
+                               "max temp (%d)\n", i,
+                               (int)data->pwm_settings[i][3],
+                               (int)data->pwm_settings[i][4]);
+                       break;
+               }
+       }
+
+abituguru_detect_no_pwms_exit:
+       data->pwms = i;
+       ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms);
+}
+
+/* Following are the sysfs callback functions. These functions expect:
+   sensor_device_attribute_2->index:   sensor address/offset in the bank
+   sensor_device_attribute_2->nr:      register offset, bitmask or NA. */
+static struct abituguru_data *abituguru_update_device(struct device *dev);
+
+static ssize_t show_bank1_value(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = abituguru_update_device(dev);
+       if (!data)
+               return -EIO;
+       return sprintf(buf, "%d\n", (data->bank1_value[attr->index] *
+               data->bank1_max_value[attr->index] + 128) / 255);
+}
+
+static ssize_t show_bank1_setting(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n",
+               (data->bank1_settings[attr->index][attr->nr] *
+               data->bank1_max_value[attr->index] + 128) / 255);
+}
+
+static ssize_t show_bank2_value(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = abituguru_update_device(dev);
+       if (!data)
+               return -EIO;
+       return sprintf(buf, "%d\n", (data->bank2_value[attr->index] *
+               ABIT_UGURU_FAN_MAX + 128) / 255);
+}
+
+static ssize_t show_bank2_setting(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n",
+               (data->bank2_settings[attr->index][attr->nr] *
+               ABIT_UGURU_FAN_MAX + 128) / 255);
+}
+
+static ssize_t store_bank1_setting(struct device *dev, struct device_attribute
+       *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       u8 val = (simple_strtoul(buf, NULL, 10) * 255 +
+               data->bank1_max_value[attr->index]/2) /
+               data->bank1_max_value[attr->index];
+       ssize_t ret = count;
+
+       mutex_lock(&data->update_lock);
+       if (data->bank1_settings[attr->index][attr->nr] != val) {
+               u8 orig_val = data->bank1_settings[attr->index][attr->nr];
+               data->bank1_settings[attr->index][attr->nr] = val;
+               if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+                               attr->index, data->bank1_settings[attr->index],
+                               3) <= attr->nr) {
+                       data->bank1_settings[attr->index][attr->nr] = orig_val;
+                       ret = -EIO;
+               }
+       }
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static ssize_t store_bank2_setting(struct device *dev, struct device_attribute
+       *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) /
+               ABIT_UGURU_FAN_MAX;
+       ssize_t ret = count;
+
+       /* this check can be done before taking the lock */
+       if ((val < abituguru_bank2_min_threshold) ||
+                       (val > abituguru_bank2_max_threshold))
+               return -EINVAL;
+
+       mutex_lock(&data->update_lock);
+       if (data->bank2_settings[attr->index][attr->nr] != val) {
+               u8 orig_val = data->bank2_settings[attr->index][attr->nr];
+               data->bank2_settings[attr->index][attr->nr] = val;
+               if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK2 + 2,
+                               attr->index, data->bank2_settings[attr->index],
+                               2) <= attr->nr) {
+                       data->bank2_settings[attr->index][attr->nr] = orig_val;
+                       ret = -EIO;
+               }
+       }
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static ssize_t show_bank1_alarm(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = abituguru_update_device(dev);
+       if (!data)
+               return -EIO;
+       /* See if the alarm bit for this sensor is set, and if the
+          alarm matches the type of alarm we're looking for (for volt
+          it can be either low or high). The type is stored in a few
+          readonly bits in the settings part of the relevant sensor.
+          The bitmask of the type is passed to us in attr->nr. */
+       if ((data->alarms[attr->index / 8] & (0x01 << (attr->index % 8))) &&
+                       (data->bank1_settings[attr->index][0] & attr->nr))
+               return sprintf(buf, "1\n");
+       else
+               return sprintf(buf, "0\n");
+}
+
+static ssize_t show_bank2_alarm(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = abituguru_update_device(dev);
+       if (!data)
+               return -EIO;
+       if (data->alarms[2] & (0x01 << attr->index))
+               return sprintf(buf, "1\n");
+       else
+               return sprintf(buf, "0\n");
+}
+
+static ssize_t show_bank1_mask(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       if (data->bank1_settings[attr->index][0] & attr->nr)
+               return sprintf(buf, "1\n");
+       else
+               return sprintf(buf, "0\n");
+}
+
+static ssize_t show_bank2_mask(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       if (data->bank2_settings[attr->index][0] & attr->nr)
+               return sprintf(buf, "1\n");
+       else
+               return sprintf(buf, "0\n");
+}
+
+static ssize_t store_bank1_mask(struct device *dev,
+       struct device_attribute *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       int mask = simple_strtoul(buf, NULL, 10);
+       ssize_t ret = count;
+       u8 orig_val;
+
+       mutex_lock(&data->update_lock);
+       orig_val = data->bank1_settings[attr->index][0];
+
+       if (mask)
+               data->bank1_settings[attr->index][0] |= attr->nr;
+       else
+               data->bank1_settings[attr->index][0] &= ~attr->nr;
+
+       if ((data->bank1_settings[attr->index][0] != orig_val) &&
+                       (abituguru_write(data,
+                       ABIT_UGURU_SENSOR_BANK1 + 2, attr->index,
+                       data->bank1_settings[attr->index], 3) < 1)) {
+               data->bank1_settings[attr->index][0] = orig_val;
+               ret = -EIO;
+       }
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static ssize_t store_bank2_mask(struct device *dev,
+       struct device_attribute *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       int mask = simple_strtoul(buf, NULL, 10);
+       ssize_t ret = count;
+       u8 orig_val;
+
+       mutex_lock(&data->update_lock);
+       orig_val = data->bank2_settings[attr->index][0];
+
+       if (mask)
+               data->bank2_settings[attr->index][0] |= attr->nr;
+       else
+               data->bank2_settings[attr->index][0] &= ~attr->nr;
+
+       if ((data->bank2_settings[attr->index][0] != orig_val) &&
+                       (abituguru_write(data,
+                       ABIT_UGURU_SENSOR_BANK2 + 2, attr->index,
+                       data->bank2_settings[attr->index], 2) < 1)) {
+               data->bank2_settings[attr->index][0] = orig_val;
+               ret = -EIO;
+       }
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+/* Fan PWM (speed control) */
+static ssize_t show_pwm_setting(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", data->pwm_settings[attr->index][attr->nr] *
+               abituguru_pwm_settings_multiplier[attr->nr]);
+}
+
+static ssize_t store_pwm_setting(struct device *dev, struct device_attribute
+       *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       u8 min, val = (simple_strtoul(buf, NULL, 10) +
+               abituguru_pwm_settings_multiplier[attr->nr]/2) /
+               abituguru_pwm_settings_multiplier[attr->nr];
+       ssize_t ret = count;
+
+       /* special case pwm1 min pwm% */
+       if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2)))
+               min = 77;
+       else
+               min = abituguru_pwm_min[attr->nr];
+
+       /* this check can be done before taking the lock */
+       if ((val < min) || (val > abituguru_pwm_max[attr->nr]))
+               return -EINVAL;
+
+       mutex_lock(&data->update_lock);
+       /* this check needs to be done after taking the lock */
+       if ((attr->nr & 1) &&
+                       (val >= data->pwm_settings[attr->index][attr->nr + 1]))
+               ret = -EINVAL;
+       else if (!(attr->nr & 1) &&
+                       (val <= data->pwm_settings[attr->index][attr->nr - 1]))
+               ret = -EINVAL;
+       else if (data->pwm_settings[attr->index][attr->nr] != val) {
+               u8 orig_val = data->pwm_settings[attr->index][attr->nr];
+               data->pwm_settings[attr->index][attr->nr] = val;
+               if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
+                               attr->index, data->pwm_settings[attr->index],
+                               5) <= attr->nr) {
+                       data->pwm_settings[attr->index][attr->nr] =
+                               orig_val;
+                       ret = -EIO;
+               }
+       }
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static ssize_t show_pwm_sensor(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       int i;
+       /* We need to walk to the temp sensor addresses to find what
+          the userspace id of the configured temp sensor is. */
+       for (i = 0; i < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; i++)
+               if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][i] ==
+                               (data->pwm_settings[attr->index][0] & 0x0F))
+                       return sprintf(buf, "%d\n", i+1);
+
+       return -ENXIO;
+}
+
+static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute
+       *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       unsigned long val = simple_strtoul(buf, NULL, 10) - 1;
+       ssize_t ret = count;
+
+       mutex_lock(&data->update_lock);
+       if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) {
+               u8 orig_val = data->pwm_settings[attr->index][0];
+               u8 address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val];
+               data->pwm_settings[attr->index][0] &= 0xF0;
+               data->pwm_settings[attr->index][0] |= address;
+               if (data->pwm_settings[attr->index][0] != orig_val) {
+                       if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
+                                       attr->index,
+                                       data->pwm_settings[attr->index],
+                                       5) < 1) {
+                               data->pwm_settings[attr->index][0] = orig_val;
+                               ret = -EIO;
+                       }
+               }
+       }
+       else
+               ret = -EINVAL;
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       int res = 0;
+       if (data->pwm_settings[attr->index][0] & ABIT_UGURU_FAN_PWM_ENABLE)
+               res = 2;
+       return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
+       *devattr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       u8 orig_val, user_val = simple_strtoul(buf, NULL, 10);
+       ssize_t ret = count;
+
+       mutex_lock(&data->update_lock);
+       orig_val = data->pwm_settings[attr->index][0];
+       switch (user_val) {
+               case 0:
+                       data->pwm_settings[attr->index][0] &=
+                               ~ABIT_UGURU_FAN_PWM_ENABLE;
+                       break;
+               case 2:
+                       data->pwm_settings[attr->index][0] |=
+                               ABIT_UGURU_FAN_PWM_ENABLE;
+                       break;
+               default:
+                       ret = -EINVAL;
+       }
+       if ((data->pwm_settings[attr->index][0] != orig_val) &&
+                       (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
+                       attr->index, data->pwm_settings[attr->index],
+                       5) < 1)) {
+               data->pwm_settings[attr->index][0] = orig_val;
+               ret = -EIO;
+       }
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+static ssize_t show_name(struct device *dev,
+       struct device_attribute *devattr, char *buf)
+{
+       return sprintf(buf, "%s\n", ABIT_UGURU_NAME);
+}
+
+/* Sysfs attr templates, the real entries are generated automatically. */
+static const
+struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] = {
+       {
+       SENSOR_ATTR_2(in%d_input, 0444, show_bank1_value, NULL, 0, 0),
+       SENSOR_ATTR_2(in%d_min, 0644, show_bank1_setting,
+               store_bank1_setting, 1, 0),
+       SENSOR_ATTR_2(in%d_min_alarm, 0444, show_bank1_alarm, NULL,
+               ABIT_UGURU_VOLT_LOW_ALARM_FLAG, 0),
+       SENSOR_ATTR_2(in%d_max, 0644, show_bank1_setting,
+               store_bank1_setting, 2, 0),
+       SENSOR_ATTR_2(in%d_max_alarm, 0444, show_bank1_alarm, NULL,
+               ABIT_UGURU_VOLT_HIGH_ALARM_FLAG, 0),
+       SENSOR_ATTR_2(in%d_beep, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0),
+       SENSOR_ATTR_2(in%d_shutdown, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0),
+       SENSOR_ATTR_2(in%d_min_alarm_enable, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_VOLT_LOW_ALARM_ENABLE, 0),
+       SENSOR_ATTR_2(in%d_max_alarm_enable, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE, 0),
+       }, {
+       SENSOR_ATTR_2(temp%d_input, 0444, show_bank1_value, NULL, 0, 0),
+       SENSOR_ATTR_2(temp%d_alarm, 0444, show_bank1_alarm, NULL,
+               ABIT_UGURU_TEMP_HIGH_ALARM_FLAG, 0),
+       SENSOR_ATTR_2(temp%d_max, 0644, show_bank1_setting,
+               store_bank1_setting, 1, 0),
+       SENSOR_ATTR_2(temp%d_crit, 0644, show_bank1_setting,
+               store_bank1_setting, 2, 0),
+       SENSOR_ATTR_2(temp%d_beep, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0),
+       SENSOR_ATTR_2(temp%d_shutdown, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0),
+       SENSOR_ATTR_2(temp%d_alarm_enable, 0644, show_bank1_mask,
+               store_bank1_mask, ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE, 0),
+       }
+};
+
+static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] = {
+       SENSOR_ATTR_2(fan%d_input, 0444, show_bank2_value, NULL, 0, 0),
+       SENSOR_ATTR_2(fan%d_alarm, 0444, show_bank2_alarm, NULL, 0, 0),
+       SENSOR_ATTR_2(fan%d_min, 0644, show_bank2_setting,
+               store_bank2_setting, 1, 0),
+       SENSOR_ATTR_2(fan%d_beep, 0644, show_bank2_mask,
+               store_bank2_mask, ABIT_UGURU_BEEP_ENABLE, 0),
+       SENSOR_ATTR_2(fan%d_shutdown, 0644, show_bank2_mask,
+               store_bank2_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0),
+       SENSOR_ATTR_2(fan%d_alarm_enable, 0644, show_bank2_mask,
+               store_bank2_mask, ABIT_UGURU_FAN_LOW_ALARM_ENABLE, 0),
+};
+
+static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = {
+       SENSOR_ATTR_2(pwm%d_enable, 0644, show_pwm_enable,
+               store_pwm_enable, 0, 0),
+       SENSOR_ATTR_2(pwm%d_auto_channels_temp, 0644, show_pwm_sensor,
+               store_pwm_sensor, 0, 0),
+       SENSOR_ATTR_2(pwm%d_auto_point1_pwm, 0644, show_pwm_setting,
+               store_pwm_setting, 1, 0),
+       SENSOR_ATTR_2(pwm%d_auto_point2_pwm, 0644, show_pwm_setting,
+               store_pwm_setting, 2, 0),
+       SENSOR_ATTR_2(pwm%d_auto_point1_temp, 0644, show_pwm_setting,
+               store_pwm_setting, 3, 0),
+       SENSOR_ATTR_2(pwm%d_auto_point2_temp, 0644, show_pwm_setting,
+               store_pwm_setting, 4, 0),
+};
+
+static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = {
+       SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
+};
+
+static int __devinit abituguru_probe(struct platform_device *pdev)
+{
+       struct abituguru_data *data;
+       int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
+       char *sysfs_filename;
+
+       /* El weirdo probe order, to keep the sysfs order identical to the
+          BIOS and window-appliction listing order. */
+       const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = {
+               0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02,
+               0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C };
+
+       if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL)))
+               return -ENOMEM;
+
+       data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+       mutex_init(&data->update_lock);
+       platform_set_drvdata(pdev, data);
+
+       /* See if the uGuru is ready */
+       if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT)
+               data->uguru_ready = 1;
+
+       /* Completely read the uGuru this has 2 purposes:
+          - testread / see if one really is there.
+          - make an in memory copy of all the uguru settings for future use. */
+       if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
+                       data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3)
+               goto abituguru_probe_error;
+
+       for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
+               if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i,
+                               &data->bank1_value[i], 1,
+                               ABIT_UGURU_MAX_RETRIES) != 1)
+                       goto abituguru_probe_error;
+               if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i,
+                               data->bank1_settings[i], 3,
+                               ABIT_UGURU_MAX_RETRIES) != 3)
+                       goto abituguru_probe_error;
+       }
+       /* Note: We don't know how many bank2 sensors / pwms there really are,
+          but in order to "detect" this we need to read the maximum amount
+          anyways. If we read sensors/pwms not there we'll just read crap
+          this can't hurt. We need the detection because we don't want
+          unwanted writes, which will hurt! */
+       for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) {
+               if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i,
+                               &data->bank2_value[i], 1,
+                               ABIT_UGURU_MAX_RETRIES) != 1)
+                       goto abituguru_probe_error;
+               if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i,
+                               data->bank2_settings[i], 2,
+                               ABIT_UGURU_MAX_RETRIES) != 2)
+                       goto abituguru_probe_error;
+       }
+       for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) {
+               if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i,
+                               data->pwm_settings[i], 5,
+                               ABIT_UGURU_MAX_RETRIES) != 5)
+                       goto abituguru_probe_error;
+       }
+       data->last_updated = jiffies;
+
+       /* Detect sensor types and fill the sysfs attr for bank1 */
+       sysfs_attr_i = 0;
+       sysfs_filename = data->sysfs_names;
+       sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH;
+       for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
+               res = abituguru_detect_bank1_sensor_type(data, probe_order[i]);
+               if (res < 0)
+                       goto abituguru_probe_error;
+               if (res == ABIT_UGURU_NC)
+                       continue;
+
+               /* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */
+               for (j = 0; j < (res ? 7 : 9); j++) {
+                       used = snprintf(sysfs_filename, sysfs_names_free,
+                               abituguru_sysfs_bank1_templ[res][j].dev_attr.
+                               attr.name, data->bank1_sensors[res] + res)
+                               + 1;
+                       data->sysfs_attr[sysfs_attr_i] =
+                               abituguru_sysfs_bank1_templ[res][j];
+                       data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+                               sysfs_filename;
+                       data->sysfs_attr[sysfs_attr_i].index = probe_order[i];
+                       sysfs_filename += used;
+                       sysfs_names_free -= used;
+                       sysfs_attr_i++;
+               }
+               data->bank1_max_value[probe_order[i]] =
+                       abituguru_bank1_max_value[res];
+               data->bank1_address[res][data->bank1_sensors[res]] =
+                       probe_order[i];
+               data->bank1_sensors[res]++;
+       }
+       /* Detect number of sensors and fill the sysfs attr for bank2 (fans) */
+       abituguru_detect_no_bank2_sensors(data);
+       for (i = 0; i < data->bank2_sensors; i++) {
+               for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) {
+                       used = snprintf(sysfs_filename, sysfs_names_free,
+                               abituguru_sysfs_fan_templ[j].dev_attr.attr.name,
+                               i + 1) + 1;
+                       data->sysfs_attr[sysfs_attr_i] =
+                               abituguru_sysfs_fan_templ[j];
+                       data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+                               sysfs_filename;
+                       data->sysfs_attr[sysfs_attr_i].index = i;
+                       sysfs_filename += used;
+                       sysfs_names_free -= used;
+                       sysfs_attr_i++;
+               }
+       }
+       /* Detect number of sensors and fill the sysfs attr for pwms */
+       abituguru_detect_no_pwms(data);
+       for (i = 0; i < data->pwms; i++) {
+               for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) {
+                       used = snprintf(sysfs_filename, sysfs_names_free,
+                               abituguru_sysfs_pwm_templ[j].dev_attr.attr.name,
+                               i + 1) + 1;
+                       data->sysfs_attr[sysfs_attr_i] =
+                               abituguru_sysfs_pwm_templ[j];
+                       data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+                               sysfs_filename;
+                       data->sysfs_attr[sysfs_attr_i].index = i;
+                       sysfs_filename += used;
+                       sysfs_names_free -= used;
+                       sysfs_attr_i++;
+               }
+       }
+       /* Fail safe check, this should never happen! */
+       if (sysfs_names_free < 0) {
+               printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of "
+                      "space for sysfs attr names. This should never "
+                      "happen please report to the abituguru maintainer "
+                      "(see MAINTAINERS)\n");
+               res = -ENAMETOOLONG;
+               goto abituguru_probe_error;
+       }
+       printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
+
+       /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->class_dev)) {
+               res = PTR_ERR(data->class_dev);
+               goto abituguru_probe_error;
+       }
+       for (i = 0; i < sysfs_attr_i; i++)
+               device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+       for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
+               device_create_file(&pdev->dev,
+                       &abituguru_sysfs_attr[i].dev_attr);
+
+       return 0;
+
+abituguru_probe_error:
+       kfree(data);
+       return res;
+}
+
+static int __devexit abituguru_remove(struct platform_device *pdev)
+{
+       struct abituguru_data *data = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       hwmon_device_unregister(data->class_dev);
+       kfree(data);
+
+       return 0;
+}
+
+static struct abituguru_data *abituguru_update_device(struct device *dev)
+{
+       int i, err;
+       struct abituguru_data *data = dev_get_drvdata(dev);
+       /* fake a complete successful read if no update necessary. */
+       char success = 1;
+
+       mutex_lock(&data->update_lock);
+       if (time_after(jiffies, data->last_updated + HZ)) {
+               success = 0;
+               if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
+                               data->alarms, 3, 0)) != 3)
+                       goto LEAVE_UPDATE;
+               for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
+                       if ((err = abituguru_read(data,
+                                       ABIT_UGURU_SENSOR_BANK1, i,
+                                       &data->bank1_value[i], 1, 0)) != 1)
+                               goto LEAVE_UPDATE;
+                       if ((err = abituguru_read(data,
+                                       ABIT_UGURU_SENSOR_BANK1 + 1, i,
+                                       data->bank1_settings[i], 3, 0)) != 3)
+                               goto LEAVE_UPDATE;
+               }
+               for (i = 0; i < data->bank2_sensors; i++)
+                       if ((err = abituguru_read(data,
+                                       ABIT_UGURU_SENSOR_BANK2, i,
+                                       &data->bank2_value[i], 1, 0)) != 1)
+                               goto LEAVE_UPDATE;
+               /* success! */
+               success = 1;
+               data->update_timeouts = 0;
+LEAVE_UPDATE:
+               /* handle timeout condition */
+               if (!success && (err == -EBUSY || err >= 0)) {
+                       /* No overflow please */
+                       if (data->update_timeouts < 255u)
+                               data->update_timeouts++;
+                       if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) {
+                               ABIT_UGURU_DEBUG(3, "timeout exceeded, will "
+                                       "try again next update\n");
+                               /* Just a timeout, fake a successful read */
+                               success = 1;
+                       } else
+                               ABIT_UGURU_DEBUG(1, "timeout exceeded %d "
+                                       "times waiting for more input state\n",
+                                       (int)data->update_timeouts);
+               }
+               /* On success set last_updated */
+               if (success)
+                       data->last_updated = jiffies;
+       }
+       mutex_unlock(&data->update_lock);
+
+       if (success)
+               return data;
+       else
+               return NULL;
+}
+
+static struct platform_driver abituguru_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = ABIT_UGURU_NAME,
+       },
+       .probe  = abituguru_probe,
+       .remove = __devexit_p(abituguru_remove),
+};
+
+static int __init abituguru_detect(void)
+{
+       /* See if there is an uguru there. After a reboot uGuru will hold 0x00
+          at DATA and 0xAC, when this driver has already been loaded once
+          DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either
+          scenario but some will hold 0x00.
+          Some uGuru's initally hold 0x09 at DATA and will only hold 0x08
+          after reading CMD first, so CMD must be read first! */
+       u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD);
+       u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA);
+       if (((data_val == 0x00) || (data_val == 0x08)) &&
+           ((cmd_val == 0x00) || (cmd_val == 0xAC)))
+               return ABIT_UGURU_BASE;
+
+       ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = "
+               "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
+
+       if (force) {
+               printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is "
+                               "present because of \"force\" parameter\n");
+               return ABIT_UGURU_BASE;
+       }
+
+       /* No uGuru found */
+       return -ENODEV;
+}
+
+static struct platform_device *abituguru_pdev;
+
+static int __init abituguru_init(void)
+{
+       int address, err;
+       struct resource res = { .flags = IORESOURCE_IO };
+
+       address = abituguru_detect();
+       if (address < 0)
+               return address;
+
+       err = platform_driver_register(&abituguru_driver);
+       if (err)
+               goto exit;
+
+       abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address);
+       if (!abituguru_pdev) {
+               printk(KERN_ERR ABIT_UGURU_NAME
+                       ": Device allocation failed\n");
+               err = -ENOMEM;
+               goto exit_driver_unregister;
+       }
+
+       res.start = address;
+       res.end = address + ABIT_UGURU_REGION_LENGTH - 1;
+       res.name = ABIT_UGURU_NAME;
+
+       err = platform_device_add_resources(abituguru_pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR ABIT_UGURU_NAME
+                       ": Device resource addition failed (%d)\n", err);
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(abituguru_pdev);
+       if (err) {
+               printk(KERN_ERR ABIT_UGURU_NAME
+                       ": Device addition failed (%d)\n", err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+exit_device_put:
+       platform_device_put(abituguru_pdev);
+exit_driver_unregister:
+       platform_driver_unregister(&abituguru_driver);
+exit:
+       return err;
+}
+
+static void __exit abituguru_exit(void)
+{
+       platform_device_unregister(abituguru_pdev);
+       platform_driver_unregister(&abituguru_driver);
+}
+
+MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_DESCRIPTION("Abit uGuru Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(abituguru_init);
+module_exit(abituguru_exit);
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
new file mode 100644 (file)
index 0000000..6ba8473
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * lm70.c
+ *
+ * The LM70 is a temperature sensor chip from National Semiconductor (NS).
+ * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
+ *
+ * The LM70 communicates with a host processor via an SPI/Microwire Bus
+ * interface. The complete datasheet is available at National's website
+ * here:
+ * http://www.national.com/pf/LM/LM70.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/kernel.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/spi/spi.h>
+#include <asm/semaphore.h>
+
+#define DRVNAME                "lm70"
+
+struct lm70 {
+       struct class_device *cdev;
+       struct semaphore sem;
+};
+
+/* sysfs hook function */
+static ssize_t lm70_sense_temp(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       int status, val;
+       u8 rxbuf[2];
+       s16 raw=0;
+       struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
+
+       if (down_interruptible(&p_lm70->sem))
+               return -ERESTARTSYS;
+
+       /*
+        * spi_read() requires a DMA-safe buffer; so we use
+        * spi_write_then_read(), transmitting 0 bytes.
+        */
+       status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
+       if (status < 0) {
+               printk(KERN_WARNING
+               "spi_write_then_read failed with status %d\n", status);
+               goto out;
+       }
+       dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]);
+
+       raw = (rxbuf[1] << 8) + rxbuf[0];
+       dev_dbg(dev, "raw=0x%x\n", raw);
+
+       /*
+        * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's
+        * complement value. Only the MSB 11 bits (1 sign + 10 temperature
+        * bits) are meaningful; the LSB 5 bits are to be discarded.
+        * See the datasheet.
+        *
+        * Further, each bit represents 0.25 degrees Celsius; so, multiply
+        * by 0.25. Also multiply by 1000 to represent in millidegrees
+        * Celsius.
+        * So it's equivalent to multiplying by 0.25 * 1000 = 250.
+        */
+       val = ((int)raw/32) * 250;
+       status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */
+out:
+       up(&p_lm70->sem);
+       return status;
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit lm70_probe(struct spi_device *spi)
+{
+       struct lm70 *p_lm70;
+       int status;
+
+       p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
+       if (!p_lm70)
+               return -ENOMEM;
+
+       init_MUTEX(&p_lm70->sem);
+
+       /* sysfs hook */
+       p_lm70->cdev = hwmon_device_register(&spi->dev);
+       if (IS_ERR(p_lm70->cdev)) {
+               dev_dbg(&spi->dev, "hwmon_device_register failed.\n");
+               status = PTR_ERR(p_lm70->cdev);
+               goto out_dev_reg_failed;
+       }
+       dev_set_drvdata(&spi->dev, p_lm70);
+
+       if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) {
+               dev_dbg(&spi->dev, "device_create_file failure.\n");
+               goto out_dev_create_file_failed;
+       }
+
+       return 0;
+
+out_dev_create_file_failed:
+       hwmon_device_unregister(p_lm70->cdev);
+out_dev_reg_failed:
+       dev_set_drvdata(&spi->dev, NULL);
+       kfree(p_lm70);
+       return status;
+}
+
+static int __exit lm70_remove(struct spi_device *spi)
+{
+       struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
+
+       device_remove_file(&spi->dev, &dev_attr_temp1_input);
+       hwmon_device_unregister(p_lm70->cdev);
+       dev_set_drvdata(&spi->dev, NULL);
+       kfree(p_lm70);
+
+       return 0;
+}
+
+static struct spi_driver lm70_driver = {
+       .driver = {
+               .name   = "lm70",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = lm70_probe,
+       .remove = __devexit_p(lm70_remove),
+};
+
+static int __init init_lm70(void)
+{
+       return spi_register_driver(&lm70_driver);
+}
+
+static void __exit cleanup_lm70(void)
+{
+       spi_unregister_driver(&lm70_driver);
+}
+
+module_init(init_lm70);
+module_exit(cleanup_lm70);
+
+MODULE_AUTHOR("Kaiwan N Billimoria");
+MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
new file mode 100644 (file)
index 0000000..bdc4570
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+    smsc47m192.c - Support for hardware monitoring block of
+                   SMSC LPC47M192 and LPC47M997 Super I/O chips
+
+    Copyright (C) 2006  Hartmut Rick <linux@rick.claranet.de>
+
+    Derived from lm78.c and other chip 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(smsc47m192);
+
+/* SMSC47M192 registers */
+#define SMSC47M192_REG_IN(nr)          ((nr)<6 ? (0x20 + (nr)) : \
+                                       (0x50 + (nr) - 6))
+#define SMSC47M192_REG_IN_MAX(nr)      ((nr)<6 ? (0x2b + (nr) * 2) : \
+                                       (0x54 + (((nr) - 6) * 2)))
+#define SMSC47M192_REG_IN_MIN(nr)      ((nr)<6 ? (0x2c + (nr) * 2) : \
+                                       (0x55 + (((nr) - 6) * 2)))
+static u8 SMSC47M192_REG_TEMP[3] =     { 0x27, 0x26, 0x52 };
+static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 };
+static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 };
+#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr)==2 ? 0x1e : 0x1f)
+#define SMSC47M192_REG_ALARM1          0x41
+#define SMSC47M192_REG_ALARM2          0x42
+#define SMSC47M192_REG_VID             0x47
+#define SMSC47M192_REG_VID4            0x49
+#define SMSC47M192_REG_CONFIG          0x40
+#define SMSC47M192_REG_SFR             0x4f
+#define SMSC47M192_REG_COMPANY_ID      0x3e
+#define SMSC47M192_REG_VERSION         0x3f
+
+/* generalised scaling with integer rounding */
+static inline int SCALE(long val, int mul, int div)
+{
+       if (val < 0)
+               return (val * mul - div / 2) / div;
+       else
+               return (val * mul + div / 2) / div;
+}
+
+/* Conversions */
+
+/* smsc47m192 internally scales voltage measurements */
+static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 };
+
+static inline unsigned int IN_FROM_REG(u8 reg, int n)
+{
+       return SCALE(reg, nom_mv[n], 192);
+}
+
+static inline u8 IN_TO_REG(unsigned long val, int n)
+{
+       return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
+}
+
+/* TEMP: 0.001 degC units (-128C to +127C)
+   REG: 1C/bit, two's complement */
+static inline s8 TEMP_TO_REG(int val)
+{
+       return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000);
+}
+
+static inline int TEMP_FROM_REG(s8 val)
+{
+       return val * 1000;
+}
+
+struct smsc47m192_data {
+       struct i2c_client client;
+       struct class_device *class_dev;
+       struct semaphore update_lock;
+       char valid;             /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+
+       u8 in[8];               /* Register value */
+       u8 in_max[8];           /* Register value */
+       u8 in_min[8];           /* Register value */
+       s8 temp[3];             /* Register value */
+       s8 temp_max[3];         /* Register value */
+       s8 temp_min[3];         /* Register value */
+       s8 temp_offset[3];      /* Register value */
+       u16 alarms;             /* Register encoding, combined */
+       u8 vid;                 /* Register encoding, combined */
+       u8 vrm;
+};
+
+static int smsc47m192_attach_adapter(struct i2c_adapter *adapter);
+static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
+               int kind);
+static int smsc47m192_detach_client(struct i2c_client *client);
+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
+
+static struct i2c_driver smsc47m192_driver = {
+       .driver = {
+               .name   = "smsc47m192",
+       },
+       .attach_adapter = smsc47m192_attach_adapter,
+       .detach_client  = smsc47m192_detach_client,
+};
+
+/* Voltages */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->in_min[nr] = IN_TO_REG(val, nr);
+       i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr),
+                                                       data->in_min[nr]);
+       up(&data->update_lock);
+       return count;
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->in_max[nr] = IN_TO_REG(val, nr);
+       i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr),
+                                                       data->in_max[nr]);
+       up(&data->update_lock);
+       return count;
+}
+
+#define show_in_offset(offset)                                 \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,         \
+               show_in, NULL, offset);                         \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+               show_in_min, set_in_min, offset);               \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+               show_in_max, set_in_max, offset);
+
+show_in_offset(0)
+show_in_offset(1)
+show_in_offset(2)
+show_in_offset(3)
+show_in_offset(4)
+show_in_offset(5)
+show_in_offset(6)
+show_in_offset(7)
+
+/* Temperatures */
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
+}
+
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
+}
+
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->temp_min[nr] = TEMP_TO_REG(val);
+       i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr],
+                                               data->temp_min[nr]);
+       up(&data->update_lock);
+       return count;
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->temp_max[nr] = TEMP_TO_REG(val);
+       i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr],
+                                               data->temp_max[nr]);
+       up(&data->update_lock);
+       return count;
+}
+
+static ssize_t show_temp_offset(struct device *dev, struct device_attribute
+               *attr, char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
+}
+
+static ssize_t set_temp_offset(struct device *dev, struct device_attribute
+               *attr, const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+       long val = simple_strtol(buf, NULL, 10);
+
+       down(&data->update_lock);
+       data->temp_offset[nr] = TEMP_TO_REG(val);
+       if (nr>1)
+               i2c_smbus_write_byte_data(client,
+                       SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
+       else if (data->temp_offset[nr] != 0) {
+               /* offset[0] and offset[1] share the same register,
+                       SFR bit 4 activates offset[0] */
+               i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
+                                       (sfr & 0xef) | (nr==0 ? 0x10 : 0));
+               data->temp_offset[1-nr] = 0;
+               i2c_smbus_write_byte_data(client,
+                       SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
+       } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0))
+               i2c_smbus_write_byte_data(client,
+                                       SMSC47M192_REG_TEMP_OFFSET(nr), 0);
+       up(&data->update_lock);
+       return count;
+}
+
+#define show_temp_index(index)                                         \
+static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO,                        \
+               show_temp, NULL, index-1);                              \
+static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR,                \
+               show_temp_min, set_temp_min, index-1);                  \
+static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR,                \
+               show_temp_max, set_temp_max, index-1);                  \
+static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR,     \
+               show_temp_offset, set_temp_offset, index-1);
+
+show_temp_index(1)
+show_temp_index(2)
+show_temp_index(3)
+
+/* VID */
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       data->vrm = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+
+/* Alarms */
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct smsc47m192_data *data = smsc47m192_update_device(dev);
+       return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000);
+static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000);
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800);
+
+/* This function is called when:
+    * smsc47m192_driver is inserted (when this module is loaded), for each
+      available adapter
+    * when a new adapter is inserted (and smsc47m192_driver is still present) */
+static int smsc47m192_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_probe(adapter, &addr_data, smsc47m192_detect);
+}
+
+static void smsc47m192_init_client(struct i2c_client *client)
+{
+       int i;
+       u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
+       u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+
+       /* select cycle mode (pause 1 sec between updates) */
+       i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
+                                               (sfr & 0xfd) | 0x02);
+       if (!(config & 0x01)) {
+               /* initialize alarm limits */
+               for (i=0; i<8; i++) {
+                       i2c_smbus_write_byte_data(client,
+                               SMSC47M192_REG_IN_MIN(i), 0);
+                       i2c_smbus_write_byte_data(client,
+                               SMSC47M192_REG_IN_MAX(i), 0xff);
+               }
+               for (i=0; i<3; i++) {
+                       i2c_smbus_write_byte_data(client,
+                               SMSC47M192_REG_TEMP_MIN[i], 0x80);
+                       i2c_smbus_write_byte_data(client,
+                               SMSC47M192_REG_TEMP_MAX[i], 0x7f);
+               }
+
+               /* start monitoring */
+               i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG,
+                                               (config & 0xf7) | 0x01);
+       }
+}
+
+/* This function is called by i2c_probe */
+static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
+               int kind)
+{
+       struct i2c_client *client;
+       struct smsc47m192_data *data;
+       int err = 0;
+       int version, config;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               goto exit;
+
+       if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &smsc47m192_driver;
+
+       if (kind == 0)
+               kind = smsc47m192;
+
+       /* Detection criteria from sensors_detect script */
+       if (kind < 0) {
+               if (i2c_smbus_read_byte_data(client,
+                               SMSC47M192_REG_COMPANY_ID) == 0x55
+                && ((version = i2c_smbus_read_byte_data(client,
+                               SMSC47M192_REG_VERSION)) & 0xf0) == 0x20
+                && (i2c_smbus_read_byte_data(client,
+                               SMSC47M192_REG_VID) & 0x70) == 0x00
+                && (i2c_smbus_read_byte_data(client,
+                               SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
+                       dev_info(&adapter->dev,
+                                "found SMSC47M192 or SMSC47M997, "
+                                "version 2, stepping A%d\n", version & 0x0f);
+               } else {
+                       dev_dbg(&adapter->dev,
+                               "SMSC47M192 detection failed at 0x%02x\n",
+                               address);
+                       goto exit_free;
+               }
+       }
+
+       /* Fill in the remaining client fields and put into the global list */
+       strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE);
+       data->vrm = vid_which_vrm();
+       init_MUTEX(&data->update_lock);
+
+       /* Tell the I2C layer a new client has arrived */
+       if ((err = i2c_attach_client(client)))
+               goto exit_free;
+
+       /* Initialize the SMSC47M192 chip */
+       smsc47m192_init_client(client);
+
+       /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
+       device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr);
+
+       /* Pin 110 is either in4 (+12V) or VID4 */
+       config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
+       if (!(config & 0x20)) {
+               device_create_file(&client->dev,
+                                  &sensor_dev_attr_in4_input.dev_attr);
+               device_create_file(&client->dev,
+                                  &sensor_dev_attr_in4_min.dev_attr);
+               device_create_file(&client->dev,
+                                  &sensor_dev_attr_in4_max.dev_attr);
+               device_create_file(&client->dev,
+                                  &sensor_dev_attr_in4_alarm.dev_attr);
+       }
+       device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+       device_create_file(&client->dev,
+                          &sensor_dev_attr_temp1_offset.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+       device_create_file(&client->dev,
+                          &sensor_dev_attr_temp2_offset.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr);
+       device_create_file(&client->dev,
+                          &sensor_dev_attr_temp2_input_fault.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+       device_create_file(&client->dev,
+                          &sensor_dev_attr_temp3_offset.dev_attr);
+       device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr);
+       device_create_file(&client->dev,
+                          &sensor_dev_attr_temp3_input_fault.dev_attr);
+       device_create_file(&client->dev, &dev_attr_cpu0_vid);
+       device_create_file(&client->dev, &dev_attr_vrm);
+
+       return 0;
+
+exit_detach:
+       i2c_detach_client(client);
+exit_free:
+       kfree(data);
+exit:
+       return err;
+}
+
+static int smsc47m192_detach_client(struct i2c_client *client)
+{
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       int err;
+
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
+               return err;
+
+       kfree(data);
+
+       return 0;
+}
+
+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct smsc47m192_data *data = i2c_get_clientdata(client);
+       int i, config;
+
+       down(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+        || !data->valid) {
+               u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+
+               dev_dbg(&client->dev, "Starting smsc47m192 update\n");
+
+               for (i = 0; i <= 7; i++) {
+                       data->in[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_IN(i));
+                       data->in_min[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_IN_MIN(i));
+                       data->in_max[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_IN_MAX(i));
+               }
+               for (i = 0; i < 3; i++) {
+                       data->temp[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_TEMP[i]);
+                       data->temp_max[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_TEMP_MAX[i]);
+                       data->temp_min[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_TEMP_MIN[i]);
+               }
+               for (i = 1; i < 3; i++)
+                       data->temp_offset[i] = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_TEMP_OFFSET(i));
+               /* first offset is temp_offset[0] if SFR bit 4 is set,
+                                       temp_offset[1] otherwise */
+               if (sfr & 0x10) {
+                       data->temp_offset[0] = data->temp_offset[1];
+                       data->temp_offset[1] = 0;
+               } else
+                       data->temp_offset[0] = 0;
+
+               data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
+                           & 0x0f;
+               config = i2c_smbus_read_byte_data(client,
+                                                 SMSC47M192_REG_CONFIG);
+               if (config & 0x20)
+                       data->vid |= (i2c_smbus_read_byte_data(client,
+                                       SMSC47M192_REG_VID4) & 0x01) << 4;
+               data->alarms = i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_ALARM1) |
+                              (i2c_smbus_read_byte_data(client,
+                                               SMSC47M192_REG_ALARM2) << 8);
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       up(&data->update_lock);
+
+       return data;
+}
+
+static int __init smsc47m192_init(void)
+{
+       return i2c_add_driver(&smsc47m192_driver);
+}
+
+static void __exit smsc47m192_exit(void)
+{
+       i2c_del_driver(&smsc47m192_driver);
+}
+
+MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>");
+MODULE_DESCRIPTION("SMSC47M192 driver");
+MODULE_LICENSE("GPL");
+
+module_init(smsc47m192_init);
+module_exit(smsc47m192_exit);
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
new file mode 100644 (file)
index 0000000..87f7312
--- /dev/null
@@ -0,0 +1,1254 @@
+/*
+    w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+
+    Copyright (C) 2006 Charles Spirakis <bezaur@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+    Supports following chips:
+
+    Chip       #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+    w83791d    10      5       3       3       0x71    0x5ca3  yes     no
+
+    The w83791d chip appears to be part way between the 83781d and the
+    83792d. Thus, this file is derived from both the w83792d.c and
+    w83781d.c files, but its output is more along the lines of the
+    83781d (which means there are no changes to the user-mode sensors
+    program which treats the 83791d as an 83781d).
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+#define NUMBER_OF_VIN          10
+#define NUMBER_OF_FANIN                5
+#define NUMBER_OF_TEMPIN       3
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83791d);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+                       "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to one to force extra software initialization");
+
+/* The W83791D registers */
+static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = {
+       0x20,                   /* VCOREA in DataSheet */
+       0x21,                   /* VINR0 in DataSheet */
+       0x22,                   /* +3.3VIN in DataSheet */
+       0x23,                   /* VDD5V in DataSheet */
+       0x24,                   /* +12VIN in DataSheet */
+       0x25,                   /* -12VIN in DataSheet */
+       0x26,                   /* -5VIN in DataSheet */
+       0xB0,                   /* 5VSB in DataSheet */
+       0xB1,                   /* VBAT in DataSheet */
+       0xB2                    /* VINR1 in DataSheet */
+};
+
+static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = {
+       0x2B,                   /* VCOREA High Limit in DataSheet */
+       0x2D,                   /* VINR0 High Limit in DataSheet */
+       0x2F,                   /* +3.3VIN High Limit in DataSheet */
+       0x31,                   /* VDD5V High Limit in DataSheet */
+       0x33,                   /* +12VIN High Limit in DataSheet */
+       0x35,                   /* -12VIN High Limit in DataSheet */
+       0x37,                   /* -5VIN High Limit in DataSheet */
+       0xB4,                   /* 5VSB High Limit in DataSheet */
+       0xB6,                   /* VBAT High Limit in DataSheet */
+       0xB8                    /* VINR1 High Limit in DataSheet */
+};
+static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = {
+       0x2C,                   /* VCOREA Low Limit in DataSheet */
+       0x2E,                   /* VINR0 Low Limit in DataSheet */
+       0x30,                   /* +3.3VIN Low Limit in DataSheet */
+       0x32,                   /* VDD5V Low Limit in DataSheet */
+       0x34,                   /* +12VIN Low Limit in DataSheet */
+       0x36,                   /* -12VIN Low Limit in DataSheet */
+       0x38,                   /* -5VIN Low Limit in DataSheet */
+       0xB5,                   /* 5VSB Low Limit in DataSheet */
+       0xB7,                   /* VBAT Low Limit in DataSheet */
+       0xB9                    /* VINR1 Low Limit in DataSheet */
+};
+static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = {
+       0x28,                   /* FAN 1 Count in DataSheet */
+       0x29,                   /* FAN 2 Count in DataSheet */
+       0x2A,                   /* FAN 3 Count in DataSheet */
+       0xBA,                   /* FAN 4 Count in DataSheet */
+       0xBB,                   /* FAN 5 Count in DataSheet */
+};
+static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = {
+       0x3B,                   /* FAN 1 Count Low Limit in DataSheet */
+       0x3C,                   /* FAN 2 Count Low Limit in DataSheet */
+       0x3D,                   /* FAN 3 Count Low Limit in DataSheet */
+       0xBC,                   /* FAN 4 Count Low Limit in DataSheet */
+       0xBD,                   /* FAN 5 Count Low Limit in DataSheet */
+};
+
+static const u8 W83791D_REG_FAN_CFG[2] = {
+       0x84,                   /* FAN 1/2 configuration */
+       0x95,                   /* FAN 3 configuration */
+};
+
+static const u8 W83791D_REG_FAN_DIV[3] = {
+       0x47,                   /* contains FAN1 and FAN2 Divisor */
+       0x4b,                   /* contains FAN3 Divisor */
+       0x5C,                   /* contains FAN4 and FAN5 Divisor */
+};
+
+#define W83791D_REG_BANK               0x4E
+#define W83791D_REG_TEMP2_CONFIG       0xC2
+#define W83791D_REG_TEMP3_CONFIG       0xCA
+
+static const u8 W83791D_REG_TEMP1[3] = {
+       0x27,                   /* TEMP 1 in DataSheet */
+       0x39,                   /* TEMP 1 Over in DataSheet */
+       0x3A,                   /* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83791D_REG_TEMP_ADD[2][6] = {
+       {0xC0,                  /* TEMP 2 in DataSheet */
+        0xC1,                  /* TEMP 2(0.5 deg) in DataSheet */
+        0xC5,                  /* TEMP 2 Over High part in DataSheet */
+        0xC6,                  /* TEMP 2 Over Low part in DataSheet */
+        0xC3,                  /* TEMP 2 Thyst High part in DataSheet */
+        0xC4},                 /* TEMP 2 Thyst Low part in DataSheet */
+       {0xC8,                  /* TEMP 3 in DataSheet */
+        0xC9,                  /* TEMP 3(0.5 deg) in DataSheet */
+        0xCD,                  /* TEMP 3 Over High part in DataSheet */
+        0xCE,                  /* TEMP 3 Over Low part in DataSheet */
+        0xCB,                  /* TEMP 3 Thyst High part in DataSheet */
+        0xCC}                  /* TEMP 3 Thyst Low part in DataSheet */
+};
+
+#define W83791D_REG_BEEP_CONFIG                0x4D
+
+static const u8 W83791D_REG_BEEP_CTRL[3] = {
+       0x56,                   /* BEEP Control Register 1 */
+       0x57,                   /* BEEP Control Register 2 */
+       0xA3,                   /* BEEP Control Register 3 */
+};
+
+#define W83791D_REG_CONFIG             0x40
+#define W83791D_REG_VID_FANDIV         0x47
+#define W83791D_REG_DID_VID4           0x49
+#define W83791D_REG_WCHIPID            0x58
+#define W83791D_REG_CHIPMAN            0x4F
+#define W83791D_REG_PIN                        0x4B
+#define W83791D_REG_I2C_SUBADDR                0x4A
+
+#define W83791D_REG_ALARM1 0xA9        /* realtime status register1 */
+#define W83791D_REG_ALARM2 0xAA        /* realtime status register2 */
+#define W83791D_REG_ALARM3 0xAB        /* realtime status register3 */
+
+#define W83791D_REG_VBAT               0x5D
+#define W83791D_REG_I2C_ADDR           0x48
+
+/* The SMBus locks itself. The Winbond W83791D has a bank select register
+   (index 0x4e), but the driver only accesses registers in bank 0. Since
+   we don't switch banks, we don't need any special code to handle
+   locking access between bank switches */
+static inline int w83791d_read(struct i2c_client *client, u8 reg)
+{
+       return i2c_smbus_read_byte_data(client, reg);
+}
+
+static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value)
+{
+       return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* The analog voltage inputs have 16mV LSB. Since the sysfs output is
+   in mV as would be measured on the chip input pin, need to just
+   multiply/divide by 16 to translate from/to register values. */
+#define IN_TO_REG(val)         (SENSORS_LIMIT((((val) + 8) / 16), 0, 255))
+#define IN_FROM_REG(val)       ((val) * 16)
+
+static u8 fan_to_reg(long rpm, int div)
+{
+       if (rpm == 0)
+               return 255;
+       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)  ((val) == 0   ? -1 : \
+                               ((val) == 255 ? 0 : \
+                                       1350000 / ((val) * (div))))
+
+/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */
+#define TEMP1_FROM_REG(val)    ((val) * 1000)
+#define TEMP1_TO_REG(val)      ((val) <= -128000 ? -128 : \
+                                (val) >= 127000 ? 127 : \
+                                (val) < 0 ? ((val) - 500) / 1000 : \
+                                ((val) + 500) / 1000)
+
+/* for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius
+   Assumes the top 8 bits are the integral amount and the bottom 8 bits
+   are the fractional amount. Since we only have 0.5 degree resolution,
+   the bottom 7 bits will always be zero */
+#define TEMP23_FROM_REG(val)   ((val) / 128 * 500)
+#define TEMP23_TO_REG(val)     ((val) <= -128000 ? 0x8000 : \
+                                (val) >= 127500 ? 0x7F80 : \
+                                (val) < 0 ? ((val) - 250) / 500 * 128 : \
+                                ((val) + 250) / 500 * 128)
+
+
+#define BEEP_MASK_TO_REG(val)          ((val) & 0xffffff)
+#define BEEP_MASK_FROM_REG(val)                ((val) & 0xffffff)
+
+#define DIV_FROM_REG(val)              (1 << (val))
+
+static u8 div_to_reg(int nr, long val)
+{
+       int i;
+       int max;
+
+       /* first three fan's divisor max out at 8, rest max out at 128 */
+       max = (nr < 3) ? 8 : 128;
+       val = SENSORS_LIMIT(val, 1, max) >> 1;
+       for (i = 0; i < 7; i++) {
+               if (val == 0)
+                       break;
+               val >>= 1;
+       }
+       return (u8) i;
+}
+
+struct w83791d_data {
+       struct i2c_client client;
+       struct class_device *class_dev;
+       struct mutex update_lock;
+
+       char valid;                     /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+
+       /* array of 2 pointers to subclients */
+       struct i2c_client *lm75[2];
+
+       /* volts */
+       u8 in[NUMBER_OF_VIN];           /* Register value */
+       u8 in_max[NUMBER_OF_VIN];       /* Register value */
+       u8 in_min[NUMBER_OF_VIN];       /* Register value */
+
+       /* fans */
+       u8 fan[NUMBER_OF_FANIN];        /* Register value */
+       u8 fan_min[NUMBER_OF_FANIN];    /* Register value */
+       u8 fan_div[NUMBER_OF_FANIN];    /* Register encoding, shifted right */
+
+       /* Temperature sensors */
+
+       s8 temp1[3];            /* current, over, thyst */
+       s16 temp_add[2][3];     /* fixed point value. Top 8 bits are the
+                                  integral part, bottom 8 bits are the
+                                  fractional part. We only use the top
+                                  9 bits as the resolution is only
+                                  to the 0.5 degree C...
+                                  two sensors with three values
+                                  (cur, over, hyst)  */
+
+       /* Misc */
+       u32 alarms;             /* realtime status register encoding,combined */
+       u8 beep_enable;         /* Global beep enable */
+       u32 beep_mask;          /* Mask off specific beeps */
+       u8 vid;                 /* Register encoding, combined */
+       u8 vrm;                 /* hwmon-vid */
+};
+
+static int w83791d_attach_adapter(struct i2c_adapter *adapter);
+static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83791d_detach_client(struct i2c_client *client);
+
+static int w83791d_read(struct i2c_client *client, u8 register);
+static int w83791d_write(struct i2c_client *client, u8 register, u8 value);
+static struct w83791d_data *w83791d_update_device(struct device *dev);
+
+#ifdef DEBUG
+static void w83791d_print_debug(struct w83791d_data *data, struct device *dev);
+#endif
+
+static void w83791d_init_client(struct i2c_client *client);
+
+static struct i2c_driver w83791d_driver = {
+       .driver = {
+               .name = "w83791d",
+       },
+       .attach_adapter = w83791d_attach_adapter,
+       .detach_client = w83791d_detach_client,
+};
+
+/* following are the sysfs callback functions */
+#define show_in_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+                       char *buf) \
+{ \
+       struct sensor_device_attribute *sensor_attr = \
+                                               to_sensor_dev_attr(attr); \
+       struct w83791d_data *data = w83791d_update_device(dev); \
+       int nr = sensor_attr->index; \
+       return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \
+}
+
+show_in_reg(in);
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg(struct device *dev, \
+                               struct device_attribute *attr, \
+                               const char *buf, size_t count) \
+{ \
+       struct sensor_device_attribute *sensor_attr = \
+                                               to_sensor_dev_attr(attr); \
+       struct i2c_client *client = to_i2c_client(dev); \
+       struct w83791d_data *data = i2c_get_clientdata(client); \
+       unsigned long val = simple_strtoul(buf, NULL, 10); \
+       int nr = sensor_attr->index; \
+        \
+       mutex_lock(&data->update_lock); \
+       data->in_##reg[nr] = IN_TO_REG(val); \
+       w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+       mutex_unlock(&data->update_lock); \
+        \
+       return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+static struct sensor_device_attribute sda_in_input[] = {
+       SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+       SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+       SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+       SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+       SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+       SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+       SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+       SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+       SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
+       SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
+};
+
+static struct sensor_device_attribute sda_in_min[] = {
+       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
+       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
+       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
+       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
+       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
+       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
+       SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
+};
+
+static struct sensor_device_attribute sda_in_max[] = {
+       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
+       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
+       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
+       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
+       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
+       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
+       SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
+};
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+                               char *buf) \
+{ \
+       struct sensor_device_attribute *sensor_attr = \
+                                               to_sensor_dev_attr(attr); \
+       struct w83791d_data *data = w83791d_update_device(dev); \
+       int nr = sensor_attr->index; \
+       return sprintf(buf,"%d\n", \
+               FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       int nr = sensor_attr->index;
+
+       mutex_lock(&data->update_lock);
+       data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr]));
+       w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       int nr = sensor_attr->index;
+       unsigned long min;
+       u8 tmp_fan_div;
+       u8 fan_div_reg;
+       int indx = 0;
+       u8 keep_mask = 0;
+       u8 new_shift = 0;
+
+       /* Save fan_min */
+       min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
+
+       mutex_lock(&data->update_lock);
+       data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10));
+
+       switch (nr) {
+       case 0:
+               indx = 0;
+               keep_mask = 0xcf;
+               new_shift = 4;
+               break;
+       case 1:
+               indx = 0;
+               keep_mask = 0x3f;
+               new_shift = 6;
+               break;
+       case 2:
+               indx = 1;
+               keep_mask = 0x3f;
+               new_shift = 6;
+               break;
+       case 3:
+               indx = 2;
+               keep_mask = 0xf8;
+               new_shift = 0;
+               break;
+       case 4:
+               indx = 2;
+               keep_mask = 0x8f;
+               new_shift = 4;
+               break;
+#ifdef DEBUG
+       default:
+               dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr);
+               count = -EINVAL;
+               goto err_exit;
+#endif
+       }
+
+       fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx])
+                       & keep_mask;
+       tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask;
+
+       w83791d_write(client, W83791D_REG_FAN_DIV[indx],
+                               fan_div_reg | tmp_fan_div);
+
+       /* Restore fan_min */
+       data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
+       w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
+
+#ifdef DEBUG
+err_exit:
+#endif
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static struct sensor_device_attribute sda_fan_input[] = {
+       SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
+       SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
+       SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
+       SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
+       SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
+};
+
+static struct sensor_device_attribute sda_fan_min[] = {
+       SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 0),
+       SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 1),
+       SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 2),
+       SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 3),
+       SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+                       show_fan_min, store_fan_min, 4),
+};
+
+static struct sensor_device_attribute sda_fan_div[] = {
+       SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 0),
+       SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 1),
+       SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 2),
+       SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 3),
+       SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO,
+                       show_fan_div, store_fan_div, 4),
+};
+
+/* read/write the temperature1, includes measured value and limits */
+static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
+                               char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index]));
+}
+
+static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr,
+                               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->index;
+
+       mutex_lock(&data->update_lock);
+       data->temp1[nr] = TEMP1_TO_REG(val);
+       w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
+/* read/write temperature2-3, includes measured value and limits */
+static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr,
+                               char *buf)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct w83791d_data *data = w83791d_update_device(dev);
+       int nr = attr->nr;
+       int index = attr->index;
+       return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index]));
+}
+
+static ssize_t store_temp23(struct device *dev,
+                               struct device_attribute *devattr,
+                               const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int nr = attr->nr;
+       int index = attr->index;
+
+       mutex_lock(&data->update_lock);
+       data->temp_add[nr][index] = TEMP23_TO_REG(val);
+       w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2],
+                               data->temp_add[nr][index] >> 8);
+       w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1],
+                               data->temp_add[nr][index] & 0x80);
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static struct sensor_device_attribute_2 sda_temp_input[] = {
+       SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
+       SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
+       SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max[] = {
+       SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
+                       show_temp1, store_temp1, 0, 1),
+       SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR,
+                       show_temp23, store_temp23, 0, 1),
+       SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR,
+                       show_temp23, store_temp23, 1, 1),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
+       SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
+                       show_temp1, store_temp1, 0, 2),
+       SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
+                       show_temp23, store_temp23, 0, 2),
+       SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR,
+                       show_temp23, store_temp23, 1, 2),
+};
+
+
+/* get reatime status of all sensors items: voltage, temp, fan */
+static ssize_t show_alarms_reg(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%u\n", data->alarms);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+
+/* Beep control */
+
+#define GLOBAL_BEEP_ENABLE_SHIFT       15
+#define GLOBAL_BEEP_ENABLE_MASK                (1 << GLOBAL_BEEP_ENABLE_SHIFT)
+
+static ssize_t show_beep_enable(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%d\n", data->beep_enable);
+}
+
+static ssize_t show_beep_mask(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask));
+}
+
+
+static ssize_t store_beep_mask(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       int i;
+
+       mutex_lock(&data->update_lock);
+
+       /* The beep_enable state overrides any enabling request from
+          the masks */
+       data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK;
+       data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
+
+       val = data->beep_mask;
+
+       for (i = 0; i < 3; i++) {
+               w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff));
+               val >>= 8;
+       }
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static ssize_t store_beep_enable(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+
+       mutex_lock(&data->update_lock);
+
+       data->beep_enable = val ? 1 : 0;
+
+       /* Keep the full mask value in sync with the current enable */
+       data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK;
+       data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
+
+       /* The global control is in the second beep control register
+          so only need to update that register */
+       val = (data->beep_mask >> 8) & 0xff;
+
+       w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val);
+
+       mutex_unlock(&data->update_lock);
+
+       return count;
+}
+
+static struct sensor_device_attribute sda_beep_ctrl[] = {
+       SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+                       show_beep_enable, store_beep_enable, 0),
+       SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR,
+                       show_beep_mask, store_beep_mask, 1)
+};
+
+/* cpu voltage regulation information */
+static ssize_t show_vid_reg(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
+
+static ssize_t show_vrm_reg(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct w83791d_data *data = w83791d_update_device(dev);
+       return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t store_vrm_reg(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+
+       /* No lock needed as vrm is internal to the driver
+          (not read from a chip register) and so is not
+          updated in w83791d_update_device() */
+       data->vrm = val;
+
+       return count;
+}
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
+
+/* This function is called when:
+     * w83791d_driver is inserted (when this module is loaded), for each
+       available adapter
+     * when a new adapter is inserted (and w83791d_driver is still present) */
+static int w83791d_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_probe(adapter, &addr_data, w83791d_detect);
+}
+
+
+static int w83791d_create_subclient(struct i2c_adapter *adapter,
+                               struct i2c_client *client, int addr,
+                               struct i2c_client **sub_cli)
+{
+       int err;
+       struct i2c_client *sub_client;
+
+       (*sub_cli) = sub_client =
+                       kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (!(sub_client)) {
+               return -ENOMEM;
+       }
+       sub_client->addr = 0x48 + addr;
+       i2c_set_clientdata(sub_client, NULL);
+       sub_client->adapter = adapter;
+       sub_client->driver = &w83791d_driver;
+       strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE);
+       if ((err = i2c_attach_client(sub_client))) {
+               dev_err(&client->dev, "subclient registration "
+                       "at address 0x%x failed\n", sub_client->addr);
+               kfree(sub_client);
+               return err;
+       }
+       return 0;
+}
+
+
+static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
+                               int kind, struct i2c_client *client)
+{
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       int i, id, err;
+       u8 val;
+
+       id = i2c_adapter_id(adapter);
+       if (force_subclients[0] == id && force_subclients[1] == address) {
+               for (i = 2; i <= 3; i++) {
+                       if (force_subclients[i] < 0x48 ||
+                           force_subclients[i] > 0x4f) {
+                               dev_err(&client->dev,
+                                       "invalid subclient "
+                                       "address %d; must be 0x48-0x4f\n",
+                                       force_subclients[i]);
+                               err = -ENODEV;
+                               goto error_sc_0;
+                       }
+               }
+               w83791d_write(client, W83791D_REG_I2C_SUBADDR,
+                                       (force_subclients[2] & 0x07) |
+                                       ((force_subclients[3] & 0x07) << 4));
+       }
+
+       val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
+       if (!(val & 0x08)) {
+               err = w83791d_create_subclient(adapter, client,
+                                               val & 0x7, &data->lm75[0]);
+               if (err < 0)
+                       goto error_sc_0;
+       }
+       if (!(val & 0x80)) {
+               if ((data->lm75[0] != NULL) &&
+                               ((val & 0x7) == ((val >> 4) & 0x7))) {
+                       dev_err(&client->dev,
+                               "duplicate addresses 0x%x, "
+                               "use force_subclient\n",
+                               data->lm75[0]->addr);
+                       err = -ENODEV;
+                       goto error_sc_1;
+               }
+               err = w83791d_create_subclient(adapter, client,
+                                       (val >> 4) & 0x7, &data->lm75[1]);
+               if (err < 0)
+                       goto error_sc_1;
+       }
+
+       return 0;
+
+/* Undo inits in case of errors */
+
+error_sc_1:
+       if (data->lm75[0] != NULL) {
+               i2c_detach_client(data->lm75[0]);
+               kfree(data->lm75[0]);
+       }
+error_sc_0:
+       return err;
+}
+
+
+static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *client;
+       struct device *dev;
+       struct w83791d_data *data;
+       int i, val1, val2;
+       int err = 0;
+       const char *client_name = "";
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               goto error0;
+       }
+
+       /* OK. For now, we presume we have a valid client. We now create the
+          client structure, even though we cannot fill it completely yet.
+          But it allows us to access w83791d_{read,write}_value. */
+       if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto error0;
+       }
+
+       client = &data->client;
+       dev = &client->dev;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &w83791d_driver;
+       mutex_init(&data->update_lock);
+
+       /* Now, we do the remaining detection. */
+
+       /* The w83791d may be stuck in some other bank than bank 0. This may
+          make reading other information impossible. Specify a force=...
+          parameter, and the Winbond will be reset to the right bank. */
+       if (kind < 0) {
+               if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) {
+                       dev_dbg(dev, "Detection failed at step 1\n");
+                       goto error1;
+               }
+               val1 = w83791d_read(client, W83791D_REG_BANK);
+               val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
+               /* Check for Winbond ID if in bank 0 */
+               if (!(val1 & 0x07)) {
+                       /* yes it is Bank0 */
+                       if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
+                           ((val1 & 0x80) && (val2 != 0x5c))) {
+                               dev_dbg(dev, "Detection failed at step 2\n");
+                               goto error1;
+                       }
+               }
+               /* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
+                  should match */
+               if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) {
+                       dev_dbg(dev, "Detection failed at step 3\n");
+                       goto error1;
+               }
+       }
+
+       /* We either have a force parameter or we have reason to
+          believe it is a Winbond chip. Either way, we want bank 0 and
+          Vendor ID high byte */
+       val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78;
+       w83791d_write(client, W83791D_REG_BANK, val1 | 0x80);
+
+       /* Verify it is a Winbond w83791d */
+       if (kind <= 0) {
+               /* get vendor ID */
+               val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
+               if (val2 != 0x5c) {     /* the vendor is NOT Winbond */
+                       dev_dbg(dev, "Detection failed at step 4\n");
+                       goto error1;
+               }
+               val1 = w83791d_read(client, W83791D_REG_WCHIPID);
+               if (val1 == 0x71) {
+                       kind = w83791d;
+               } else {
+                       if (kind == 0)
+                               dev_warn(dev,
+                                       "w83791d: Ignoring 'force' parameter "
+                                       "for unknown chip at adapter %d, "
+                                       "address 0x%02x\n",
+                                       i2c_adapter_id(adapter), address);
+                       goto error1;
+               }
+       }
+
+       if (kind == w83791d) {
+               client_name = "w83791d";
+       } else {
+               dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?",
+                       kind);
+               goto error1;
+       }
+
+#ifdef DEBUG
+       val1 = w83791d_read(client, W83791D_REG_DID_VID4);
+       dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n",
+                       (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
+#endif
+
+       /* Fill in the remaining client fields and put into the global list */
+       strlcpy(client->name, client_name, I2C_NAME_SIZE);
+
+       /* Tell the I2C layer a new client has arrived */
+       if ((err = i2c_attach_client(client)))
+               goto error1;
+
+       if ((err = w83791d_detect_subclients(adapter, address, kind, client)))
+               goto error2;
+
+       /* Initialize the chip */
+       w83791d_init_client(client);
+
+       /* If the fan_div is changed, make sure there is a rational
+          fan_min in place */
+       for (i = 0; i < NUMBER_OF_FANIN; i++) {
+               data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]);
+       }
+
+       /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto error3;
+       }
+
+       for (i = 0; i < NUMBER_OF_VIN; i++) {
+               device_create_file(dev, &sda_in_input[i].dev_attr);
+               device_create_file(dev, &sda_in_min[i].dev_attr);
+               device_create_file(dev, &sda_in_max[i].dev_attr);
+       }
+
+       for (i = 0; i < NUMBER_OF_FANIN; i++) {
+               device_create_file(dev, &sda_fan_input[i].dev_attr);
+               device_create_file(dev, &sda_fan_div[i].dev_attr);
+               device_create_file(dev, &sda_fan_min[i].dev_attr);
+       }
+
+       for (i = 0; i < NUMBER_OF_TEMPIN; i++) {
+               device_create_file(dev, &sda_temp_input[i].dev_attr);
+               device_create_file(dev, &sda_temp_max[i].dev_attr);
+               device_create_file(dev, &sda_temp_max_hyst[i].dev_attr);
+       }
+
+       device_create_file(dev, &dev_attr_alarms);
+
+       for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) {
+               device_create_file(dev, &sda_beep_ctrl[i].dev_attr);
+       }
+
+       device_create_file(dev, &dev_attr_cpu0_vid);
+       device_create_file(dev, &dev_attr_vrm);
+
+       return 0;
+
+error3:
+       if (data->lm75[0] != NULL) {
+               i2c_detach_client(data->lm75[0]);
+               kfree(data->lm75[0]);
+       }
+       if (data->lm75[1] != NULL) {
+               i2c_detach_client(data->lm75[1]);
+               kfree(data->lm75[1]);
+       }
+error2:
+       i2c_detach_client(client);
+error1:
+       kfree(data);
+error0:
+       return err;
+}
+
+static int w83791d_detach_client(struct i2c_client *client)
+{
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       int err;
+
+       /* main client */
+       if (data)
+               hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
+               return err;
+
+       /* main client */
+       if (data)
+               kfree(data);
+       /* subclient */
+       else
+               kfree(client);
+
+       return 0;
+}
+
+static void w83791d_init_client(struct i2c_client *client)
+{
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       u8 tmp;
+       u8 old_beep;
+
+       /* The difference between reset and init is that reset
+          does a hard reset of the chip via index 0x40, bit 7,
+          but init simply forces certain registers to have "sane"
+          values. The hope is that the BIOS has done the right
+          thing (which is why the default is reset=0, init=0),
+          but if not, reset is the hard hammer and init
+          is the soft mallet both of which are trying to whack
+          things into place...
+          NOTE: The data sheet makes a distinction between
+          "power on defaults" and "reset by MR". As far as I can tell,
+          the hard reset puts everything into a power-on state so I'm
+          not sure what "reset by MR" means or how it can happen.
+          */
+       if (reset || init) {
+               /* keep some BIOS settings when we... */
+               old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG);
+
+               if (reset) {
+                       /* ... reset the chip and ... */
+                       w83791d_write(client, W83791D_REG_CONFIG, 0x80);
+               }
+
+               /* ... disable power-on abnormal beep */
+               w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80);
+
+               /* disable the global beep (not done by hard reset) */
+               tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]);
+               w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef);
+
+               if (init) {
+                       /* Make sure monitoring is turned on for add-ons */
+                       tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG);
+                       if (tmp & 1) {
+                               w83791d_write(client, W83791D_REG_TEMP2_CONFIG,
+                                       tmp & 0xfe);
+                       }
+
+                       tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG);
+                       if (tmp & 1) {
+                               w83791d_write(client, W83791D_REG_TEMP3_CONFIG,
+                                       tmp & 0xfe);
+                       }
+
+                       /* Start monitoring */
+                       tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7;
+                       w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01);
+               }
+       }
+
+       data->vrm = vid_which_vrm();
+}
+
+static struct w83791d_data *w83791d_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83791d_data *data = i2c_get_clientdata(client);
+       int i, j;
+       u8 reg_array_tmp[3];
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + (HZ * 3))
+                       || !data->valid) {
+               dev_dbg(dev, "Starting w83791d device update\n");
+
+               /* Update the voltages measured value and limits */
+               for (i = 0; i < NUMBER_OF_VIN; i++) {
+                       data->in[i] = w83791d_read(client,
+                                               W83791D_REG_IN[i]);
+                       data->in_max[i] = w83791d_read(client,
+                                               W83791D_REG_IN_MAX[i]);
+                       data->in_min[i] = w83791d_read(client,
+                                               W83791D_REG_IN_MIN[i]);
+               }
+
+               /* Update the fan counts and limits */
+               for (i = 0; i < NUMBER_OF_FANIN; i++) {
+                       /* Update the Fan measured value and limits */
+                       data->fan[i] = w83791d_read(client,
+                                               W83791D_REG_FAN[i]);
+                       data->fan_min[i] = w83791d_read(client,
+                                               W83791D_REG_FAN_MIN[i]);
+               }
+
+               /* Update the fan divisor */
+               for (i = 0; i < 3; i++) {
+                       reg_array_tmp[i] = w83791d_read(client,
+                                               W83791D_REG_FAN_DIV[i]);
+               }
+               data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03;
+               data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03;
+               data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03;
+               data->fan_div[3] = reg_array_tmp[2] & 0x07;
+               data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07;
+
+               /* Update the first temperature sensor */
+               for (i = 0; i < 3; i++) {
+                       data->temp1[i] = w83791d_read(client,
+                                               W83791D_REG_TEMP1[i]);
+               }
+
+               /* Update the rest of the temperature sensors */
+               for (i = 0; i < 2; i++) {
+                       for (j = 0; j < 3; j++) {
+                               data->temp_add[i][j] =
+                                       (w83791d_read(client,
+                                       W83791D_REG_TEMP_ADD[i][j * 2]) << 8) |
+                                       w83791d_read(client,
+                                       W83791D_REG_TEMP_ADD[i][j * 2 + 1]);
+                       }
+               }
+
+               /* Update the realtime status */
+               data->alarms =
+                       w83791d_read(client, W83791D_REG_ALARM1) +
+                       (w83791d_read(client, W83791D_REG_ALARM2) << 8) +
+                       (w83791d_read(client, W83791D_REG_ALARM3) << 16);
+
+               /* Update the beep configuration information */
+               data->beep_mask =
+                       w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) +
+                       (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) +
+                       (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16);
+
+               data->beep_enable =
+                       (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01;
+
+               /* Update the cpu voltage information */
+               i = w83791d_read(client, W83791D_REG_VID_FANDIV);
+               data->vid = i & 0x0f;
+               data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01)
+                               << 4;
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->update_lock);
+
+#ifdef DEBUG
+       w83791d_print_debug(data, dev);
+#endif
+
+       return data;
+}
+
+#ifdef DEBUG
+static void w83791d_print_debug(struct w83791d_data *data, struct device *dev)
+{
+       int i = 0, j = 0;
+
+       dev_dbg(dev, "======Start of w83791d debug values======\n");
+       dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN);
+       for (i = 0; i < NUMBER_OF_VIN; i++) {
+               dev_dbg(dev, "vin[%d] is:     0x%02x\n", i, data->in[i]);
+               dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]);
+               dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]);
+       }
+       dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN);
+       for (i = 0; i < NUMBER_OF_FANIN; i++) {
+               dev_dbg(dev, "fan[%d] is:     0x%02x\n", i, data->fan[i]);
+               dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]);
+               dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]);
+       }
+
+       /* temperature math is signed, but only print out the
+          bits that matter */
+       dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN);
+       for (i = 0; i < 3; i++) {
+               dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]);
+       }
+       for (i = 0; i < 2; i++) {
+               for (j = 0; j < 3; j++) {
+                       dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j,
+                               (u16) data->temp_add[i][j]);
+               }
+       }
+
+       dev_dbg(dev, "Misc Information: ===>\n");
+       dev_dbg(dev, "alarm is:     0x%08x\n", data->alarms);
+       dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask);
+       dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable);
+       dev_dbg(dev, "vid is: 0x%02x\n", data->vid);
+       dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm);
+       dev_dbg(dev, "=======End of w83791d debug values========\n");
+       dev_dbg(dev, "\n");
+}
+#endif
+
+static int __init sensors_w83791d_init(void)
+{
+       return i2c_add_driver(&w83791d_driver);
+}
+
+static void __exit sensors_w83791d_exit(void)
+{
+       i2c_del_driver(&w83791d_driver);
+}
+
+MODULE_AUTHOR("Charles Spirakis <bezaur@gmail.com>");
+MODULE_DESCRIPTION("W83791D driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83791d_init);
+module_exit(sensors_w83791d_exit);
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
new file mode 100644 (file)
index 0000000..820a752
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
+ * (http://www.opencores.org/projects.cgi/web/i2c/overview).
+ *
+ * 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/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/i2c-ocores.h>
+#include <asm/io.h>
+
+struct ocores_i2c {
+       void __iomem *base;
+       int regstep;
+       wait_queue_head_t wait;
+       struct i2c_adapter adap;
+       struct i2c_msg *msg;
+       int pos;
+       int nmsgs;
+       int state; /* see STATE_ */
+};
+
+/* registers */
+#define OCI2C_PRELOW           0
+#define OCI2C_PREHIGH          1
+#define OCI2C_CONTROL          2
+#define OCI2C_DATA             3
+#define OCI2C_CMD              4 /* write only */
+#define OCI2C_STATUS           4 /* read only, same address as OCI2C_CMD */
+
+#define OCI2C_CTRL_IEN         0x40
+#define OCI2C_CTRL_EN          0x80
+
+#define OCI2C_CMD_START                0x91
+#define OCI2C_CMD_STOP         0x41
+#define OCI2C_CMD_READ         0x21
+#define OCI2C_CMD_WRITE                0x11
+#define OCI2C_CMD_READ_ACK     0x21
+#define OCI2C_CMD_READ_NACK    0x29
+#define OCI2C_CMD_IACK         0x01
+
+#define OCI2C_STAT_IF          0x01
+#define OCI2C_STAT_TIP         0x02
+#define OCI2C_STAT_ARBLOST     0x20
+#define OCI2C_STAT_BUSY                0x40
+#define OCI2C_STAT_NACK                0x80
+
+#define STATE_DONE             0
+#define STATE_START            1
+#define STATE_WRITE            2
+#define STATE_READ             3
+#define STATE_ERROR            4
+
+static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
+{
+       iowrite8(value, i2c->base + reg * i2c->regstep);
+}
+
+static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
+{
+       return ioread8(i2c->base + reg * i2c->regstep);
+}
+
+static void ocores_process(struct ocores_i2c *i2c)
+{
+       struct i2c_msg *msg = i2c->msg;
+       u8 stat = oc_getreg(i2c, OCI2C_STATUS);
+
+       if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
+               /* stop has been sent */
+               oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
+               wake_up(&i2c->wait);
+               return;
+       }
+
+       /* error? */
+       if (stat & OCI2C_STAT_ARBLOST) {
+               i2c->state = STATE_ERROR;
+               oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+               return;
+       }
+
+       if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) {
+               i2c->state =
+                       (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
+
+               if (stat & OCI2C_STAT_NACK) {
+                       i2c->state = STATE_ERROR;
+                       oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+                       return;
+               }
+       } else
+               msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA);
+
+       /* end of msg? */
+       if (i2c->pos == msg->len) {
+               i2c->nmsgs--;
+               i2c->msg++;
+               i2c->pos = 0;
+               msg = i2c->msg;
+
+               if (i2c->nmsgs) {       /* end? */
+                       /* send start? */
+                       if (!(msg->flags & I2C_M_NOSTART)) {
+                               u8 addr = (msg->addr << 1);
+
+                               if (msg->flags & I2C_M_RD)
+                                       addr |= 1;
+
+                               i2c->state = STATE_START;
+
+                               oc_setreg(i2c, OCI2C_DATA, addr);
+                               oc_setreg(i2c, OCI2C_CMD,  OCI2C_CMD_START);
+                               return;
+                       } else
+                               i2c->state = (msg->flags & I2C_M_RD)
+                                       ? STATE_READ : STATE_WRITE;
+               } else {
+                       i2c->state = STATE_DONE;
+                       oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+                       return;
+               }
+       }
+
+       if (i2c->state == STATE_READ) {
+               oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ?
+                         OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK);
+       } else {
+               oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);
+               oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);
+       }
+}
+
+static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct ocores_i2c *i2c = dev_id;
+
+       ocores_process(i2c);
+
+       return IRQ_HANDLED;
+}
+
+static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       struct ocores_i2c *i2c = i2c_get_adapdata(adap);
+
+       i2c->msg = msgs;
+       i2c->pos = 0;
+       i2c->nmsgs = num;
+       i2c->state = STATE_START;
+
+       oc_setreg(i2c, OCI2C_DATA,
+                       (i2c->msg->addr << 1) |
+                       ((i2c->msg->flags & I2C_M_RD) ? 1:0));
+
+       oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
+
+       if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
+                              (i2c->state == STATE_DONE), HZ))
+               return (i2c->state == STATE_DONE) ? num : -EIO;
+       else
+               return -ETIMEDOUT;
+}
+
+static void ocores_init(struct ocores_i2c *i2c,
+                       struct ocores_i2c_platform_data *pdata)
+{
+       int prescale;
+       u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
+
+       /* make sure the device is disabled */
+       oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
+
+       prescale = (pdata->clock_khz / (5*100)) - 1;
+       oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
+       oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
+
+       /* Init the device */
+       oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
+       oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN);
+}
+
+
+static u32 ocores_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm ocores_algorithm = {
+       .master_xfer    = ocores_xfer,
+       .functionality  = ocores_func,
+};
+
+static struct i2c_adapter ocores_adapter = {
+       .owner          = THIS_MODULE,
+       .name           = "i2c-ocores",
+       .class          = I2C_CLASS_HWMON,
+       .algo           = &ocores_algorithm,
+};
+
+
+static int __devinit ocores_i2c_probe(struct platform_device *pdev)
+{
+       struct ocores_i2c *i2c;
+       struct ocores_i2c_platform_data *pdata;
+       struct resource *res, *res2;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res2)
+               return -ENODEV;
+
+       pdata = (struct ocores_i2c_platform_data*) pdev->dev.platform_data;
+       if (!pdata)
+               return -ENODEV;
+
+       i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+       if (!i2c)
+               return -ENOMEM;
+
+       if (!request_mem_region(res->start, res->end - res->start + 1,
+                               pdev->name)) {
+               dev_err(&pdev->dev, "Memory region busy\n");
+               ret = -EBUSY;
+               goto request_mem_failed;
+       }
+
+       i2c->base = ioremap(res->start, res->end - res->start + 1);
+       if (!i2c->base) {
+               dev_err(&pdev->dev, "Unable to map registers\n");
+               ret = -EIO;
+               goto map_failed;
+       }
+
+       i2c->regstep = pdata->regstep;
+       ocores_init(i2c, pdata);
+
+       init_waitqueue_head(&i2c->wait);
+       ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c);
+       if (ret) {
+               dev_err(&pdev->dev, "Cannot claim IRQ\n");
+               goto request_irq_failed;
+       }
+
+       /* hook up driver to tree */
+       platform_set_drvdata(pdev, i2c);
+       i2c->adap = ocores_adapter;
+       i2c_set_adapdata(&i2c->adap, i2c);
+       i2c->adap.dev.parent = &pdev->dev;
+
+       /* add i2c adapter to i2c tree */
+       ret = i2c_add_adapter(&i2c->adap);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to add adapter\n");
+               goto add_adapter_failed;
+       }
+
+       return 0;
+
+add_adapter_failed:
+       free_irq(res2->start, i2c);
+request_irq_failed:
+       iounmap(i2c->base);
+map_failed:
+       release_mem_region(res->start, res->end - res->start + 1);
+request_mem_failed:
+       kfree(i2c);
+
+       return ret;
+}
+
+static int __devexit ocores_i2c_remove(struct platform_device* pdev)
+{
+       struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       /* disable i2c logic */
+       oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL)
+                 & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
+
+       /* remove adapter & data */
+       i2c_del_adapter(&i2c->adap);
+       platform_set_drvdata(pdev, NULL);
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res)
+               free_irq(res->start, i2c);
+
+       iounmap(i2c->base);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res)
+               release_mem_region(res->start, res->end - res->start + 1);
+
+       kfree(i2c);
+
+       return 0;
+}
+
+static struct platform_driver ocores_i2c_driver = {
+       .probe  = ocores_i2c_probe,
+       .remove = __devexit_p(ocores_i2c_remove),
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "ocores-i2c",
+       },
+};
+
+static int __init ocores_i2c_init(void)
+{
+       return platform_driver_register(&ocores_i2c_driver);
+}
+
+static void __exit ocores_i2c_exit(void)
+{
+       platform_driver_unregister(&ocores_i2c_driver);
+}
+
+module_init(ocores_i2c_init);
+module_exit(ocores_i2c_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("OpenCores I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
new file mode 100644 (file)
index 0000000..1205e80
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+#include <linux/mutex.h>
+#include <linux/inetdevice.h>
+#include <linux/workqueue.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+#include <net/neighbour.h>
+#include <net/route.h>
+#include <net/netevent.h>
+#include <rdma/ib_addr.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("IB Address Translation");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct addr_req {
+       struct list_head list;
+       struct sockaddr src_addr;
+       struct sockaddr dst_addr;
+       struct rdma_dev_addr *addr;
+       void *context;
+       void (*callback)(int status, struct sockaddr *src_addr,
+                        struct rdma_dev_addr *addr, void *context);
+       unsigned long timeout;
+       int status;
+};
+
+static void process_req(void *data);
+
+static DEFINE_MUTEX(lock);
+static LIST_HEAD(req_list);
+static DECLARE_WORK(work, process_req, NULL);
+static struct workqueue_struct *addr_wq;
+
+static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
+                    unsigned char *dst_dev_addr)
+{
+       switch (dev->type) {
+       case ARPHRD_INFINIBAND:
+               dev_addr->dev_type = IB_NODE_CA;
+               break;
+       default:
+               return -EADDRNOTAVAIL;
+       }
+
+       memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+       memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN);
+       if (dst_dev_addr)
+               memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN);
+       return 0;
+}
+
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
+{
+       struct net_device *dev;
+       u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+       int ret;
+
+       dev = ip_dev_find(ip);
+       if (!dev)
+               return -EADDRNOTAVAIL;
+
+       ret = copy_addr(dev_addr, dev, NULL);
+       dev_put(dev);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_translate_ip);
+
+static void set_timeout(unsigned long time)
+{
+       unsigned long delay;
+
+       cancel_delayed_work(&work);
+
+       delay = time - jiffies;
+       if ((long)delay <= 0)
+               delay = 1;
+
+       queue_delayed_work(addr_wq, &work, delay);
+}
+
+static void queue_req(struct addr_req *req)
+{
+       struct addr_req *temp_req;
+
+       mutex_lock(&lock);
+       list_for_each_entry_reverse(temp_req, &req_list, list) {
+               if (time_after(req->timeout, temp_req->timeout))
+                       break;
+       }
+
+       list_add(&req->list, &temp_req->list);
+
+       if (req_list.next == &req->list)
+               set_timeout(req->timeout);
+       mutex_unlock(&lock);
+}
+
+static void addr_send_arp(struct sockaddr_in *dst_in)
+{
+       struct rtable *rt;
+       struct flowi fl;
+       u32 dst_ip = dst_in->sin_addr.s_addr;
+
+       memset(&fl, 0, sizeof fl);
+       fl.nl_u.ip4_u.daddr = dst_ip;
+       if (ip_route_output_key(&rt, &fl))
+               return;
+
+       arp_send(ARPOP_REQUEST, ETH_P_ARP, rt->rt_gateway, rt->idev->dev,
+                rt->rt_src, NULL, rt->idev->dev->dev_addr, NULL);
+       ip_rt_put(rt);
+}
+
+static int addr_resolve_remote(struct sockaddr_in *src_in,
+                              struct sockaddr_in *dst_in,
+                              struct rdma_dev_addr *addr)
+{
+       u32 src_ip = src_in->sin_addr.s_addr;
+       u32 dst_ip = dst_in->sin_addr.s_addr;
+       struct flowi fl;
+       struct rtable *rt;
+       struct neighbour *neigh;
+       int ret;
+
+       memset(&fl, 0, sizeof fl);
+       fl.nl_u.ip4_u.daddr = dst_ip;
+       fl.nl_u.ip4_u.saddr = src_ip;
+       ret = ip_route_output_key(&rt, &fl);
+       if (ret)
+               goto out;
+
+       /* If the device does ARP internally, return 'done' */
+       if (rt->idev->dev->flags & IFF_NOARP) {
+               copy_addr(addr, rt->idev->dev, NULL);
+               goto put;
+       }
+
+       neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
+       if (!neigh) {
+               ret = -ENODATA;
+               goto put;
+       }
+
+       if (!(neigh->nud_state & NUD_VALID)) {
+               ret = -ENODATA;
+               goto release;
+       }
+
+       if (!src_ip) {
+               src_in->sin_family = dst_in->sin_family;
+               src_in->sin_addr.s_addr = rt->rt_src;
+       }
+
+       ret = copy_addr(addr, neigh->dev, neigh->ha);
+release:
+       neigh_release(neigh);
+put:
+       ip_rt_put(rt);
+out:
+       return ret;
+}
+
+static void process_req(void *data)
+{
+       struct addr_req *req, *temp_req;
+       struct sockaddr_in *src_in, *dst_in;
+       struct list_head done_list;
+
+       INIT_LIST_HEAD(&done_list);
+
+       mutex_lock(&lock);
+       list_for_each_entry_safe(req, temp_req, &req_list, list) {
+               if (req->status) {
+                       src_in = (struct sockaddr_in *) &req->src_addr;
+                       dst_in = (struct sockaddr_in *) &req->dst_addr;
+                       req->status = addr_resolve_remote(src_in, dst_in,
+                                                         req->addr);
+               }
+               if (req->status && time_after(jiffies, req->timeout))
+                       req->status = -ETIMEDOUT;
+               else if (req->status == -ENODATA)
+                       continue;
+
+               list_del(&req->list);
+               list_add_tail(&req->list, &done_list);
+       }
+
+       if (!list_empty(&req_list)) {
+               req = list_entry(req_list.next, struct addr_req, list);
+               set_timeout(req->timeout);
+       }
+       mutex_unlock(&lock);
+
+       list_for_each_entry_safe(req, temp_req, &done_list, list) {
+               list_del(&req->list);
+               req->callback(req->status, &req->src_addr, req->addr,
+                             req->context);
+               kfree(req);
+       }
+}
+
+static int addr_resolve_local(struct sockaddr_in *src_in,
+                             struct sockaddr_in *dst_in,
+                             struct rdma_dev_addr *addr)
+{
+       struct net_device *dev;
+       u32 src_ip = src_in->sin_addr.s_addr;
+       u32 dst_ip = dst_in->sin_addr.s_addr;
+       int ret;
+
+       dev = ip_dev_find(dst_ip);
+       if (!dev)
+               return -EADDRNOTAVAIL;
+
+       if (ZERONET(src_ip)) {
+               src_in->sin_family = dst_in->sin_family;
+               src_in->sin_addr.s_addr = dst_ip;
+               ret = copy_addr(addr, dev, dev->dev_addr);
+       } else if (LOOPBACK(src_ip)) {
+               ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
+               if (!ret)
+                       memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+       } else {
+               ret = rdma_translate_ip((struct sockaddr *)src_in, addr);
+               if (!ret)
+                       memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+       }
+
+       dev_put(dev);
+       return ret;
+}
+
+int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+                   struct rdma_dev_addr *addr, int timeout_ms,
+                   void (*callback)(int status, struct sockaddr *src_addr,
+                                    struct rdma_dev_addr *addr, void *context),
+                   void *context)
+{
+       struct sockaddr_in *src_in, *dst_in;
+       struct addr_req *req;
+       int ret = 0;
+
+       req = kmalloc(sizeof *req, GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+       memset(req, 0, sizeof *req);
+
+       if (src_addr)
+               memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr));
+       memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr));
+       req->addr = addr;
+       req->callback = callback;
+       req->context = context;
+
+       src_in = (struct sockaddr_in *) &req->src_addr;
+       dst_in = (struct sockaddr_in *) &req->dst_addr;
+
+       req->status = addr_resolve_local(src_in, dst_in, addr);
+       if (req->status == -EADDRNOTAVAIL)
+               req->status = addr_resolve_remote(src_in, dst_in, addr);
+
+       switch (req->status) {
+       case 0:
+               req->timeout = jiffies;
+               queue_req(req);
+               break;
+       case -ENODATA:
+               req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
+               queue_req(req);
+               addr_send_arp(dst_in);
+               break;
+       default:
+               ret = req->status;
+               kfree(req);
+               break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_ip);
+
+void rdma_addr_cancel(struct rdma_dev_addr *addr)
+{
+       struct addr_req *req, *temp_req;
+
+       mutex_lock(&lock);
+       list_for_each_entry_safe(req, temp_req, &req_list, list) {
+               if (req->addr == addr) {
+                       req->status = -ECANCELED;
+                       req->timeout = jiffies;
+                       list_del(&req->list);
+                       list_add(&req->list, &req_list);
+                       set_timeout(req->timeout);
+                       break;
+               }
+       }
+       mutex_unlock(&lock);
+}
+EXPORT_SYMBOL(rdma_addr_cancel);
+
+static int netevent_callback(struct notifier_block *self, unsigned long event, 
+       void *ctx)
+{
+       if (event == NETEVENT_NEIGH_UPDATE) {  
+               struct neighbour *neigh = ctx;
+
+               if (neigh->dev->type == ARPHRD_INFINIBAND &&
+                   (neigh->nud_state & NUD_VALID)) {
+                       set_timeout(jiffies);
+               }
+       }
+       return 0;
+}
+
+static struct notifier_block nb = {
+       .notifier_call = netevent_callback
+};
+
+static int addr_init(void)
+{
+       addr_wq = create_singlethread_workqueue("ib_addr_wq");
+       if (!addr_wq)
+               return -ENOMEM;
+
+       register_netevent_notifier(&nb);
+       return 0;
+}
+
+static void addr_cleanup(void)
+{
+       unregister_netevent_notifier(&nb);
+       destroy_workqueue(addr_wq);
+}
+
+module_init(addr_init);
+module_exit(addr_cleanup);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
new file mode 100644 (file)
index 0000000..5d625a8
--- /dev/null
@@ -0,0 +1,1929 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#include <linux/completion.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/mutex.h>
+#include <linux/random.h>
+#include <linux/idr.h>
+
+#include <net/tcp.h>
+
+#include <rdma/rdma_cm.h>
+#include <rdma/rdma_cm_ib.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
+#include <rdma/ib_sa.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("Generic RDMA CM Agent");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define CMA_CM_RESPONSE_TIMEOUT 20
+#define CMA_MAX_CM_RETRIES 15
+
+static void cma_add_one(struct ib_device *device);
+static void cma_remove_one(struct ib_device *device);
+
+static struct ib_client cma_client = {
+       .name   = "cma",
+       .add    = cma_add_one,
+       .remove = cma_remove_one
+};
+
+static LIST_HEAD(dev_list);
+static LIST_HEAD(listen_any_list);
+static DEFINE_MUTEX(lock);
+static struct workqueue_struct *cma_wq;
+static DEFINE_IDR(sdp_ps);
+static DEFINE_IDR(tcp_ps);
+
+struct cma_device {
+       struct list_head        list;
+       struct ib_device        *device;
+       __be64                  node_guid;
+       struct completion       comp;
+       atomic_t                refcount;
+       struct list_head        id_list;
+};
+
+enum cma_state {
+       CMA_IDLE,
+       CMA_ADDR_QUERY,
+       CMA_ADDR_RESOLVED,
+       CMA_ROUTE_QUERY,
+       CMA_ROUTE_RESOLVED,
+       CMA_CONNECT,
+       CMA_DISCONNECT,
+       CMA_ADDR_BOUND,
+       CMA_LISTEN,
+       CMA_DEVICE_REMOVAL,
+       CMA_DESTROYING
+};
+
+struct rdma_bind_list {
+       struct idr              *ps;
+       struct hlist_head       owners;
+       unsigned short          port;
+};
+
+/*
+ * Device removal can occur at anytime, so we need extra handling to
+ * serialize notifying the user of device removal with other callbacks.
+ * We do this by disabling removal notification while a callback is in process,
+ * and reporting it after the callback completes.
+ */
+struct rdma_id_private {
+       struct rdma_cm_id       id;
+
+       struct rdma_bind_list   *bind_list;
+       struct hlist_node       node;
+       struct list_head        list;
+       struct list_head        listen_list;
+       struct cma_device       *cma_dev;
+
+       enum cma_state          state;
+       spinlock_t              lock;
+       struct completion       comp;
+       atomic_t                refcount;
+       wait_queue_head_t       wait_remove;
+       atomic_t                dev_remove;
+
+       int                     backlog;
+       int                     timeout_ms;
+       struct ib_sa_query      *query;
+       int                     query_id;
+       union {
+               struct ib_cm_id *ib;
+       } cm_id;
+
+       u32                     seq_num;
+       u32                     qp_num;
+       enum ib_qp_type         qp_type;
+       u8                      srq;
+};
+
+struct cma_work {
+       struct work_struct      work;
+       struct rdma_id_private  *id;
+       enum cma_state          old_state;
+       enum cma_state          new_state;
+       struct rdma_cm_event    event;
+};
+
+union cma_ip_addr {
+       struct in6_addr ip6;
+       struct {
+               __u32 pad[3];
+               __u32 addr;
+       } ip4;
+};
+
+struct cma_hdr {
+       u8 cma_version;
+       u8 ip_version;  /* IP version: 7:4 */
+       __u16 port;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
+};
+
+struct sdp_hh {
+       u8 bsdh[16];
+       u8 sdp_version; /* Major version: 7:4 */
+       u8 ip_version;  /* IP version: 7:4 */
+       u8 sdp_specific1[10];
+       __u16 port;
+       __u16 sdp_specific2;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
+};
+
+struct sdp_hah {
+       u8 bsdh[16];
+       u8 sdp_version;
+};
+
+#define CMA_VERSION 0x00
+#define SDP_MAJ_VERSION 0x2
+
+static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&id_priv->lock, flags);
+       ret = (id_priv->state == comp);
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return ret;
+}
+
+static int cma_comp_exch(struct rdma_id_private *id_priv,
+                        enum cma_state comp, enum cma_state exch)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&id_priv->lock, flags);
+       if ((ret = (id_priv->state == comp)))
+               id_priv->state = exch;
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return ret;
+}
+
+static enum cma_state cma_exch(struct rdma_id_private *id_priv,
+                              enum cma_state exch)
+{
+       unsigned long flags;
+       enum cma_state old;
+
+       spin_lock_irqsave(&id_priv->lock, flags);
+       old = id_priv->state;
+       id_priv->state = exch;
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return old;
+}
+
+static inline u8 cma_get_ip_ver(struct cma_hdr *hdr)
+{
+       return hdr->ip_version >> 4;
+}
+
+static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver)
+{
+       hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF);
+}
+
+static inline u8 sdp_get_majv(u8 sdp_version)
+{
+       return sdp_version >> 4;
+}
+
+static inline u8 sdp_get_ip_ver(struct sdp_hh *hh)
+{
+       return hh->ip_version >> 4;
+}
+
+static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
+{
+       hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
+}
+
+static void cma_attach_to_dev(struct rdma_id_private *id_priv,
+                             struct cma_device *cma_dev)
+{
+       atomic_inc(&cma_dev->refcount);
+       id_priv->cma_dev = cma_dev;
+       id_priv->id.device = cma_dev->device;
+       list_add_tail(&id_priv->list, &cma_dev->id_list);
+}
+
+static inline void cma_deref_dev(struct cma_device *cma_dev)
+{
+       if (atomic_dec_and_test(&cma_dev->refcount))
+               complete(&cma_dev->comp);
+}
+
+static void cma_detach_from_dev(struct rdma_id_private *id_priv)
+{
+       list_del(&id_priv->list);
+       cma_deref_dev(id_priv->cma_dev);
+       id_priv->cma_dev = NULL;
+}
+
+static int cma_acquire_ib_dev(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+       union ib_gid gid;
+       int ret = -ENODEV;
+
+       ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid),
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list) {
+               ret = ib_find_cached_gid(cma_dev->device, &gid,
+                                        &id_priv->id.port_num, NULL);
+               if (!ret) {
+                       cma_attach_to_dev(id_priv, cma_dev);
+                       break;
+               }
+       }
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static int cma_acquire_dev(struct rdma_id_private *id_priv)
+{
+       switch (id_priv->id.route.addr.dev_addr.dev_type) {
+       case IB_NODE_CA:
+               return cma_acquire_ib_dev(id_priv);
+       default:
+               return -ENODEV;
+       }
+}
+
+static void cma_deref_id(struct rdma_id_private *id_priv)
+{
+       if (atomic_dec_and_test(&id_priv->refcount))
+               complete(&id_priv->comp);
+}
+
+static void cma_release_remove(struct rdma_id_private *id_priv)
+{
+       if (atomic_dec_and_test(&id_priv->dev_remove))
+               wake_up(&id_priv->wait_remove);
+}
+
+struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+                                 void *context, enum rdma_port_space ps)
+{
+       struct rdma_id_private *id_priv;
+
+       id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL);
+       if (!id_priv)
+               return ERR_PTR(-ENOMEM);
+
+       id_priv->state = CMA_IDLE;
+       id_priv->id.context = context;
+       id_priv->id.event_handler = event_handler;
+       id_priv->id.ps = ps;
+       spin_lock_init(&id_priv->lock);
+       init_completion(&id_priv->comp);
+       atomic_set(&id_priv->refcount, 1);
+       init_waitqueue_head(&id_priv->wait_remove);
+       atomic_set(&id_priv->dev_remove, 0);
+       INIT_LIST_HEAD(&id_priv->listen_list);
+       get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
+
+       return &id_priv->id;
+}
+EXPORT_SYMBOL(rdma_create_id);
+
+static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+{
+       struct ib_qp_attr qp_attr;
+       struct rdma_dev_addr *dev_addr;
+       int ret;
+
+       dev_addr = &id_priv->id.route.addr.dev_addr;
+       ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
+                                 ib_addr_get_pkey(dev_addr),
+                                 &qp_attr.pkey_index);
+       if (ret)
+               return ret;
+
+       qp_attr.qp_state = IB_QPS_INIT;
+       qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+       qp_attr.port_num = id_priv->id.port_num;
+       return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
+                                         IB_QP_PKEY_INDEX | IB_QP_PORT);
+}
+
+int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
+                  struct ib_qp_init_attr *qp_init_attr)
+{
+       struct rdma_id_private *id_priv;
+       struct ib_qp *qp;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id->device != pd->device)
+               return -EINVAL;
+
+       qp = ib_create_qp(pd, qp_init_attr);
+       if (IS_ERR(qp))
+               return PTR_ERR(qp);
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = cma_init_ib_qp(id_priv, qp);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       if (ret)
+               goto err;
+
+       id->qp = qp;
+       id_priv->qp_num = qp->qp_num;
+       id_priv->qp_type = qp->qp_type;
+       id_priv->srq = (qp->srq != NULL);
+       return 0;
+err:
+       ib_destroy_qp(qp);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_create_qp);
+
+void rdma_destroy_qp(struct rdma_cm_id *id)
+{
+       ib_destroy_qp(id->qp);
+}
+EXPORT_SYMBOL(rdma_destroy_qp);
+
+static int cma_modify_qp_rtr(struct rdma_cm_id *id)
+{
+       struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
+
+       if (!id->qp)
+               return 0;
+
+       /* Need to update QP attributes from default values. */
+       qp_attr.qp_state = IB_QPS_INIT;
+       ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+       if (ret)
+               return ret;
+
+       qp_attr.qp_state = IB_QPS_RTR;
+       ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+}
+
+static int cma_modify_qp_rts(struct rdma_cm_id *id)
+{
+       struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
+
+       if (!id->qp)
+               return 0;
+
+       qp_attr.qp_state = IB_QPS_RTS;
+       ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+}
+
+static int cma_modify_qp_err(struct rdma_cm_id *id)
+{
+       struct ib_qp_attr qp_attr;
+
+       if (!id->qp)
+               return 0;
+
+       qp_attr.qp_state = IB_QPS_ERR;
+       return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
+}
+
+int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
+                      int *qp_attr_mask)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       switch (id_priv->id.device->node_type) {
+       case IB_NODE_CA:
+               ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
+                                        qp_attr_mask);
+               if (qp_attr->qp_state == IB_QPS_RTR)
+                       qp_attr->rq_psn = id_priv->seq_num;
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(rdma_init_qp_attr);
+
+static inline int cma_zero_addr(struct sockaddr *addr)
+{
+       struct in6_addr *ip6;
+
+       if (addr->sa_family == AF_INET)
+               return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+       else {
+               ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
+               return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
+                       ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0;
+       }
+}
+
+static inline int cma_loopback_addr(struct sockaddr *addr)
+{
+       return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+}
+
+static inline int cma_any_addr(struct sockaddr *addr)
+{
+       return cma_zero_addr(addr) || cma_loopback_addr(addr);
+}
+
+static inline int cma_any_port(struct sockaddr *addr)
+{
+       return !((struct sockaddr_in *) addr)->sin_port;
+}
+
+static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
+                           u8 *ip_ver, __u16 *port,
+                           union cma_ip_addr **src, union cma_ip_addr **dst)
+{
+       switch (ps) {
+       case RDMA_PS_SDP:
+               if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) !=
+                   SDP_MAJ_VERSION)
+                       return -EINVAL;
+
+               *ip_ver = sdp_get_ip_ver(hdr);
+               *port   = ((struct sdp_hh *) hdr)->port;
+               *src    = &((struct sdp_hh *) hdr)->src_addr;
+               *dst    = &((struct sdp_hh *) hdr)->dst_addr;
+               break;
+       default:
+               if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)
+                       return -EINVAL;
+
+               *ip_ver = cma_get_ip_ver(hdr);
+               *port   = ((struct cma_hdr *) hdr)->port;
+               *src    = &((struct cma_hdr *) hdr)->src_addr;
+               *dst    = &((struct cma_hdr *) hdr)->dst_addr;
+               break;
+       }
+
+       if (*ip_ver != 4 && *ip_ver != 6)
+               return -EINVAL;
+       return 0;
+}
+
+static void cma_save_net_info(struct rdma_addr *addr,
+                             struct rdma_addr *listen_addr,
+                             u8 ip_ver, __u16 port,
+                             union cma_ip_addr *src, union cma_ip_addr *dst)
+{
+       struct sockaddr_in *listen4, *ip4;
+       struct sockaddr_in6 *listen6, *ip6;
+
+       switch (ip_ver) {
+       case 4:
+               listen4 = (struct sockaddr_in *) &listen_addr->src_addr;
+               ip4 = (struct sockaddr_in *) &addr->src_addr;
+               ip4->sin_family = listen4->sin_family;
+               ip4->sin_addr.s_addr = dst->ip4.addr;
+               ip4->sin_port = listen4->sin_port;
+
+               ip4 = (struct sockaddr_in *) &addr->dst_addr;
+               ip4->sin_family = listen4->sin_family;
+               ip4->sin_addr.s_addr = src->ip4.addr;
+               ip4->sin_port = port;
+               break;
+       case 6:
+               listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
+               ip6 = (struct sockaddr_in6 *) &addr->src_addr;
+               ip6->sin6_family = listen6->sin6_family;
+               ip6->sin6_addr = dst->ip6;
+               ip6->sin6_port = listen6->sin6_port;
+
+               ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
+               ip6->sin6_family = listen6->sin6_family;
+               ip6->sin6_addr = src->ip6;
+               ip6->sin6_port = port;
+               break;
+       default:
+               break;
+       }
+}
+
+static inline int cma_user_data_offset(enum rdma_port_space ps)
+{
+       switch (ps) {
+       case RDMA_PS_SDP:
+               return 0;
+       default:
+               return sizeof(struct cma_hdr);
+       }
+}
+
+static int cma_notify_user(struct rdma_id_private *id_priv,
+                          enum rdma_cm_event_type type, int status,
+                          void *data, u8 data_len)
+{
+       struct rdma_cm_event event;
+
+       event.event = type;
+       event.status = status;
+       event.private_data = data;
+       event.private_data_len = data_len;
+
+       return id_priv->id.event_handler(&id_priv->id, &event);
+}
+
+static void cma_cancel_route(struct rdma_id_private *id_priv)
+{
+       switch (id_priv->id.device->node_type) {
+       case IB_NODE_CA:
+               if (id_priv->query)
+                       ib_sa_cancel_query(id_priv->query_id, id_priv->query);
+               break;
+       default:
+               break;
+       }
+}
+
+static inline int cma_internal_listen(struct rdma_id_private *id_priv)
+{
+       return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev &&
+              cma_any_addr(&id_priv->id.route.addr.src_addr);
+}
+
+static void cma_destroy_listen(struct rdma_id_private *id_priv)
+{
+       cma_exch(id_priv, CMA_DESTROYING);
+
+       if (id_priv->cma_dev) {
+               switch (id_priv->id.device->node_type) {
+               case IB_NODE_CA:
+                       if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+                               ib_destroy_cm_id(id_priv->cm_id.ib);
+                       break;
+               default:
+                       break;
+               }
+               cma_detach_from_dev(id_priv);
+       }
+       list_del(&id_priv->listen_list);
+
+       cma_deref_id(id_priv);
+       wait_for_completion(&id_priv->comp);
+
+       kfree(id_priv);
+}
+
+static void cma_cancel_listens(struct rdma_id_private *id_priv)
+{
+       struct rdma_id_private *dev_id_priv;
+
+       mutex_lock(&lock);
+       list_del(&id_priv->list);
+
+       while (!list_empty(&id_priv->listen_list)) {
+               dev_id_priv = list_entry(id_priv->listen_list.next,
+                                        struct rdma_id_private, listen_list);
+               cma_destroy_listen(dev_id_priv);
+       }
+       mutex_unlock(&lock);
+}
+
+static void cma_cancel_operation(struct rdma_id_private *id_priv,
+                                enum cma_state state)
+{
+       switch (state) {
+       case CMA_ADDR_QUERY:
+               rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);
+               break;
+       case CMA_ROUTE_QUERY:
+               cma_cancel_route(id_priv);
+               break;
+       case CMA_LISTEN:
+               if (cma_any_addr(&id_priv->id.route.addr.src_addr) &&
+                   !id_priv->cma_dev)
+                       cma_cancel_listens(id_priv);
+               break;
+       default:
+               break;
+       }
+}
+
+static void cma_release_port(struct rdma_id_private *id_priv)
+{
+       struct rdma_bind_list *bind_list = id_priv->bind_list;
+
+       if (!bind_list)
+               return;
+
+       mutex_lock(&lock);
+       hlist_del(&id_priv->node);
+       if (hlist_empty(&bind_list->owners)) {
+               idr_remove(bind_list->ps, bind_list->port);
+               kfree(bind_list);
+       }
+       mutex_unlock(&lock);
+}
+
+void rdma_destroy_id(struct rdma_cm_id *id)
+{
+       struct rdma_id_private *id_priv;
+       enum cma_state state;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       state = cma_exch(id_priv, CMA_DESTROYING);
+       cma_cancel_operation(id_priv, state);
+
+       if (id_priv->cma_dev) {
+               switch (id->device->node_type) {
+               case IB_NODE_CA:
+                       if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+                               ib_destroy_cm_id(id_priv->cm_id.ib);
+                       break;
+               default:
+                       break;
+               }
+               mutex_lock(&lock);
+               cma_detach_from_dev(id_priv);
+               mutex_unlock(&lock);
+       }
+
+       cma_release_port(id_priv);
+       cma_deref_id(id_priv);
+       wait_for_completion(&id_priv->comp);
+
+       kfree(id_priv->id.route.path_rec);
+       kfree(id_priv);
+}
+EXPORT_SYMBOL(rdma_destroy_id);
+
+static int cma_rep_recv(struct rdma_id_private *id_priv)
+{
+       int ret;
+
+       ret = cma_modify_qp_rtr(&id_priv->id);
+       if (ret)
+               goto reject;
+
+       ret = cma_modify_qp_rts(&id_priv->id);
+       if (ret)
+               goto reject;
+
+       ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);
+       if (ret)
+               goto reject;
+
+       return 0;
+reject:
+       cma_modify_qp_err(&id_priv->id);
+       ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
+                      NULL, 0, NULL, 0);
+       return ret;
+}
+
+static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
+{
+       if (id_priv->id.ps == RDMA_PS_SDP &&
+           sdp_get_majv(((struct sdp_hah *) data)->sdp_version) !=
+           SDP_MAJ_VERSION)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int cma_rtu_recv(struct rdma_id_private *id_priv)
+{
+       int ret;
+
+       ret = cma_modify_qp_rts(&id_priv->id);
+       if (ret)
+               goto reject;
+
+       return 0;
+reject:
+       cma_modify_qp_err(&id_priv->id);
+       ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
+                      NULL, 0, NULL, 0);
+       return ret;
+}
+
+static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+{
+       struct rdma_id_private *id_priv = cm_id->context;
+       enum rdma_cm_event_type event;
+       u8 private_data_len = 0;
+       int ret = 0, status = 0;
+
+       atomic_inc(&id_priv->dev_remove);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               goto out;
+
+       switch (ib_event->event) {
+       case IB_CM_REQ_ERROR:
+       case IB_CM_REP_ERROR:
+               event = RDMA_CM_EVENT_UNREACHABLE;
+               status = -ETIMEDOUT;
+               break;
+       case IB_CM_REP_RECEIVED:
+               status = cma_verify_rep(id_priv, ib_event->private_data);
+               if (status)
+                       event = RDMA_CM_EVENT_CONNECT_ERROR;
+               else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
+                       status = cma_rep_recv(id_priv);
+                       event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
+                                        RDMA_CM_EVENT_ESTABLISHED;
+               } else
+                       event = RDMA_CM_EVENT_CONNECT_RESPONSE;
+               private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
+               break;
+       case IB_CM_RTU_RECEIVED:
+               status = cma_rtu_recv(id_priv);
+               event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
+                                RDMA_CM_EVENT_ESTABLISHED;
+               break;
+       case IB_CM_DREQ_ERROR:
+               status = -ETIMEDOUT; /* fall through */
+       case IB_CM_DREQ_RECEIVED:
+       case IB_CM_DREP_RECEIVED:
+               if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
+                       goto out;
+               event = RDMA_CM_EVENT_DISCONNECTED;
+               break;
+       case IB_CM_TIMEWAIT_EXIT:
+       case IB_CM_MRA_RECEIVED:
+               /* ignore event */
+               goto out;
+       case IB_CM_REJ_RECEIVED:
+               cma_modify_qp_err(&id_priv->id);
+               status = ib_event->param.rej_rcvd.reason;
+               event = RDMA_CM_EVENT_REJECTED;
+               private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE;
+               break;
+       default:
+               printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
+                      ib_event->event);
+               goto out;
+       }
+
+       ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
+                             private_data_len);
+       if (ret) {
+               /* Destroy the CM ID by returning a non-zero value. */
+               id_priv->cm_id.ib = NULL;
+               cma_exch(id_priv, CMA_DESTROYING);
+               cma_release_remove(id_priv);
+               rdma_destroy_id(&id_priv->id);
+               return ret;
+       }
+out:
+       cma_release_remove(id_priv);
+       return ret;
+}
+
+static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
+                                         struct ib_cm_event *ib_event)
+{
+       struct rdma_id_private *id_priv;
+       struct rdma_cm_id *id;
+       struct rdma_route *rt;
+       union cma_ip_addr *src, *dst;
+       __u16 port;
+       u8 ip_ver;
+
+       id = rdma_create_id(listen_id->event_handler, listen_id->context,
+                           listen_id->ps);
+       if (IS_ERR(id))
+               return NULL;
+
+       rt = &id->route;
+       rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
+       rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL);
+       if (!rt->path_rec)
+               goto err;
+
+       if (cma_get_net_info(ib_event->private_data, listen_id->ps,
+                            &ip_ver, &port, &src, &dst))
+               goto err;
+
+       cma_save_net_info(&id->route.addr, &listen_id->route.addr,
+                         ip_ver, port, src, dst);
+       rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
+       if (rt->num_paths == 2)
+               rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
+
+       ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+       ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
+       ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
+       rt->addr.dev_addr.dev_type = IB_NODE_CA;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       id_priv->state = CMA_CONNECT;
+       return id_priv;
+err:
+       rdma_destroy_id(id);
+       return NULL;
+}
+
+static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+{
+       struct rdma_id_private *listen_id, *conn_id;
+       int offset, ret;
+
+       listen_id = cm_id->context;
+       atomic_inc(&listen_id->dev_remove);
+       if (!cma_comp(listen_id, CMA_LISTEN)) {
+               ret = -ECONNABORTED;
+               goto out;
+       }
+
+       conn_id = cma_new_id(&listen_id->id, ib_event);
+       if (!conn_id) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       atomic_inc(&conn_id->dev_remove);
+       ret = cma_acquire_ib_dev(conn_id);
+       if (ret) {
+               ret = -ENODEV;
+               cma_release_remove(conn_id);
+               rdma_destroy_id(&conn_id->id);
+               goto out;
+       }
+
+       conn_id->cm_id.ib = cm_id;
+       cm_id->context = conn_id;
+       cm_id->cm_handler = cma_ib_handler;
+
+       offset = cma_user_data_offset(listen_id->id.ps);
+       ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
+                             ib_event->private_data + offset,
+                             IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
+       if (ret) {
+               /* Destroy the CM ID by returning a non-zero value. */
+               conn_id->cm_id.ib = NULL;
+               cma_exch(conn_id, CMA_DESTROYING);
+               cma_release_remove(conn_id);
+               rdma_destroy_id(&conn_id->id);
+       }
+out:
+       cma_release_remove(listen_id);
+       return ret;
+}
+
+static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
+{
+       return cpu_to_be64(((u64)ps << 16) +
+              be16_to_cpu(((struct sockaddr_in *) addr)->sin_port));
+}
+
+static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
+                                struct ib_cm_compare_data *compare)
+{
+       struct cma_hdr *cma_data, *cma_mask;
+       struct sdp_hh *sdp_data, *sdp_mask;
+       __u32 ip4_addr;
+       struct in6_addr ip6_addr;
+
+       memset(compare, 0, sizeof *compare);
+       cma_data = (void *) compare->data;
+       cma_mask = (void *) compare->mask;
+       sdp_data = (void *) compare->data;
+       sdp_mask = (void *) compare->mask;
+
+       switch (addr->sa_family) {
+       case AF_INET:
+               ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+               if (ps == RDMA_PS_SDP) {
+                       sdp_set_ip_ver(sdp_data, 4);
+                       sdp_set_ip_ver(sdp_mask, 0xF);
+                       sdp_data->dst_addr.ip4.addr = ip4_addr;
+                       sdp_mask->dst_addr.ip4.addr = ~0;
+               } else {
+                       cma_set_ip_ver(cma_data, 4);
+                       cma_set_ip_ver(cma_mask, 0xF);
+                       cma_data->dst_addr.ip4.addr = ip4_addr;
+                       cma_mask->dst_addr.ip4.addr = ~0;
+               }
+               break;
+       case AF_INET6:
+               ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
+               if (ps == RDMA_PS_SDP) {
+                       sdp_set_ip_ver(sdp_data, 6);
+                       sdp_set_ip_ver(sdp_mask, 0xF);
+                       sdp_data->dst_addr.ip6 = ip6_addr;
+                       memset(&sdp_mask->dst_addr.ip6, 0xFF,
+                              sizeof sdp_mask->dst_addr.ip6);
+               } else {
+                       cma_set_ip_ver(cma_data, 6);
+                       cma_set_ip_ver(cma_mask, 0xF);
+                       cma_data->dst_addr.ip6 = ip6_addr;
+                       memset(&cma_mask->dst_addr.ip6, 0xFF,
+                              sizeof cma_mask->dst_addr.ip6);
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static int cma_ib_listen(struct rdma_id_private *id_priv)
+{
+       struct ib_cm_compare_data compare_data;
+       struct sockaddr *addr;
+       __be64 svc_id;
+       int ret;
+
+       id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
+                                           id_priv);
+       if (IS_ERR(id_priv->cm_id.ib))
+               return PTR_ERR(id_priv->cm_id.ib);
+
+       addr = &id_priv->id.route.addr.src_addr;
+       svc_id = cma_get_service_id(id_priv->id.ps, addr);
+       if (cma_any_addr(addr))
+               ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
+       else {
+               cma_set_compare_data(id_priv->id.ps, addr, &compare_data);
+               ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data);
+       }
+
+       if (ret) {
+               ib_destroy_cm_id(id_priv->cm_id.ib);
+               id_priv->cm_id.ib = NULL;
+       }
+
+       return ret;
+}
+
+static int cma_listen_handler(struct rdma_cm_id *id,
+                             struct rdma_cm_event *event)
+{
+       struct rdma_id_private *id_priv = id->context;
+
+       id->context = id_priv->id.context;
+       id->event_handler = id_priv->id.event_handler;
+       return id_priv->id.event_handler(id, event);
+}
+
+static void cma_listen_on_dev(struct rdma_id_private *id_priv,
+                             struct cma_device *cma_dev)
+{
+       struct rdma_id_private *dev_id_priv;
+       struct rdma_cm_id *id;
+       int ret;
+
+       id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps);
+       if (IS_ERR(id))
+               return;
+
+       dev_id_priv = container_of(id, struct rdma_id_private, id);
+
+       dev_id_priv->state = CMA_ADDR_BOUND;
+       memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr,
+              ip_addr_size(&id_priv->id.route.addr.src_addr));
+
+       cma_attach_to_dev(dev_id_priv, cma_dev);
+       list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
+
+       ret = rdma_listen(id, id_priv->backlog);
+       if (ret)
+               goto err;
+
+       return;
+err:
+       cma_destroy_listen(dev_id_priv);
+}
+
+static void cma_listen_on_all(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+
+       mutex_lock(&lock);
+       list_add_tail(&id_priv->list, &listen_any_list);
+       list_for_each_entry(cma_dev, &dev_list, list)
+               cma_listen_on_dev(id_priv, cma_dev);
+       mutex_unlock(&lock);
+}
+
+static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
+{
+       struct sockaddr_in addr_in;
+
+       memset(&addr_in, 0, sizeof addr_in);
+       addr_in.sin_family = af;
+       return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
+}
+
+int rdma_listen(struct rdma_cm_id *id, int backlog)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id_priv->state == CMA_IDLE) {
+               ret = cma_bind_any(id, AF_INET);
+               if (ret)
+                       return ret;
+       }
+
+       if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
+               return -EINVAL;
+
+       id_priv->backlog = backlog;
+       if (id->device) {
+               switch (id->device->node_type) {
+               case IB_NODE_CA:
+                       ret = cma_ib_listen(id_priv);
+                       if (ret)
+                               goto err;
+                       break;
+               default:
+                       ret = -ENOSYS;
+                       goto err;
+               }
+       } else
+               cma_listen_on_all(id_priv);
+
+       return 0;
+err:
+       id_priv->backlog = 0;
+       cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_listen);
+
+static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec,
+                             void *context)
+{
+       struct cma_work *work = context;
+       struct rdma_route *route;
+
+       route = &work->id->id.route;
+
+       if (!status) {
+               route->num_paths = 1;
+               *route->path_rec = *path_rec;
+       } else {
+               work->old_state = CMA_ROUTE_QUERY;
+               work->new_state = CMA_ADDR_RESOLVED;
+               work->event.event = RDMA_CM_EVENT_ROUTE_ERROR;
+       }
+
+       queue_work(cma_wq, &work->work);
+}
+
+static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
+                             struct cma_work *work)
+{
+       struct rdma_dev_addr *addr = &id_priv->id.route.addr.dev_addr;
+       struct ib_sa_path_rec path_rec;
+
+       memset(&path_rec, 0, sizeof path_rec);
+       ib_addr_get_sgid(addr, &path_rec.sgid);
+       ib_addr_get_dgid(addr, &path_rec.dgid);
+       path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr));
+       path_rec.numb_path = 1;
+
+       id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device,
+                               id_priv->id.port_num, &path_rec,
+                               IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
+                               IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH,
+                               timeout_ms, GFP_KERNEL,
+                               cma_query_handler, work, &id_priv->query);
+
+       return (id_priv->query_id < 0) ? id_priv->query_id : 0;
+}
+
+static void cma_work_handler(void *data)
+{
+       struct cma_work *work = data;
+       struct rdma_id_private *id_priv = work->id;
+       int destroy = 0;
+
+       atomic_inc(&id_priv->dev_remove);
+       if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
+               goto out;
+
+       if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               destroy = 1;
+       }
+out:
+       cma_release_remove(id_priv);
+       cma_deref_id(id_priv);
+       if (destroy)
+               rdma_destroy_id(&id_priv->id);
+       kfree(work);
+}
+
+static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
+{
+       struct rdma_route *route = &id_priv->id.route;
+       struct cma_work *work;
+       int ret;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       work->id = id_priv;
+       INIT_WORK(&work->work, cma_work_handler, work);
+       work->old_state = CMA_ROUTE_QUERY;
+       work->new_state = CMA_ROUTE_RESOLVED;
+       work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+
+       route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
+       if (!route->path_rec) {
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       ret = cma_query_ib_route(id_priv, timeout_ms, work);
+       if (ret)
+               goto err2;
+
+       return 0;
+err2:
+       kfree(route->path_rec);
+       route->path_rec = NULL;
+err1:
+       kfree(work);
+       return ret;
+}
+
+int rdma_set_ib_paths(struct rdma_cm_id *id,
+                     struct ib_sa_path_rec *path_rec, int num_paths)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED))
+               return -EINVAL;
+
+       id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
+       if (!id->route.path_rec) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths);
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_set_ib_paths);
+
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY))
+               return -EINVAL;
+
+       atomic_inc(&id_priv->refcount);
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = cma_resolve_ib_route(id_priv, timeout_ms);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED);
+       cma_deref_id(id_priv);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_route);
+
+static int cma_bind_loopback(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+       struct ib_port_attr port_attr;
+       union ib_gid gid;
+       u16 pkey;
+       int ret;
+       u8 p;
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list)
+               for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p)
+                       if (!ib_query_port (cma_dev->device, p, &port_attr) &&
+                           port_attr.state == IB_PORT_ACTIVE)
+                               goto port_found;
+
+       if (!list_empty(&dev_list)) {
+               p = 1;
+               cma_dev = list_entry(dev_list.next, struct cma_device, list);
+       } else {
+               ret = -ENODEV;
+               goto out;
+       }
+
+port_found:
+       ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid);
+       if (ret)
+               goto out;
+
+       ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey);
+       if (ret)
+               goto out;
+
+       ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+       ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
+       id_priv->id.port_num = p;
+       cma_attach_to_dev(id_priv, cma_dev);
+out:
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static void addr_handler(int status, struct sockaddr *src_addr,
+                        struct rdma_dev_addr *dev_addr, void *context)
+{
+       struct rdma_id_private *id_priv = context;
+       enum rdma_cm_event_type event;
+
+       atomic_inc(&id_priv->dev_remove);
+       if (!id_priv->cma_dev && !status)
+               status = cma_acquire_dev(id_priv);
+
+       if (status) {
+               if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND))
+                       goto out;
+               event = RDMA_CM_EVENT_ADDR_ERROR;
+       } else {
+               if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
+                       goto out;
+               memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+                      ip_addr_size(src_addr));
+               event = RDMA_CM_EVENT_ADDR_RESOLVED;
+       }
+
+       if (cma_notify_user(id_priv, event, status, NULL, 0)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               cma_release_remove(id_priv);
+               cma_deref_id(id_priv);
+               rdma_destroy_id(&id_priv->id);
+               return;
+       }
+out:
+       cma_release_remove(id_priv);
+       cma_deref_id(id_priv);
+}
+
+static int cma_resolve_loopback(struct rdma_id_private *id_priv)
+{
+       struct cma_work *work;
+       struct sockaddr_in *src_in, *dst_in;
+       union ib_gid gid;
+       int ret;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       if (!id_priv->cma_dev) {
+               ret = cma_bind_loopback(id_priv);
+               if (ret)
+                       goto err;
+       }
+
+       ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+       ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
+
+       if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) {
+               src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
+               dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
+               src_in->sin_family = dst_in->sin_family;
+               src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
+       }
+
+       work->id = id_priv;
+       INIT_WORK(&work->work, cma_work_handler, work);
+       work->old_state = CMA_ADDR_QUERY;
+       work->new_state = CMA_ADDR_RESOLVED;
+       work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
+       queue_work(cma_wq, &work->work);
+       return 0;
+err:
+       kfree(work);
+       return ret;
+}
+
+static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+                        struct sockaddr *dst_addr)
+{
+       if (src_addr && src_addr->sa_family)
+               return rdma_bind_addr(id, src_addr);
+       else
+               return cma_bind_any(id, dst_addr->sa_family);
+}
+
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+                     struct sockaddr *dst_addr, int timeout_ms)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id_priv->state == CMA_IDLE) {
+               ret = cma_bind_addr(id, src_addr, dst_addr);
+               if (ret)
+                       return ret;
+       }
+
+       if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY))
+               return -EINVAL;
+
+       atomic_inc(&id_priv->refcount);
+       memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
+       if (cma_any_addr(dst_addr))
+               ret = cma_resolve_loopback(id_priv);
+       else
+               ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr,
+                                     &id->route.addr.dev_addr,
+                                     timeout_ms, addr_handler, id_priv);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND);
+       cma_deref_id(id_priv);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_addr);
+
+static void cma_bind_port(struct rdma_bind_list *bind_list,
+                         struct rdma_id_private *id_priv)
+{
+       struct sockaddr_in *sin;
+
+       sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
+       sin->sin_port = htons(bind_list->port);
+       id_priv->bind_list = bind_list;
+       hlist_add_head(&id_priv->node, &bind_list->owners);
+}
+
+static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
+                         unsigned short snum)
+{
+       struct rdma_bind_list *bind_list;
+       int port, start, ret;
+
+       bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+       if (!bind_list)
+               return -ENOMEM;
+
+       start = snum ? snum : sysctl_local_port_range[0];
+
+       do {
+               ret = idr_get_new_above(ps, bind_list, start, &port);
+       } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
+
+       if (ret)
+               goto err;
+
+       if ((snum && port != snum) ||
+           (!snum && port > sysctl_local_port_range[1])) {
+               idr_remove(ps, port);
+               ret = -EADDRNOTAVAIL;
+               goto err;
+       }
+
+       bind_list->ps = ps;
+       bind_list->port = (unsigned short) port;
+       cma_bind_port(bind_list, id_priv);
+       return 0;
+err:
+       kfree(bind_list);
+       return ret;
+}
+
+static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
+{
+       struct rdma_id_private *cur_id;
+       struct sockaddr_in *sin, *cur_sin;
+       struct rdma_bind_list *bind_list;
+       struct hlist_node *node;
+       unsigned short snum;
+
+       sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
+       snum = ntohs(sin->sin_port);
+       if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+               return -EACCES;
+
+       bind_list = idr_find(ps, snum);
+       if (!bind_list)
+               return cma_alloc_port(ps, id_priv, snum);
+
+       /*
+        * We don't support binding to any address if anyone is bound to
+        * a specific address on the same port.
+        */
+       if (cma_any_addr(&id_priv->id.route.addr.src_addr))
+               return -EADDRNOTAVAIL;
+
+       hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
+               if (cma_any_addr(&cur_id->id.route.addr.src_addr))
+                       return -EADDRNOTAVAIL;
+               
+               cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr;
+               if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
+                       return -EADDRINUSE;
+       }
+
+       cma_bind_port(bind_list, id_priv);
+       return 0;
+}
+
+static int cma_get_port(struct rdma_id_private *id_priv)
+{
+       struct idr *ps;
+       int ret;
+
+       switch (id_priv->id.ps) {
+       case RDMA_PS_SDP:
+               ps = &sdp_ps;
+               break;
+       case RDMA_PS_TCP:
+               ps = &tcp_ps;
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       mutex_lock(&lock);
+       if (cma_any_port(&id_priv->id.route.addr.src_addr))
+               ret = cma_alloc_port(ps, id_priv, 0);
+       else
+               ret = cma_use_port(ps, id_priv);
+       mutex_unlock(&lock);
+
+       return ret;
+}
+
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       if (addr->sa_family != AF_INET)
+               return -EAFNOSUPPORT;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
+               return -EINVAL;
+
+       if (!cma_any_addr(addr)) {
+               ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
+               if (!ret)
+                       ret = cma_acquire_dev(id_priv);
+               if (ret)
+                       goto err;
+       }
+
+       memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
+       ret = cma_get_port(id_priv);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_bind_addr);
+
+static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
+                         struct rdma_route *route)
+{
+       struct sockaddr_in *src4, *dst4;
+       struct cma_hdr *cma_hdr;
+       struct sdp_hh *sdp_hdr;
+
+       src4 = (struct sockaddr_in *) &route->addr.src_addr;
+       dst4 = (struct sockaddr_in *) &route->addr.dst_addr;
+
+       switch (ps) {
+       case RDMA_PS_SDP:
+               sdp_hdr = hdr;
+               if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
+                       return -EINVAL;
+               sdp_set_ip_ver(sdp_hdr, 4);
+               sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+               sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+               sdp_hdr->port = src4->sin_port;
+               break;
+       default:
+               cma_hdr = hdr;
+               cma_hdr->cma_version = CMA_VERSION;
+               cma_set_ip_ver(cma_hdr, 4);
+               cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+               cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+               cma_hdr->port = src4->sin_port;
+               break;
+       }
+       return 0;
+}
+
+static int cma_connect_ib(struct rdma_id_private *id_priv,
+                         struct rdma_conn_param *conn_param)
+{
+       struct ib_cm_req_param req;
+       struct rdma_route *route;
+       void *private_data;
+       int offset, ret;
+
+       memset(&req, 0, sizeof req);
+       offset = cma_user_data_offset(id_priv->id.ps);
+       req.private_data_len = offset + conn_param->private_data_len;
+       private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
+       if (!private_data)
+               return -ENOMEM;
+
+       if (conn_param->private_data && conn_param->private_data_len)
+               memcpy(private_data + offset, conn_param->private_data,
+                      conn_param->private_data_len);
+
+       id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
+                                           id_priv);
+       if (IS_ERR(id_priv->cm_id.ib)) {
+               ret = PTR_ERR(id_priv->cm_id.ib);
+               goto out;
+       }
+
+       route = &id_priv->id.route;
+       ret = cma_format_hdr(private_data, id_priv->id.ps, route);
+       if (ret)
+               goto out;
+       req.private_data = private_data;
+
+       req.primary_path = &route->path_rec[0];
+       if (route->num_paths == 2)
+               req.alternate_path = &route->path_rec[1];
+
+       req.service_id = cma_get_service_id(id_priv->id.ps,
+                                           &route->addr.dst_addr);
+       req.qp_num = id_priv->qp_num;
+       req.qp_type = id_priv->qp_type;
+       req.starting_psn = id_priv->seq_num;
+       req.responder_resources = conn_param->responder_resources;
+       req.initiator_depth = conn_param->initiator_depth;
+       req.flow_control = conn_param->flow_control;
+       req.retry_count = conn_param->retry_count;
+       req.rnr_retry_count = conn_param->rnr_retry_count;
+       req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
+       req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
+       req.max_cm_retries = CMA_MAX_CM_RETRIES;
+       req.srq = id_priv->srq ? 1 : 0;
+
+       ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
+out:
+       kfree(private_data);
+       return ret;
+}
+
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
+               return -EINVAL;
+
+       if (!id->qp) {
+               id_priv->qp_num = conn_param->qp_num;
+               id_priv->qp_type = conn_param->qp_type;
+               id_priv->srq = conn_param->srq;
+       }
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = cma_connect_ib(id_priv, conn_param);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_connect);
+
+static int cma_accept_ib(struct rdma_id_private *id_priv,
+                        struct rdma_conn_param *conn_param)
+{
+       struct ib_cm_rep_param rep;
+       int ret;
+
+       ret = cma_modify_qp_rtr(&id_priv->id);
+       if (ret)
+               return ret;
+
+       memset(&rep, 0, sizeof rep);
+       rep.qp_num = id_priv->qp_num;
+       rep.starting_psn = id_priv->seq_num;
+       rep.private_data = conn_param->private_data;
+       rep.private_data_len = conn_param->private_data_len;
+       rep.responder_resources = conn_param->responder_resources;
+       rep.initiator_depth = conn_param->initiator_depth;
+       rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
+       rep.failover_accepted = 0;
+       rep.flow_control = conn_param->flow_control;
+       rep.rnr_retry_count = conn_param->rnr_retry_count;
+       rep.srq = id_priv->srq ? 1 : 0;
+
+       return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+}
+
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               return -EINVAL;
+
+       if (!id->qp && conn_param) {
+               id_priv->qp_num = conn_param->qp_num;
+               id_priv->qp_type = conn_param->qp_type;
+               id_priv->srq = conn_param->srq;
+       }
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               if (conn_param)
+                       ret = cma_accept_ib(id_priv, conn_param);
+               else
+                       ret = cma_rep_recv(id_priv);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       if (ret)
+               goto reject;
+
+       return 0;
+reject:
+       cma_modify_qp_err(id);
+       rdma_reject(id, NULL, 0);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_accept);
+
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+               u8 private_data_len)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               return -EINVAL;
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = ib_send_cm_rej(id_priv->cm_id.ib,
+                                    IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
+                                    private_data, private_data_len);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(rdma_reject);
+
+int rdma_disconnect(struct rdma_cm_id *id)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT) &&
+           !cma_comp(id_priv, CMA_DISCONNECT))
+               return -EINVAL;
+
+       ret = cma_modify_qp_err(id);
+       if (ret)
+               goto out;
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               /* Initiate or respond to a disconnect. */
+               if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
+                       ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
+               break;
+       default:
+               break;
+       }
+out:
+       return ret;
+}
+EXPORT_SYMBOL(rdma_disconnect);
+
+static void cma_add_one(struct ib_device *device)
+{
+       struct cma_device *cma_dev;
+       struct rdma_id_private *id_priv;
+
+       cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL);
+       if (!cma_dev)
+               return;
+
+       cma_dev->device = device;
+       cma_dev->node_guid = device->node_guid;
+       if (!cma_dev->node_guid)
+               goto err;
+
+       init_completion(&cma_dev->comp);
+       atomic_set(&cma_dev->refcount, 1);
+       INIT_LIST_HEAD(&cma_dev->id_list);
+       ib_set_client_data(device, &cma_client, cma_dev);
+
+       mutex_lock(&lock);
+       list_add_tail(&cma_dev->list, &dev_list);
+       list_for_each_entry(id_priv, &listen_any_list, list)
+               cma_listen_on_dev(id_priv, cma_dev);
+       mutex_unlock(&lock);
+       return;
+err:
+       kfree(cma_dev);
+}
+
+static int cma_remove_id_dev(struct rdma_id_private *id_priv)
+{
+       enum cma_state state;
+
+       /* Record that we want to remove the device */
+       state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
+       if (state == CMA_DESTROYING)
+               return 0;
+
+       cma_cancel_operation(id_priv, state);
+       wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove));
+
+       /* Check for destruction from another callback. */
+       if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
+               return 0;
+
+       return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
+                              0, NULL, 0);
+}
+
+static void cma_process_remove(struct cma_device *cma_dev)
+{
+       struct list_head remove_list;
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       INIT_LIST_HEAD(&remove_list);
+
+       mutex_lock(&lock);
+       while (!list_empty(&cma_dev->id_list)) {
+               id_priv = list_entry(cma_dev->id_list.next,
+                                    struct rdma_id_private, list);
+
+               if (cma_internal_listen(id_priv)) {
+                       cma_destroy_listen(id_priv);
+                       continue;
+               }
+
+               list_del(&id_priv->list);
+               list_add_tail(&id_priv->list, &remove_list);
+               atomic_inc(&id_priv->refcount);
+               mutex_unlock(&lock);
+
+               ret = cma_remove_id_dev(id_priv);
+               cma_deref_id(id_priv);
+               if (ret)
+                       rdma_destroy_id(&id_priv->id);
+
+               mutex_lock(&lock);
+       }
+       mutex_unlock(&lock);
+
+       cma_deref_dev(cma_dev);
+       wait_for_completion(&cma_dev->comp);
+}
+
+static void cma_remove_one(struct ib_device *device)
+{
+       struct cma_device *cma_dev;
+
+       cma_dev = ib_get_client_data(device, &cma_client);
+       if (!cma_dev)
+               return;
+
+       mutex_lock(&lock);
+       list_del(&cma_dev->list);
+       mutex_unlock(&lock);
+
+       cma_process_remove(cma_dev);
+       kfree(cma_dev);
+}
+
+static int cma_init(void)
+{
+       int ret;
+
+       cma_wq = create_singlethread_workqueue("rdma_cm_wq");
+       if (!cma_wq)
+               return -ENOMEM;
+
+       ret = ib_register_client(&cma_client);
+       if (ret)
+               goto err;
+       return 0;
+
+err:
+       destroy_workqueue(cma_wq);
+       return ret;
+}
+
+static void cma_cleanup(void)
+{
+       ib_unregister_client(&cma_client);
+       destroy_workqueue(cma_wq);
+       idr_destroy(&sdp_ps);
+       idr_destroy(&tcp_ps);
+}
+
+module_init(cma_init);
+module_exit(cma_cleanup);
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
new file mode 100644 (file)
index 0000000..ce46b13
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_marshall.h>
+
+static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
+                                   struct ib_ah_attr *src)
+{
+       memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid);
+       dst->grh.flow_label        = src->grh.flow_label;
+       dst->grh.sgid_index        = src->grh.sgid_index;
+       dst->grh.hop_limit         = src->grh.hop_limit;
+       dst->grh.traffic_class     = src->grh.traffic_class;
+       dst->dlid                  = src->dlid;
+       dst->sl                    = src->sl;
+       dst->src_path_bits         = src->src_path_bits;
+       dst->static_rate           = src->static_rate;
+       dst->is_global             = src->ah_flags & IB_AH_GRH ? 1 : 0;
+       dst->port_num              = src->port_num;
+}
+
+void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+                            struct ib_qp_attr *src)
+{
+       dst->cur_qp_state       = src->cur_qp_state;
+       dst->path_mtu           = src->path_mtu;
+       dst->path_mig_state     = src->path_mig_state;
+       dst->qkey               = src->qkey;
+       dst->rq_psn             = src->rq_psn;
+       dst->sq_psn             = src->sq_psn;
+       dst->dest_qp_num        = src->dest_qp_num;
+       dst->qp_access_flags    = src->qp_access_flags;
+
+       dst->max_send_wr        = src->cap.max_send_wr;
+       dst->max_recv_wr        = src->cap.max_recv_wr;
+       dst->max_send_sge       = src->cap.max_send_sge;
+       dst->max_recv_sge       = src->cap.max_recv_sge;
+       dst->max_inline_data    = src->cap.max_inline_data;
+
+       ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
+       ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr);
+
+       dst->pkey_index         = src->pkey_index;
+       dst->alt_pkey_index     = src->alt_pkey_index;
+       dst->en_sqd_async_notify = src->en_sqd_async_notify;
+       dst->sq_draining        = src->sq_draining;
+       dst->max_rd_atomic      = src->max_rd_atomic;
+       dst->max_dest_rd_atomic = src->max_dest_rd_atomic;
+       dst->min_rnr_timer      = src->min_rnr_timer;
+       dst->port_num           = src->port_num;
+       dst->timeout            = src->timeout;
+       dst->retry_cnt          = src->retry_cnt;
+       dst->rnr_retry          = src->rnr_retry;
+       dst->alt_port_num       = src->alt_port_num;
+       dst->alt_timeout        = src->alt_timeout;
+}
+EXPORT_SYMBOL(ib_copy_qp_attr_to_user);
+
+void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+                             struct ib_sa_path_rec *src)
+{
+       memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid);
+       memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid);
+
+       dst->dlid               = src->dlid;
+       dst->slid               = src->slid;
+       dst->raw_traffic        = src->raw_traffic;
+       dst->flow_label         = src->flow_label;
+       dst->hop_limit          = src->hop_limit;
+       dst->traffic_class      = src->traffic_class;
+       dst->reversible         = src->reversible;
+       dst->numb_path          = src->numb_path;
+       dst->pkey               = src->pkey;
+       dst->sl                 = src->sl;
+       dst->mtu_selector       = src->mtu_selector;
+       dst->mtu                = src->mtu;
+       dst->rate_selector      = src->rate_selector;
+       dst->rate               = src->rate;
+       dst->packet_life_time   = src->packet_life_time;
+       dst->preference         = src->preference;
+       dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+EXPORT_SYMBOL(ib_copy_path_rec_to_user);
+
+void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
+                               struct ib_user_path_rec *src)
+{
+       memcpy(dst->dgid.raw, src->dgid, sizeof dst->dgid);
+       memcpy(dst->sgid.raw, src->sgid, sizeof dst->sgid);
+
+       dst->dlid               = src->dlid;
+       dst->slid               = src->slid;
+       dst->raw_traffic        = src->raw_traffic;
+       dst->flow_label         = src->flow_label;
+       dst->hop_limit          = src->hop_limit;
+       dst->traffic_class      = src->traffic_class;
+       dst->reversible         = src->reversible;
+       dst->numb_path          = src->numb_path;
+       dst->pkey               = src->pkey;
+       dst->sl                 = src->sl;
+       dst->mtu_selector       = src->mtu_selector;
+       dst->mtu                = src->mtu;
+       dst->rate_selector      = src->rate_selector;
+       dst->rate               = src->rate;
+       dst->packet_life_time   = src->packet_life_time;
+       dst->preference         = src->preference;
+       dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+EXPORT_SYMBOL(ib_copy_path_rec_from_user);
diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig
new file mode 100644 (file)
index 0000000..fead87d
--- /dev/null
@@ -0,0 +1,11 @@
+config INFINIBAND_ISER
+       tristate "ISCSI RDMA Protocol"
+       depends on INFINIBAND && SCSI
+       select SCSI_ISCSI_ATTRS
+       ---help---
+         Support for the ISCSI RDMA Protocol over InfiniBand.  This
+         allows you to access storage devices that speak ISER/ISCSI
+         over InfiniBand.
+
+         The ISER protocol is defined by IETF.
+         See <http://www.ietf.org/>.
diff --git a/drivers/infiniband/ulp/iser/Makefile b/drivers/infiniband/ulp/iser/Makefile
new file mode 100644 (file)
index 0000000..fe6cd15
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_INFINIBAND_ISER)  += ib_iser.o
+
+ib_iser-y                      := iser_verbs.o iser_initiator.o iser_memory.o \
+                                  iscsi_iser.o
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
new file mode 100644 (file)
index 0000000..1437d7e
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ * iSCSI Initiator over iSER Data-Path
+ *
+ * Copyright (C) 2004 Dmitry Yusupov
+ * Copyright (C) 2004 Alex Aizman
+ * Copyright (C) 2005 Mike Christie
+ * Copyright (c) 2005, 2006 Voltaire, Inc. All rights reserved.
+ * maintained by openib-general@openib.org
+ *
+ * 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     - Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer.
+ *
+ *     - Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Credits:
+ *     Christoph Hellwig
+ *     FUJITA Tomonori
+ *     Arne Redlich
+ *     Zhenyu Wang
+ * Modified by:
+ *      Erez Zilber
+ *
+ *
+ * $Id: iscsi_iser.c 6965 2006-05-07 11:36:20Z ogerlitz $
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/hardirq.h>
+#include <linux/kfifo.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+
+#include <net/sock.h>
+
+#include <asm/uaccess.h>
+
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include "iscsi_iser.h"
+
+static unsigned int iscsi_max_lun = 512;
+module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+
+int iser_debug_level = 0;
+
+MODULE_DESCRIPTION("iSER (iSCSI Extensions for RDMA) Datamover "
+                  "v" DRV_VER " (" DRV_DATE ")");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Alex Nezhinsky, Dan Bar Dov, Or Gerlitz");
+
+module_param_named(debug_level, iser_debug_level, int, 0644);
+MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:disabled)");
+
+struct iser_global ig;
+
+void
+iscsi_iser_recv(struct iscsi_conn *conn,
+               struct iscsi_hdr *hdr, char *rx_data, int rx_data_len)
+{
+       int rc = 0;
+       uint32_t ret_itt;
+       int datalen;
+       int ahslen;
+
+       /* verify PDU length */
+       datalen = ntoh24(hdr->dlength);
+       if (datalen != rx_data_len) {
+               printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n",
+                      datalen, rx_data_len);
+               rc = ISCSI_ERR_DATALEN;
+               goto error;
+       }
+
+       /* read AHS */
+       ahslen = hdr->hlength * 4;
+
+       /* verify itt (itt encoding: age+cid+itt) */
+       rc = iscsi_verify_itt(conn, hdr, &ret_itt);
+
+       if (!rc)
+               rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len);
+
+       if (rc && rc != ISCSI_ERR_NO_SCSI_CMD)
+               goto error;
+
+       return;
+error:
+       iscsi_conn_failure(conn, rc);
+}
+
+
+/**
+ * iscsi_iser_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+ *
+ **/
+static void
+iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+{
+       struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       struct scsi_cmnd  *sc = ctask->sc;
+
+       iser_ctask->command_sent = 0;
+       iser_ctask->iser_conn    = iser_conn;
+
+       if (sc->sc_data_direction == DMA_TO_DEVICE) {
+               BUG_ON(ctask->total_length == 0);
+               /* bytes to be sent via RDMA operations */
+               iser_ctask->rdma_data_count = ctask->total_length -
+                                        ctask->imm_count -
+                                        ctask->unsol_count;
+
+               debug_scsi("cmd [itt %x total %d imm %d unsol_data %d "
+                          "rdma_data %d]\n",
+                          ctask->itt, ctask->total_length, ctask->imm_count,
+                          ctask->unsol_count, iser_ctask->rdma_data_count);
+       } else
+               /* bytes to be sent via RDMA operations */
+               iser_ctask->rdma_data_count = ctask->total_length;
+
+       iser_ctask_rdma_init(iser_ctask);
+}
+
+/**
+ * iscsi_mtask_xmit - xmit management(immediate) task
+ * @conn: iscsi connection
+ * @mtask: task management task
+ *
+ * Notes:
+ *     The function can return -EAGAIN in which case caller must
+ *     call it again later, or recover. '0' return code means successful
+ *     xmit.
+ *
+ **/
+static int
+iscsi_iser_mtask_xmit(struct iscsi_conn *conn,
+                     struct iscsi_mgmt_task *mtask)
+{
+       int error = 0;
+
+       debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt);
+
+       error = iser_send_control(conn, mtask);
+
+       /* since iser xmits control with zero copy, mtasks can not be recycled
+        * right after sending them.
+        * The recycling scheme is based on whether a response is expected
+        * - if yes, the mtask is recycled at iscsi_complete_pdu
+        * - if no,  the mtask is recycled at iser_snd_completion
+        */
+       if (error && error != -EAGAIN)
+               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+
+       return error;
+}
+
+static int
+iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,
+                                struct iscsi_cmd_task *ctask)
+{
+       struct iscsi_data  hdr;
+       int error = 0;
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+
+       /* Send data-out PDUs while there's still unsolicited data to send */
+       while (ctask->unsol_count > 0) {
+               iscsi_prep_unsolicit_data_pdu(ctask, &hdr,
+                                             iser_ctask->rdma_data_count);
+
+               debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
+                          hdr.itt, ctask->data_count);
+
+               /* the buffer description has been passed with the command */
+               /* Send the command */
+               error = iser_send_data_out(conn, ctask, &hdr);
+               if (error) {
+                       ctask->unsol_datasn--;
+                       goto iscsi_iser_ctask_xmit_unsol_data_exit;
+               }
+               ctask->unsol_count -= ctask->data_count;
+               debug_scsi("Need to send %d more as data-out PDUs\n",
+                          ctask->unsol_count);
+       }
+
+iscsi_iser_ctask_xmit_unsol_data_exit:
+       return error;
+}
+
+static int
+iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
+                     struct iscsi_cmd_task *ctask)
+{
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       int error = 0;
+
+       debug_scsi("ctask deq [cid %d itt 0x%x]\n",
+                  conn->id, ctask->itt);
+
+       /*
+        * serialize with TMF AbortTask
+        */
+       if (ctask->mtask)
+               return error;
+
+       /* Send the cmd PDU */
+       if (!iser_ctask->command_sent) {
+               error = iser_send_command(conn, ctask);
+               if (error)
+                       goto iscsi_iser_ctask_xmit_exit;
+               iser_ctask->command_sent = 1;
+       }
+
+       /* Send unsolicited data-out PDU(s) if necessary */
+       if (ctask->unsol_count)
+               error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask);
+
+ iscsi_iser_ctask_xmit_exit:
+       if (error && error != -EAGAIN)
+               iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+       return error;
+}
+
+static void
+iscsi_iser_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+{
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+
+       if (iser_ctask->status == ISER_TASK_STATUS_STARTED) {
+               iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+               iser_ctask_rdma_finalize(iser_ctask);
+       }
+}
+
+static struct iser_conn *
+iscsi_iser_ib_conn_lookup(__u64 ep_handle)
+{
+       struct iser_conn *ib_conn;
+       struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle;
+
+       mutex_lock(&ig.connlist_mutex);
+       list_for_each_entry(ib_conn, &ig.connlist, conn_list) {
+               if (ib_conn == uib_conn) {
+                       mutex_unlock(&ig.connlist_mutex);
+                       return ib_conn;
+               }
+       }
+       mutex_unlock(&ig.connlist_mutex);
+       iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle);
+       return NULL;
+}
+
+static struct iscsi_cls_conn *
+iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+{
+       struct iscsi_conn *conn;
+       struct iscsi_cls_conn *cls_conn;
+       struct iscsi_iser_conn *iser_conn;
+
+       cls_conn = iscsi_conn_setup(cls_session, conn_idx);
+       if (!cls_conn)
+               return NULL;
+       conn = cls_conn->dd_data;
+
+       /*
+        * due to issues with the login code re iser sematics
+        * this not set in iscsi_conn_setup - FIXME
+        */
+       conn->max_recv_dlength = 128;
+
+       iser_conn = kzalloc(sizeof(*iser_conn), GFP_KERNEL);
+       if (!iser_conn)
+               goto conn_alloc_fail;
+
+       /* currently this is the only field which need to be initiated */
+       rwlock_init(&iser_conn->lock);
+
+       conn->dd_data = iser_conn;
+       iser_conn->iscsi_conn = conn;
+
+       return cls_conn;
+
+conn_alloc_fail:
+       iscsi_conn_teardown(cls_conn);
+       return NULL;
+}
+
+static void
+iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+       iscsi_conn_teardown(cls_conn);
+       kfree(iser_conn);
+}
+
+static int
+iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+                    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+                    int is_leading)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       struct iscsi_iser_conn *iser_conn;
+       struct iser_conn *ib_conn;
+       int error;
+
+       error = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+       if (error)
+               return error;
+
+       /* the transport ep handle comes from user space so it must be
+        * verified against the global ib connections list */
+       ib_conn = iscsi_iser_ib_conn_lookup(transport_eph);
+       if (!ib_conn) {
+               iser_err("can't bind eph %llx\n",
+                        (unsigned long long)transport_eph);
+               return -EINVAL;
+       }
+       /* binds the iSER connection retrieved from the previously
+        * connected ep_handle to the iSCSI layer connection. exchanges
+        * connection pointers */
+       iser_err("binding iscsi conn %p to iser_conn %p\n",conn,ib_conn);
+       iser_conn = conn->dd_data;
+       ib_conn->iser_conn = iser_conn;
+       iser_conn->ib_conn  = ib_conn;
+
+       conn->recv_lock = &iser_conn->lock;
+
+       return 0;
+}
+
+static int
+iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+       int err;
+
+       err = iscsi_conn_start(cls_conn);
+       if (err)
+               return err;
+
+       return iser_conn_set_full_featured_mode(conn);
+}
+
+static struct iscsi_transport iscsi_iser_transport;
+
+static struct iscsi_cls_session *
+iscsi_iser_session_create(struct iscsi_transport *iscsit,
+                        struct scsi_transport_template *scsit,
+                         uint32_t initial_cmdsn, uint32_t *hostno)
+{
+       struct iscsi_cls_session *cls_session;
+       struct iscsi_session *session;
+       int i;
+       uint32_t hn;
+       struct iscsi_cmd_task  *ctask;
+       struct iscsi_mgmt_task *mtask;
+       struct iscsi_iser_cmd_task *iser_ctask;
+       struct iser_desc *desc;
+
+       cls_session = iscsi_session_setup(iscsit, scsit,
+                                         sizeof(struct iscsi_iser_cmd_task),
+                                         sizeof(struct iser_desc),
+                                         initial_cmdsn, &hn);
+       if (!cls_session)
+       return NULL;
+
+       *hostno = hn;
+       session = class_to_transport_session(cls_session);
+
+       /* libiscsi setup itts, data and pool so just set desc fields */
+       for (i = 0; i < session->cmds_max; i++) {
+               ctask      = session->cmds[i];
+               iser_ctask = ctask->dd_data;
+               ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header;
+       }
+
+       for (i = 0; i < session->mgmtpool_max; i++) {
+               mtask      = session->mgmt_cmds[i];
+               desc       = mtask->dd_data;
+               mtask->hdr = &desc->iscsi_header;
+               desc->data = mtask->data;
+       }
+
+       return cls_session;
+}
+
+static int
+iscsi_iser_set_param(struct iscsi_cls_conn *cls_conn,
+                    enum iscsi_param param, char *buf, int buflen)
+{
+       int value;
+
+       switch (param) {
+       case ISCSI_PARAM_MAX_RECV_DLENGTH:
+               /* TBD */
+               break;
+       case ISCSI_PARAM_HDRDGST_EN:
+               sscanf(buf, "%d", &value);
+               if (value) {
+                       printk(KERN_ERR "DataDigest wasn't negotiated to None");
+                       return -EPROTO;
+               }
+               break;
+       case ISCSI_PARAM_DATADGST_EN:
+               sscanf(buf, "%d", &value);
+               if (value) {
+                       printk(KERN_ERR "DataDigest wasn't negotiated to None");
+                       return -EPROTO;
+               }
+               break;
+       case ISCSI_PARAM_IFMARKER_EN:
+               sscanf(buf, "%d", &value);
+               if (value) {
+                       printk(KERN_ERR "IFMarker wasn't negotiated to No");
+                       return -EPROTO;
+               }
+               break;
+       case ISCSI_PARAM_OFMARKER_EN:
+               sscanf(buf, "%d", &value);
+               if (value) {
+                       printk(KERN_ERR "OFMarker wasn't negotiated to No");
+                       return -EPROTO;
+               }
+               break;
+       default:
+               return iscsi_set_param(cls_conn, param, buf, buflen);
+       }
+
+       return 0;
+}
+
+static void
+iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+{
+       struct iscsi_conn *conn = cls_conn->dd_data;
+
+       stats->txdata_octets = conn->txdata_octets;
+       stats->rxdata_octets = conn->rxdata_octets;
+       stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+       stats->dataout_pdus = conn->dataout_pdus_cnt;
+       stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+       stats->datain_pdus = conn->datain_pdus_cnt; /* always 0 */
+       stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */
+       stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+       stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+       stats->custom_length = 3;
+       strcpy(stats->custom[0].desc, "qp_tx_queue_full");
+       stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */
+       strcpy(stats->custom[1].desc, "fmr_map_not_avail");
+       stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */;
+       strcpy(stats->custom[2].desc, "eh_abort_cnt");
+       stats->custom[2].value = conn->eh_abort_cnt;
+}
+
+static int
+iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking,
+                     __u64 *ep_handle)
+{
+       int err;
+       struct iser_conn *ib_conn;
+
+       err = iser_conn_init(&ib_conn);
+       if (err)
+               goto out;
+
+       err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, non_blocking);
+       if (!err)
+               *ep_handle = (__u64)(unsigned long)ib_conn;
+
+out:
+       return err;
+}
+
+static int
+iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms)
+{
+       struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+       int rc;
+
+       if (!ib_conn)
+               return -EINVAL;
+
+       rc = wait_event_interruptible_timeout(ib_conn->wait,
+                            ib_conn->state == ISER_CONN_UP,
+                            msecs_to_jiffies(timeout_ms));
+
+       /* if conn establishment failed, return error code to iscsi */
+       if (!rc &&
+           (ib_conn->state == ISER_CONN_TERMINATING ||
+            ib_conn->state == ISER_CONN_DOWN))
+               rc = -1;
+
+       iser_err("ib conn %p rc = %d\n", ib_conn, rc);
+
+       if (rc > 0)
+               return 1; /* success, this is the equivalent of POLLOUT */
+       else if (!rc)
+               return 0; /* timeout */
+       else
+               return rc; /* signal */
+}
+
+static void
+iscsi_iser_ep_disconnect(__u64 ep_handle)
+{
+       struct iser_conn *ib_conn;
+
+       ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+       if (!ib_conn)
+               return;
+
+       iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state);
+       iser_conn_terminate(ib_conn);
+}
+
+static struct scsi_host_template iscsi_iser_sht = {
+       .name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+       .queuecommand           = iscsi_queuecommand,
+       .can_queue              = ISCSI_XMIT_CMDS_MAX - 1,
+       .sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
+       .cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
+       .eh_abort_handler       = iscsi_eh_abort,
+       .eh_host_reset_handler  = iscsi_eh_host_reset,
+       .use_clustering         = DISABLE_CLUSTERING,
+       .proc_name              = "iscsi_iser",
+       .this_id                = -1,
+};
+
+static struct iscsi_transport iscsi_iser_transport = {
+       .owner                  = THIS_MODULE,
+       .name                   = "iser",
+       .caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
+       .param_mask             = ISCSI_MAX_RECV_DLENGTH |
+                                 ISCSI_MAX_XMIT_DLENGTH |
+                                 ISCSI_HDRDGST_EN |
+                                 ISCSI_DATADGST_EN |
+                                 ISCSI_INITIAL_R2T_EN |
+                                 ISCSI_MAX_R2T |
+                                 ISCSI_IMM_DATA_EN |
+                                 ISCSI_FIRST_BURST |
+                                 ISCSI_MAX_BURST |
+                                 ISCSI_PDU_INORDER_EN |
+                                 ISCSI_DATASEQ_INORDER_EN |
+                                 ISCSI_EXP_STATSN |
+                                 ISCSI_PERSISTENT_PORT |
+                                 ISCSI_PERSISTENT_ADDRESS |
+                                 ISCSI_TARGET_NAME |
+                                 ISCSI_TPGT,
+       .host_template          = &iscsi_iser_sht,
+       .conndata_size          = sizeof(struct iscsi_conn),
+       .max_lun                = ISCSI_ISER_MAX_LUN,
+       .max_cmd_len            = ISCSI_ISER_MAX_CMD_LEN,
+       /* session management */
+       .create_session         = iscsi_iser_session_create,
+       .destroy_session        = iscsi_session_teardown,
+       /* connection management */
+       .create_conn            = iscsi_iser_conn_create,
+       .bind_conn              = iscsi_iser_conn_bind,
+       .destroy_conn           = iscsi_iser_conn_destroy,
+       .set_param              = iscsi_iser_set_param,
+       .get_conn_param         = iscsi_conn_get_param,
+       .get_session_param      = iscsi_session_get_param,
+       .start_conn             = iscsi_iser_conn_start,
+       .stop_conn              = iscsi_conn_stop,
+       /* IO */
+       .send_pdu               = iscsi_conn_send_pdu,
+       .get_stats              = iscsi_iser_conn_get_stats,
+       .init_cmd_task          = iscsi_iser_cmd_init,
+       .xmit_cmd_task          = iscsi_iser_ctask_xmit,
+       .xmit_mgmt_task         = iscsi_iser_mtask_xmit,
+       .cleanup_cmd_task       = iscsi_iser_cleanup_ctask,
+       /* recovery */
+       .session_recovery_timedout = iscsi_session_recovery_timedout,
+
+       .ep_connect             = iscsi_iser_ep_connect,
+       .ep_poll                = iscsi_iser_ep_poll,
+       .ep_disconnect          = iscsi_iser_ep_disconnect
+};
+
+static int __init iser_init(void)
+{
+       int err;
+
+       iser_dbg("Starting iSER datamover...\n");
+
+       if (iscsi_max_lun < 1) {
+               printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
+               return -EINVAL;
+       }
+
+       iscsi_iser_transport.max_lun = iscsi_max_lun;
+
+       memset(&ig, 0, sizeof(struct iser_global));
+
+       ig.desc_cache = kmem_cache_create("iser_descriptors",
+                                         sizeof (struct iser_desc),
+                                         0, SLAB_HWCACHE_ALIGN,
+                                         NULL, NULL);
+       if (ig.desc_cache == NULL)
+               return -ENOMEM;
+
+       /* device init is called only after the first addr resolution */
+       mutex_init(&ig.device_list_mutex);
+       INIT_LIST_HEAD(&ig.device_list);
+       mutex_init(&ig.connlist_mutex);
+       INIT_LIST_HEAD(&ig.connlist);
+
+       if (!iscsi_register_transport(&iscsi_iser_transport)) {
+               iser_err("iscsi_register_transport failed\n");
+               err = -EINVAL;
+               goto register_transport_failure;
+       }
+
+       return 0;
+
+register_transport_failure:
+       kmem_cache_destroy(ig.desc_cache);
+
+       return err;
+}
+
+static void __exit iser_exit(void)
+{
+       iser_dbg("Removing iSER datamover...\n");
+       iscsi_unregister_transport(&iscsi_iser_transport);
+       kmem_cache_destroy(ig.desc_cache);
+}
+
+module_init(iser_init);
+module_exit(iser_exit);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
new file mode 100644 (file)
index 0000000..3350ba6
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * iSER transport for the Open iSCSI Initiator & iSER transport internals
+ *
+ * Copyright (C) 2004 Dmitry Yusupov
+ * Copyright (C) 2004 Alex Aizman
+ * Copyright (C) 2005 Mike Christie
+ * based on code maintained by open-iscsi@googlegroups.com
+ *
+ * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     - Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer.
+ *
+ *     - Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iscsi_iser.h 7051 2006-05-10 12:29:11Z ogerlitz $
+ */
+#ifndef __ISCSI_ISER_H__
+#define __ISCSI_ISER_H__
+
+#include <linux/types.h>
+#include <linux/net.h>
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
+#include <linux/mempool.h>
+#include <linux/uio.h>
+
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_fmr_pool.h>
+#include <rdma/rdma_cm.h>
+
+#define DRV_NAME       "iser"
+#define PFX            DRV_NAME ": "
+#define DRV_VER                "0.1"
+#define DRV_DATE       "May 7th, 2006"
+
+#define iser_dbg(fmt, arg...)                          \
+       do {                                            \
+               if (iser_debug_level > 0)               \
+                       printk(KERN_DEBUG PFX "%s:" fmt,\
+                               __func__ , ## arg);     \
+       } while (0)
+
+#define iser_err(fmt, arg...)                          \
+       do {                                            \
+               printk(KERN_ERR PFX "%s:" fmt,          \
+                      __func__ , ## arg);              \
+       } while (0)
+
+                                       /* support upto 512KB in one RDMA */
+#define ISCSI_ISER_SG_TABLESIZE         (0x80000 >> PAGE_SHIFT)
+#define ISCSI_ISER_MAX_LUN             256
+#define ISCSI_ISER_MAX_CMD_LEN         16
+
+/* QP settings */
+/* Maximal bounds on received asynchronous PDUs */
+#define ISER_MAX_RX_MISC_PDUS          4 /* NOOP_IN(2) , ASYNC_EVENT(2)   */
+
+#define ISER_MAX_TX_MISC_PDUS          6 /* NOOP_OUT(2), TEXT(1),         *
+                                          * SCSI_TMFUNC(2), LOGOUT(1) */
+
+#define ISER_QP_MAX_RECV_DTOS          (ISCSI_XMIT_CMDS_MAX + \
+                                       ISER_MAX_RX_MISC_PDUS    +  \
+                                       ISER_MAX_TX_MISC_PDUS)
+
+/* the max TX (send) WR supported by the iSER QP is defined by                 *
+ * max_send_wr = T * (1 + D) + C ; D is how many inflight dataouts we expect   *
+ * to have at max for SCSI command. The tx posting & completion handling code  *
+ * supports -EAGAIN scheme where tx is suspended till the QP has room for more *
+ * send WR. D=8 comes from 64K/8K                                              */
+
+#define ISER_INFLIGHT_DATAOUTS         8
+
+#define ISER_QP_MAX_REQ_DTOS           (ISCSI_XMIT_CMDS_MAX *    \
+                                       (1 + ISER_INFLIGHT_DATAOUTS) + \
+                                       ISER_MAX_TX_MISC_PDUS        + \
+                                       ISER_MAX_RX_MISC_PDUS)
+
+#define ISER_VER                       0x10
+#define ISER_WSV                       0x08
+#define ISER_RSV                       0x04
+
+struct iser_hdr {
+       u8      flags;
+       u8      rsvd[3];
+       __be32  write_stag; /* write rkey */
+       __be64  write_va;
+       __be32  read_stag;  /* read rkey */
+       __be64  read_va;
+} __attribute__((packed));
+
+
+/* Length of an object name string */
+#define ISER_OBJECT_NAME_SIZE              64
+
+enum iser_ib_conn_state {
+       ISER_CONN_INIT,            /* descriptor allocd, no conn          */
+       ISER_CONN_PENDING,         /* in the process of being established */
+       ISER_CONN_UP,              /* up and running                      */
+       ISER_CONN_TERMINATING,     /* in the process of being terminated  */
+       ISER_CONN_DOWN,            /* shut down                           */
+       ISER_CONN_STATES_NUM
+};
+
+enum iser_task_status {
+       ISER_TASK_STATUS_INIT = 0,
+       ISER_TASK_STATUS_STARTED,
+       ISER_TASK_STATUS_COMPLETED
+};
+
+enum iser_data_dir {
+       ISER_DIR_IN = 0,           /* to initiator */
+       ISER_DIR_OUT,              /* from initiator */
+       ISER_DIRS_NUM
+};
+
+struct iser_data_buf {
+       void               *buf;      /* pointer to the sg list               */
+       unsigned int       size;      /* num entries of this sg               */
+       unsigned long      data_len;  /* total data len                       */
+       unsigned int       dma_nents; /* returned by dma_map_sg               */
+       char               *copy_buf; /* allocated copy buf for SGs unaligned *
+                                      * for rdma which are copied            */
+       struct scatterlist sg_single; /* SG-ified clone of a non SG SC or     *
+                                      * unaligned SG                         */
+  };
+
+/* fwd declarations */
+struct iser_device;
+struct iscsi_iser_conn;
+struct iscsi_iser_cmd_task;
+
+struct iser_mem_reg {
+       u32  lkey;
+       u32  rkey;
+       u64  va;
+       u64  len;
+       void *mem_h;
+};
+
+struct iser_regd_buf {
+       struct iser_mem_reg     reg;        /* memory registration info        */
+       void                    *virt_addr;
+       struct iser_device      *device;    /* device->device for dma_unmap    */
+       dma_addr_t              dma_addr;   /* if non zero, addr for dma_unmap */
+       enum dma_data_direction direction;  /* direction for dma_unmap         */
+       unsigned int            data_size;
+       atomic_t                ref_count;  /* refcount, freed when dec to 0   */
+};
+
+#define MAX_REGD_BUF_VECTOR_LEN        2
+
+struct iser_dto {
+       struct iscsi_iser_cmd_task *ctask;
+       struct iscsi_iser_conn     *conn;
+       int                        notify_enable;
+
+       /* vector of registered buffers */
+       unsigned int               regd_vector_len;
+       struct iser_regd_buf       *regd[MAX_REGD_BUF_VECTOR_LEN];
+
+       /* offset into the registered buffer may be specified */
+       unsigned int               offset[MAX_REGD_BUF_VECTOR_LEN];
+
+       /* a smaller size may be specified, if 0, then full size is used */
+       unsigned int               used_sz[MAX_REGD_BUF_VECTOR_LEN];
+};
+
+enum iser_desc_type {
+       ISCSI_RX,
+       ISCSI_TX_CONTROL ,
+       ISCSI_TX_SCSI_COMMAND,
+       ISCSI_TX_DATAOUT
+};
+
+struct iser_desc {
+       struct iser_hdr              iser_header;
+       struct iscsi_hdr             iscsi_header;
+       struct iser_regd_buf         hdr_regd_buf;
+       void                         *data;         /* used by RX & TX_CONTROL */
+       struct iser_regd_buf         data_regd_buf; /* used by RX & TX_CONTROL */
+       enum   iser_desc_type        type;
+       struct iser_dto              dto;
+};
+
+struct iser_device {
+       struct ib_device             *ib_device;
+       struct ib_pd                 *pd;
+       struct ib_cq                 *cq;
+       struct ib_mr                 *mr;
+       struct tasklet_struct        cq_tasklet;
+       struct list_head             ig_list; /* entry in ig devices list */
+       int                          refcount;
+};
+
+struct iser_conn {
+       struct iscsi_iser_conn       *iser_conn; /* iser conn for upcalls  */
+       enum iser_ib_conn_state      state;         /* rdma connection state   */
+       spinlock_t                   lock;          /* used for state changes  */
+       struct iser_device           *device;       /* device context          */
+       struct rdma_cm_id            *cma_id;       /* CMA ID                  */
+       struct ib_qp                 *qp;           /* QP                      */
+       struct ib_fmr_pool           *fmr_pool;     /* pool of IB FMRs         */
+       int                          disc_evt_flag; /* disconn event delivered */
+       wait_queue_head_t            wait;          /* waitq for conn/disconn  */
+       atomic_t                     post_recv_buf_count; /* posted rx count   */
+       atomic_t                     post_send_buf_count; /* posted tx count   */
+       struct work_struct           comperror_work; /* conn term sleepable ctx*/
+       char                         name[ISER_OBJECT_NAME_SIZE];
+       struct iser_page_vec         *page_vec;     /* represents SG to fmr maps*
+                                                    * maps serialized as tx is*/
+       struct list_head             conn_list;       /* entry in ig conn list */
+};
+
+struct iscsi_iser_conn {
+       struct iscsi_conn            *iscsi_conn;/* ptr to iscsi conn */
+       struct iser_conn             *ib_conn;   /* iSER IB conn      */
+
+       rwlock_t                     lock;
+};
+
+struct iscsi_iser_cmd_task {
+       struct iser_desc             desc;
+       struct iscsi_iser_conn       *iser_conn;
+       int                          rdma_data_count;/* RDMA bytes           */
+       enum iser_task_status        status;
+       int                          command_sent;  /* set if command  sent  */
+       int                          dir[ISER_DIRS_NUM];      /* set if dir use*/
+       struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
+       struct iser_data_buf         data[ISER_DIRS_NUM];     /* orig. data des*/
+       struct iser_data_buf         data_copy[ISER_DIRS_NUM];/* contig. copy  */
+};
+
+struct iser_page_vec {
+       u64 *pages;
+       int length;
+       int offset;
+       int data_size;
+};
+
+struct iser_global {
+       struct mutex      device_list_mutex;/*                   */
+       struct list_head  device_list;       /* all iSER devices */
+       struct mutex      connlist_mutex;
+       struct list_head  connlist;             /* all iSER IB connections */
+
+       kmem_cache_t *desc_cache;
+};
+
+extern struct iser_global ig;
+extern int iser_debug_level;
+
+/* allocate connection resources needed for rdma functionality */
+int iser_conn_set_full_featured_mode(struct iscsi_conn *conn);
+
+int iser_send_control(struct iscsi_conn      *conn,
+                     struct iscsi_mgmt_task *mtask);
+
+int iser_send_command(struct iscsi_conn      *conn,
+                     struct iscsi_cmd_task  *ctask);
+
+int iser_send_data_out(struct iscsi_conn     *conn,
+                      struct iscsi_cmd_task *ctask,
+                      struct iscsi_data          *hdr);
+
+void iscsi_iser_recv(struct iscsi_conn *conn,
+                    struct iscsi_hdr       *hdr,
+                    char                   *rx_data,
+                    int                    rx_data_len);
+
+int  iser_conn_init(struct iser_conn **ib_conn);
+
+void iser_conn_terminate(struct iser_conn *ib_conn);
+
+void iser_conn_release(struct iser_conn *ib_conn);
+
+void iser_rcv_completion(struct iser_desc *desc,
+                        unsigned long    dto_xfer_len);
+
+void iser_snd_completion(struct iser_desc *desc);
+
+void iser_ctask_rdma_init(struct iscsi_iser_cmd_task     *ctask);
+
+void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *ctask);
+
+void iser_dto_buffs_release(struct iser_dto *dto);
+
+int  iser_regd_buff_release(struct iser_regd_buf *regd_buf);
+
+void iser_reg_single(struct iser_device      *device,
+                    struct iser_regd_buf    *regd_buf,
+                    enum dma_data_direction direction);
+
+int  iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task    *ctask,
+                                 enum iser_data_dir            cmd_dir);
+
+void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask,
+                                    enum iser_data_dir         cmd_dir);
+
+int  iser_reg_rdma_mem(struct iscsi_iser_cmd_task *ctask,
+                      enum   iser_data_dir        cmd_dir);
+
+int  iser_connect(struct iser_conn   *ib_conn,
+                 struct sockaddr_in *src_addr,
+                 struct sockaddr_in *dst_addr,
+                 int                non_blocking);
+
+int  iser_reg_page_vec(struct iser_conn     *ib_conn,
+                      struct iser_page_vec *page_vec,
+                      struct iser_mem_reg  *mem_reg);
+
+void iser_unreg_mem(struct iser_mem_reg *mem_reg);
+
+int  iser_post_recv(struct iser_desc *rx_desc);
+int  iser_post_send(struct iser_desc *tx_desc);
+
+int iser_conn_state_comp(struct iser_conn *ib_conn,
+                        enum iser_ib_conn_state comp);
+#endif
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
new file mode 100644 (file)
index 0000000..ccf56f6
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2004, 2005, 2006 Voltaire, 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     - Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer.
+ *
+ *     - Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iser_initiator.c 6964 2006-05-07 11:11:43Z ogerlitz $
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+#include <linux/kfifo.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+
+#include "iscsi_iser.h"
+
+/* Constant PDU lengths calculations */
+#define ISER_TOTAL_HEADERS_LEN  (sizeof (struct iser_hdr) + \
+                                sizeof (struct iscsi_hdr))
+
+/* iser_dto_add_regd_buff - increments the reference count for *
+ * the registered buffer & adds it to the DTO object           */
+static void iser_dto_add_regd_buff(struct iser_dto *dto,
+                                  struct iser_regd_buf *regd_buf,
+                                  unsigned long use_offset,
+                                  unsigned long use_size)
+{
+       int add_idx;
+
+       atomic_inc(&regd_buf->ref_count);
+
+       add_idx = dto->regd_vector_len;
+       dto->regd[add_idx] = regd_buf;
+       dto->used_sz[add_idx] = use_size;
+       dto->offset[add_idx] = use_offset;
+
+       dto->regd_vector_len++;
+}
+
+static int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
+                                 struct iser_data_buf       *data,
+                                 enum   iser_data_dir       iser_dir,
+                                 enum   dma_data_direction  dma_dir)
+{
+       struct device *dma_device;
+
+       iser_ctask->dir[iser_dir] = 1;
+       dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+       data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir);
+       if (data->dma_nents == 0) {
+               iser_err("dma_map_sg failed!!!\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
+{
+       struct device  *dma_device;
+       struct iser_data_buf *data;
+
+       dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+       if (iser_ctask->dir[ISER_DIR_IN]) {
+               data = &iser_ctask->data[ISER_DIR_IN];
+               dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE);
+       }
+
+       if (iser_ctask->dir[ISER_DIR_OUT]) {
+               data = &iser_ctask->data[ISER_DIR_OUT];
+               dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE);
+       }
+}
+
+/* Register user buffer memory and initialize passive rdma
+ *  dto descriptor. Total data size is stored in
+ *  iser_ctask->data[ISER_DIR_IN].data_len
+ */
+static int iser_prepare_read_cmd(struct iscsi_cmd_task *ctask,
+                                unsigned int edtl)
+
+{
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       struct iser_regd_buf *regd_buf;
+       int err;
+       struct iser_hdr *hdr = &iser_ctask->desc.iser_header;
+       struct iser_data_buf *buf_in = &iser_ctask->data[ISER_DIR_IN];
+
+       err = iser_dma_map_task_data(iser_ctask,
+                                    buf_in,
+                                    ISER_DIR_IN,
+                                    DMA_FROM_DEVICE);
+       if (err)
+               return err;
+
+       if (edtl > iser_ctask->data[ISER_DIR_IN].data_len) {
+               iser_err("Total data length: %ld, less than EDTL: "
+                        "%d, in READ cmd BHS itt: %d, conn: 0x%p\n",
+                        iser_ctask->data[ISER_DIR_IN].data_len, edtl,
+                        ctask->itt, iser_ctask->iser_conn);
+               return -EINVAL;
+       }
+
+       err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_IN);
+       if (err) {
+               iser_err("Failed to set up Data-IN RDMA\n");
+               return err;
+       }
+       regd_buf = &iser_ctask->rdma_regd[ISER_DIR_IN];
+
+       hdr->flags    |= ISER_RSV;
+       hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey);
+       hdr->read_va   = cpu_to_be64(regd_buf->reg.va);
+
+       iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n",
+                ctask->itt, regd_buf->reg.rkey,
+                (unsigned long long)regd_buf->reg.va);
+
+       return 0;
+}
+
+/* Register user buffer memory and initialize passive rdma
+ *  dto descriptor. Total data size is stored in
+ *  ctask->data[ISER_DIR_OUT].data_len
+ */
+static int
+iser_prepare_write_cmd(struct iscsi_cmd_task *ctask,
+                      unsigned int imm_sz,
+                      unsigned int unsol_sz,
+                      unsigned int edtl)
+{
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       struct iser_regd_buf *regd_buf;
+       int err;
+       struct iser_dto *send_dto = &iser_ctask->desc.dto;
+       struct iser_hdr *hdr = &iser_ctask->desc.iser_header;
+       struct iser_data_buf *buf_out = &iser_ctask->data[ISER_DIR_OUT];
+
+       err = iser_dma_map_task_data(iser_ctask,
+                                    buf_out,
+                                    ISER_DIR_OUT,
+                                    DMA_TO_DEVICE);
+       if (err)
+               return err;
+
+       if (edtl > iser_ctask->data[ISER_DIR_OUT].data_len) {
+               iser_err("Total data length: %ld, less than EDTL: %d, "
+                        "in WRITE cmd BHS itt: %d, conn: 0x%p\n",
+                        iser_ctask->data[ISER_DIR_OUT].data_len,
+                        edtl, ctask->itt, ctask->conn);
+               return -EINVAL;
+       }
+
+       err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_OUT);
+       if (err != 0) {
+               iser_err("Failed to register write cmd RDMA mem\n");
+               return err;
+       }
+
+       regd_buf = &iser_ctask->rdma_regd[ISER_DIR_OUT];
+
+       if (unsol_sz < edtl) {
+               hdr->flags     |= ISER_WSV;
+               hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey);
+               hdr->write_va   = cpu_to_be64(regd_buf->reg.va + unsol_sz);
+
+               iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X "
+                        "VA:%#llX + unsol:%d\n",
+                        ctask->itt, regd_buf->reg.rkey,
+                        (unsigned long long)regd_buf->reg.va, unsol_sz);
+       }
+
+       if (imm_sz > 0) {
+               iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
+                        ctask->itt, imm_sz);
+               iser_dto_add_regd_buff(send_dto,
+                                      regd_buf,
+                                      0,
+                                      imm_sz);
+       }
+
+       return 0;
+}
+
+/**
+ * iser_post_receive_control - allocates, initializes and posts receive DTO.
+ */
+static int iser_post_receive_control(struct iscsi_conn *conn)
+{
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+       struct iser_desc     *rx_desc;
+       struct iser_regd_buf *regd_hdr;
+       struct iser_regd_buf *regd_data;
+       struct iser_dto      *recv_dto = NULL;
+       struct iser_device  *device = iser_conn->ib_conn->device;
+       int rx_data_size, err = 0;
+
+       rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
+       if (rx_desc == NULL) {
+               iser_err("Failed to alloc desc for post recv\n");
+               return -ENOMEM;
+       }
+       rx_desc->type = ISCSI_RX;
+
+       /* for the login sequence we must support rx of upto 8K; login is done
+        * after conn create/bind (connect) and conn stop/bind (reconnect),
+        * what's common for both schemes is that the connection is not started
+        */
+       if (conn->c_stage != ISCSI_CONN_STARTED)
+               rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+       else /* FIXME till user space sets conn->max_recv_dlength correctly */
+               rx_data_size = 128;
+
+       rx_desc->data = kmalloc(rx_data_size, GFP_NOIO);
+       if (rx_desc->data == NULL) {
+               iser_err("Failed to alloc data buf for post recv\n");
+               err = -ENOMEM;
+               goto post_rx_kmalloc_failure;
+       }
+
+       recv_dto = &rx_desc->dto;
+       recv_dto->conn          = iser_conn;
+       recv_dto->regd_vector_len = 0;
+
+       regd_hdr = &rx_desc->hdr_regd_buf;
+       memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
+       regd_hdr->device  = device;
+       regd_hdr->virt_addr  = rx_desc; /* == &rx_desc->iser_header */
+       regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
+
+       iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE);
+
+       iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0);
+
+       regd_data = &rx_desc->data_regd_buf;
+       memset(regd_data, 0, sizeof(struct iser_regd_buf));
+       regd_data->device  = device;
+       regd_data->virt_addr  = rx_desc->data;
+       regd_data->data_size  = rx_data_size;
+
+       iser_reg_single(device, regd_data, DMA_FROM_DEVICE);
+
+       iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0);
+
+       err = iser_post_recv(rx_desc);
+       if (!err)
+               return 0;
+
+       /* iser_post_recv failed */
+       iser_dto_buffs_release(recv_dto);
+       kfree(rx_desc->data);
+post_rx_kmalloc_failure:
+       kmem_cache_free(ig.desc_cache, rx_desc);
+       return err;
+}
+
+/* creates a new tx descriptor and adds header regd buffer */
+static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn,
+                                 struct iser_desc       *tx_desc)
+{
+       struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf;
+       struct iser_dto      *send_dto = &tx_desc->dto;
+
+       memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
+       regd_hdr->device  = iser_conn->ib_conn->device;
+       regd_hdr->virt_addr  = tx_desc; /* == &tx_desc->iser_header */
+       regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
+
+       send_dto->conn          = iser_conn;
+       send_dto->notify_enable   = 1;
+       send_dto->regd_vector_len = 0;
+
+       memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
+       tx_desc->iser_header.flags = ISER_VER;
+
+       iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0);
+}
+
+/**
+ *  iser_conn_set_full_featured_mode - (iSER API)
+ */
+int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+{
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+       int i;
+       /* no need to keep it in a var, we are after login so if this should
+        * be negotiated, by now the result should be available here */
+       int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS;
+
+       iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num);
+
+       /* Check that there is no posted recv or send buffers left - */
+       /* they must be consumed during the login phase */
+       BUG_ON(atomic_read(&iser_conn->ib_conn->post_recv_buf_count) != 0);
+       BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+
+       /* Initial post receive buffers */
+       for (i = 0; i < initial_post_recv_bufs_num; i++) {
+               if (iser_post_receive_control(conn) != 0) {
+                       iser_err("Failed to post recv bufs at:%d conn:0x%p\n",
+                                i, conn);
+                       return -ENOMEM;
+               }
+       }
+       iser_dbg("Posted %d post recv bufs, conn:0x%p\n", i, conn);
+       return 0;
+}
+
+static int
+iser_check_xmit(struct iscsi_conn *conn, void *task)
+{
+       int rc = 0;
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+       write_lock_bh(conn->recv_lock);
+       if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
+           ISER_QP_MAX_REQ_DTOS) {
+               iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task);
+               set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+               rc = -EAGAIN;
+       }
+       write_unlock_bh(conn->recv_lock);
+       return rc;
+}
+
+
+/**
+ * iser_send_command - send command PDU
+ */
+int iser_send_command(struct iscsi_conn     *conn,
+                     struct iscsi_cmd_task *ctask)
+{
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       struct iser_dto *send_dto = NULL;
+       unsigned long edtl;
+       int err = 0;
+       struct iser_data_buf *data_buf;
+
+       struct iscsi_cmd *hdr =  ctask->hdr;
+       struct scsi_cmnd *sc  =  ctask->sc;
+
+       if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+               iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+               return -EPERM;
+       }
+       if (iser_check_xmit(conn, ctask))
+               return -EAGAIN;
+
+       edtl = ntohl(hdr->data_length);
+
+       /* build the tx desc regd header and add it to the tx desc dto */
+       iser_ctask->desc.type = ISCSI_TX_SCSI_COMMAND;
+       send_dto = &iser_ctask->desc.dto;
+       send_dto->ctask = iser_ctask;
+       iser_create_send_desc(iser_conn, &iser_ctask->desc);
+
+       if (hdr->flags & ISCSI_FLAG_CMD_READ)
+               data_buf = &iser_ctask->data[ISER_DIR_IN];
+       else
+               data_buf = &iser_ctask->data[ISER_DIR_OUT];
+
+       if (sc->use_sg) { /* using a scatter list */
+               data_buf->buf  = sc->request_buffer;
+               data_buf->size = sc->use_sg;
+       } else if (sc->request_bufflen) {
+               /* using a single buffer - convert it into one entry SG */
+               sg_init_one(&data_buf->sg_single,
+                           sc->request_buffer, sc->request_bufflen);
+               data_buf->buf   = &data_buf->sg_single;
+               data_buf->size  = 1;
+       }
+
+       data_buf->data_len = sc->request_bufflen;
+
+       if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+               err = iser_prepare_read_cmd(ctask, edtl);
+               if (err)
+                       goto send_command_error;
+       }
+       if (hdr->flags & ISCSI_FLAG_CMD_WRITE) {
+               err = iser_prepare_write_cmd(ctask,
+                                            ctask->imm_count,
+                                            ctask->imm_count +
+                                            ctask->unsol_count,
+                                            edtl);
+               if (err)
+                       goto send_command_error;
+       }
+
+       iser_reg_single(iser_conn->ib_conn->device,
+                       send_dto->regd[0], DMA_TO_DEVICE);
+
+       if (iser_post_receive_control(conn) != 0) {
+               iser_err("post_recv failed!\n");
+               err = -ENOMEM;
+               goto send_command_error;
+       }
+
+       iser_ctask->status = ISER_TASK_STATUS_STARTED;
+
+       err = iser_post_send(&iser_ctask->desc);
+       if (!err)
+               return 0;
+
+send_command_error:
+       iser_dto_buffs_release(send_dto);
+       iser_err("conn %p failed ctask->itt %d err %d\n",conn, ctask->itt, err);
+       return err;
+}
+
+/**
+ * iser_send_data_out - send data out PDU
+ */
+int iser_send_data_out(struct iscsi_conn     *conn,
+                      struct iscsi_cmd_task *ctask,
+                      struct iscsi_data *hdr)
+{
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+       struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+       struct iser_desc *tx_desc = NULL;
+       struct iser_dto *send_dto = NULL;
+       unsigned long buf_offset;
+       unsigned long data_seg_len;
+       unsigned int itt;
+       int err = 0;
+
+       if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+               iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+               return -EPERM;
+       }
+
+       if (iser_check_xmit(conn, ctask))
+               return -EAGAIN;
+
+       itt = ntohl(hdr->itt);
+       data_seg_len = ntoh24(hdr->dlength);
+       buf_offset   = ntohl(hdr->offset);
+
+       iser_dbg("%s itt %d dseg_len %d offset %d\n",
+                __func__,(int)itt,(int)data_seg_len,(int)buf_offset);
+
+       tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
+       if (tx_desc == NULL) {
+               iser_err("Failed to alloc desc for post dataout\n");
+               return -ENOMEM;
+       }
+
+       tx_desc->type = ISCSI_TX_DATAOUT;
+       memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr));
+
+       /* build the tx desc regd header and add it to the tx desc dto */
+       send_dto = &tx_desc->dto;
+       send_dto->ctask = iser_ctask;
+       iser_create_send_desc(iser_conn, tx_desc);
+
+       iser_reg_single(iser_conn->ib_conn->device,
+                       send_dto->regd[0], DMA_TO_DEVICE);
+
+       /* all data was registered for RDMA, we can use the lkey */
+       iser_dto_add_regd_buff(send_dto,
+                              &iser_ctask->rdma_regd[ISER_DIR_OUT],
+                              buf_offset,
+                              data_seg_len);
+
+       if (buf_offset + data_seg_len > iser_ctask->data[ISER_DIR_OUT].data_len) {
+               iser_err("Offset:%ld & DSL:%ld in Data-Out "
+                        "inconsistent with total len:%ld, itt:%d\n",
+                        buf_offset, data_seg_len,
+                        iser_ctask->data[ISER_DIR_OUT].data_len, itt);
+               err = -EINVAL;
+               goto send_data_out_error;
+       }
+       iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n",
+                itt, buf_offset, data_seg_len);
+
+
+       err = iser_post_send(tx_desc);
+       if (!err)
+               return 0;
+
+send_data_out_error:
+       iser_dto_buffs_release(send_dto);
+       kmem_cache_free(ig.desc_cache, tx_desc);
+       iser_err("conn %p failed err %d\n",conn, err);
+       return err;
+}
+
+int iser_send_control(struct iscsi_conn *conn,
+                     struct iscsi_mgmt_task *mtask)
+{
+       struct iscsi_iser_conn *iser_conn = conn->dd_data;
+       struct iser_desc *mdesc = mtask->dd_data;
+       struct iser_dto *send_dto = NULL;
+       unsigned int itt;
+       unsigned long data_seg_len;
+       int err = 0;
+       unsigned char opcode;
+       struct iser_regd_buf *regd_buf;
+       struct iser_device *device;
+
+       if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+               iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+               return -EPERM;
+       }
+
+       if (iser_check_xmit(conn,mtask))
+               return -EAGAIN;
+
+       /* build the tx desc regd header and add it to the tx desc dto */
+       mdesc->type = ISCSI_TX_CONTROL;
+       send_dto = &mdesc->dto;
+       send_dto->ctask = NULL;
+       iser_create_send_desc(iser_conn, mdesc);
+
+       device = iser_conn->ib_conn->device;
+
+       iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
+
+       itt = ntohl(mtask->hdr->itt);
+       opcode = mtask->hdr->opcode & ISCSI_OPCODE_MASK;
+       data_seg_len = ntoh24(mtask->hdr->dlength);
+
+       if (data_seg_len > 0) {
+               regd_buf = &mdesc->data_regd_buf;
+               memset(regd_buf, 0, sizeof(struct iser_regd_buf));
+               regd_buf->device = device;
+               regd_buf->virt_addr = mtask->data;
+               regd_buf->data_size = mtask->data_count;
+               iser_reg_single(device, regd_buf,
+                               DMA_TO_DEVICE);
+               iser_dto_add_regd_buff(send_dto, regd_buf,
+                                      0,
+                                      data_seg_len);
+       }
+
+       if (iser_post_receive_control(conn) != 0) {
+               iser_err("post_rcv_buff failed!\n");
+               err = -ENOMEM;
+               goto send_control_error;
+       }
+
+       err = iser_post_send(mdesc);
+       if (!err)
+               return 0;
+
+send_control_error:
+       iser_dto_buffs_release(send_dto);
+       iser_err("conn %p failed err %d\n",conn, err);
+       return err;
+}
+
+/**
+ * iser_rcv_dto_completion - recv DTO completion
+ */
+void iser_rcv_completion(struct iser_desc *rx_desc,
+                        unsigned long dto_xfer_len)
+{
+       struct iser_dto        *dto = &rx_desc->dto;
+       struct iscsi_iser_conn *conn = dto->conn;
+       struct iscsi_session *session = conn->iscsi_conn->session;
+       struct iscsi_cmd_task *ctask;
+       struct iscsi_iser_cmd_task *iser_ctask;
+       struct iscsi_hdr *hdr;
+       char   *rx_data = NULL;
+       int     rx_data_len = 0;
+       unsigned int itt;
+       unsigned char opcode;
+
+       hdr = &rx_desc->iscsi_header;
+
+       iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt);
+
+       if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */
+               rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN;
+               rx_data     = dto->regd[1]->virt_addr;
+               rx_data    += dto->offset[1];
+       }
+
+       opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+
+       if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
+               itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */
+               if (!(itt < session->cmds_max))
+                       iser_err("itt can't be matched to task!!!"
+                                "conn %p opcode %d cmds_max %d itt %d\n",
+                                conn->iscsi_conn,opcode,session->cmds_max,itt);
+               /* use the mapping given with the cmds array indexed by itt */
+               ctask = (struct iscsi_cmd_task *)session->cmds[itt];
+               iser_ctask = ctask->dd_data;
+               iser_dbg("itt %d ctask %p\n",itt,ctask);
+               iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+               iser_ctask_rdma_finalize(iser_ctask);
+       }
+
+       iser_dto_buffs_release(dto);
+
+       iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len);
+
+       kfree(rx_desc->data);
+       kmem_cache_free(ig.desc_cache, rx_desc);
+
+       /* decrementing conn->post_recv_buf_count only --after-- freeing the   *
+        * task eliminates the need to worry on tasks which are completed in   *
+        * parallel to the execution of iser_conn_term. So the code that waits *
+        * for the posted rx bufs refcount to become zero handles everything   */
+       atomic_dec(&conn->ib_conn->post_recv_buf_count);
+}
+
+void iser_snd_completion(struct iser_desc *tx_desc)
+{
+       struct iser_dto        *dto = &tx_desc->dto;
+       struct iscsi_iser_conn *iser_conn = dto->conn;
+       struct iscsi_conn      *conn = iser_conn->iscsi_conn;
+       struct iscsi_mgmt_task *mtask;
+
+       iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
+
+       iser_dto_buffs_release(dto);
+
+       if (tx_desc->type == ISCSI_TX_DATAOUT)
+               kmem_cache_free(ig.desc_cache, tx_desc);
+
+       atomic_dec(&iser_conn->ib_conn->post_send_buf_count);
+
+       write_lock(conn->recv_lock);
+       if (conn->suspend_tx) {
+               iser_dbg("%ld resuming tx\n",jiffies);
+               clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+               scsi_queue_work(conn->session->host, &conn->xmitwork);
+       }
+       write_unlock(conn->recv_lock);
+
+       if (tx_desc->type == ISCSI_TX_CONTROL) {
+               /* this arithmetic is legal by libiscsi dd_data allocation */
+               mtask = (void *) ((long)(void *)tx_desc -
+                                 sizeof(struct iscsi_mgmt_task));
+               if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+                       struct iscsi_session *session = conn->session;
+
+                       spin_lock(&conn->session->lock);
+                       list_del(&mtask->running);
+                       __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+                                   sizeof(void*));
+                       spin_unlock(&session->lock);
+               }
+       }
+}
+
+void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask)
+
+{
+       iser_ctask->status = ISER_TASK_STATUS_INIT;
+
+       iser_ctask->dir[ISER_DIR_IN] = 0;
+       iser_ctask->dir[ISER_DIR_OUT] = 0;
+
+       iser_ctask->data[ISER_DIR_IN].data_len  = 0;
+       iser_ctask->data[ISER_DIR_OUT].data_len = 0;
+
+       memset(&iser_ctask->rdma_regd[ISER_DIR_IN], 0,
+              sizeof(struct iser_regd_buf));
+       memset(&iser_ctask->rdma_regd[ISER_DIR_OUT], 0,
+              sizeof(struct iser_regd_buf));
+}
+
+void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
+{
+       int deferred;
+
+       /* if we were reading, copy back to unaligned sglist,
+        * anyway dma_unmap and free the copy
+        */
+       if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL)
+               iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN);
+       if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL)
+               iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT);
+
+       if (iser_ctask->dir[ISER_DIR_IN]) {
+               deferred = iser_regd_buff_release
+                       (&iser_ctask->rdma_regd[ISER_DIR_IN]);
+               if (deferred) {
+                       iser_err("References remain for BUF-IN rdma reg\n");
+                       BUG();
+               }
+       }
+
+       if (iser_ctask->dir[ISER_DIR_OUT]) {
+               deferred = iser_regd_buff_release
+                       (&iser_ctask->rdma_regd[ISER_DIR_OUT]);
+               if (deferred) {
+                       iser_err("References remain for BUF-OUT rdma reg\n");
+                       BUG();
+               }
+       }
+
+       iser_dma_unmap_task_data(iser_ctask);
+}
+
+void iser_dto_buffs_release(struct iser_dto *dto)
+{
+       int i;
+
+       for (i = 0; i < dto->regd_vector_len; i++)
+               iser_regd_buff_release(dto->regd[i]);
+}
+
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
new file mode 100644 (file)
index 0000000..31950a5
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2004, 2005, 2006 Voltaire, 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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     - Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer.
+ *
+ *     - Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iser_memory.c 6964 2006-05-07 11:11:43Z ogerlitz $
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include "iscsi_iser.h"
+
+#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */
+/**
+ * Decrements the reference count for the
+ * registered buffer & releases it
+ *
+ * returns 0 if released, 1 if deferred
+ */
+int iser_regd_buff_release(struct iser_regd_buf *regd_buf)
+{
+       struct device *dma_device;
+
+       if ((atomic_read(&regd_buf->ref_count) == 0) ||
+           atomic_dec_and_test(&regd_buf->ref_count)) {
+               /* if we used the dma mr, unreg is just NOP */
+               if (regd_buf->reg.rkey != 0)
+                       iser_unreg_mem(&regd_buf->reg);
+
+               if (regd_buf->dma_addr) {
+                       dma_device = regd_buf->device->ib_device->dma_device;
+                       dma_unmap_single(dma_device,
+                                        regd_buf->dma_addr,
+                                        regd_buf->data_size,
+                                        regd_buf->direction);
+               }
+               /* else this regd buf is associated with task which we */
+               /* dma_unmap_single/sg later */
+               return 0;
+       } else {
+               iser_dbg("Release deferred, regd.buff: 0x%p\n", regd_buf);
+               return 1;
+       }
+}
+
+/**
+ * iser_reg_single - fills registered buffer descriptor with
+ *                  registration information
+ */
+void iser_reg_single(struct iser_device *device,
+                    struct iser_regd_buf *regd_buf,
+                    enum dma_data_direction direction)
+{
+       dma_addr_t dma_addr;
+
+       dma_addr  = dma_map_single(device->ib_device->dma_device,
+                                  regd_buf->virt_addr,
+                                  regd_buf->data_size, direction);
+       BUG_ON(dma_mapping_error(dma_addr));
+
+       regd_buf->reg.lkey = device->mr->lkey;
+       regd_buf->reg.rkey = 0; /* indicate there's no need to unreg */
+       regd_buf->reg.len  = regd_buf->data_size;
+       regd_buf->reg.va   = dma_addr;
+
+       regd_buf->dma_addr  = dma_addr;
+       regd_buf->direction = direction;
+}
+
+/**
+ * iser_start_rdma_unaligned_sg
+ */
+int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task  *iser_ctask,
+                                enum iser_data_dir cmd_dir)
+{
+       int dma_nents;
+       struct device *dma_device;
+       char *mem = NULL;
+       struct iser_data_buf *data = &iser_ctask->data[cmd_dir];
+       unsigned long  cmd_data_len = data->data_len;
+
+       if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+               mem = (void *)__get_free_pages(GFP_NOIO,
+                     long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+       else
+               mem = kmalloc(cmd_data_len, GFP_NOIO);
+
+       if (mem == NULL) {
+               iser_err("Failed to allocate mem size %d %d for copying sglist\n",
+                        data->size,(int)cmd_data_len);
+               return -ENOMEM;
+       }
+
+       if (cmd_dir == ISER_DIR_OUT) {
+               /* copy the unaligned sg the buffer which is used for RDMA */
+               struct scatterlist *sg = (struct scatterlist *)data->buf;
+               int i;
+               char *p, *from;
+
+               for (p = mem, i = 0; i < data->size; i++) {
+                       from = kmap_atomic(sg[i].page, KM_USER0);
+                       memcpy(p,
+                              from + sg[i].offset,
+                              sg[i].length);
+                       kunmap_atomic(from, KM_USER0);
+                       p += sg[i].length;
+               }
+       }
+
+       sg_init_one(&iser_ctask->data_copy[cmd_dir].sg_single, mem, cmd_data_len);
+       iser_ctask->data_copy[cmd_dir].buf  =
+               &iser_ctask->data_copy[cmd_dir].sg_single;
+       iser_ctask->data_copy[cmd_dir].size = 1;
+
+       iser_ctask->data_copy[cmd_dir].copy_buf  = mem;
+
+       dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+       if (cmd_dir == ISER_DIR_OUT)
+               dma_nents = dma_map_sg(dma_device,
+                                      &iser_ctask->data_copy[cmd_dir].sg_single,
+                                      1, DMA_TO_DEVICE);
+       else
+               dma_nents = dma_map_sg(dma_device,
+                                      &iser_ctask->data_copy[cmd_dir].sg_single,
+                                      1, DMA_FROM_DEVICE);
+
+       BUG_ON(dma_nents == 0);
+
+       iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents;
+       return 0;
+}
+
+/**
+ * iser_finalize_rdma_unaligned_sg
+ */
+void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
+                                    enum iser_data_dir         cmd_dir)
+{
+       struct device *dma_device;
+       struct iser_data_buf *mem_copy;
+       unsigned long  cmd_data_len;
+
+       dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+       mem_copy   = &iser_ctask->data_copy[cmd_dir];
+
+       if (cmd_dir == ISER_DIR_OUT)
+               dma_unmap_sg(dma_device, &mem_copy->sg_single, 1,
+                            DMA_TO_DEVICE);
+       else
+               dma_unmap_sg(dma_device, &mem_copy->sg_single, 1,
+                            DMA_FROM_DEVICE);
+
+       if (cmd_dir == ISER_DIR_IN) {
+               char *mem;
+               struct scatterlist *sg;
+               unsigned char *p, *to;
+               unsigned int sg_size;
+               int i;
+
+               /* copy back read RDMA to unaligned sg */
+               mem     = mem_copy->copy_buf;
+
+               sg      = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf;
+               sg_size = iser_ctask->data[ISER_DIR_IN].size;
+
+               for (p = mem, i = 0; i < sg_size; i++){
+                       to = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
+                       memcpy(to + sg[i].offset,
+                              p,
+                              sg[i].length);
+                       kunmap_atomic(to, KM_SOFTIRQ0);
+                       p += sg[i].length;
+               }
+       }
+
+       cmd_data_len = iser_ctask->data[cmd_dir].data_len;
+
+       if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+               free_pages((unsigned long)mem_copy->copy_buf,
+                          long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+       else
+               kfree(mem_copy->copy_buf);
+
+       mem_copy->copy_buf = NULL;
+}
+
+/**
+ * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses
+ * and returns the length of resulting physical address array (may be less than
+ * the original due to possible compaction).
+ *
+ * we build a "page vec" under the assumption that the SG meets the RDMA
+ * alignment requirements. Other then the first and last SG elements, all
+ * the "internal" elements can be compacted into a list whose elements are
+ * dma addresses of physical pages. The code supports also the weird case
+ * where --few fragments of the same page-- are present in the SG as
+ * consecutive elements. Also, it handles one entry SG.
+ */
+static int iser_sg_to_page_vec(struct iser_data_buf *data,
+                              struct iser_page_vec *page_vec)
+{
+       struct scatterlist *sg = (struct scatterlist *)data->buf;
+       dma_addr_t first_addr, last_addr, page;
+       int start_aligned, end_aligned;
+       unsigned int cur_page = 0;
+       unsigned long total_sz = 0;
+       int i;
+
+       /* compute the offset of first element */
+       page_vec->offset = (u64) sg[0].offset;
+
+       for (i = 0; i < data->dma_nents; i++) {
+               total_sz += sg_dma_len(&sg[i]);
+
+               first_addr = sg_dma_address(&sg[i]);
+               last_addr  = first_addr + sg_dma_len(&sg[i]);
+
+               start_aligned = !(first_addr & ~PAGE_MASK);
+               end_aligned   = !(last_addr  & ~PAGE_MASK);
+
+               /* continue to collect page fragments till aligned or SG ends */
+               while (!end_aligned && (i + 1 < data->dma_nents)) {
+                       i++;
+                       total_sz += sg_dma_len(&sg[i]);
+                       last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]);
+                       end_aligned = !(last_addr  & ~PAGE_MASK);
+               }
+
+               first_addr = first_addr & PAGE_MASK;
+
+               for (page = first_addr; page < last_addr; page += PAGE_SIZE)
+                       page_vec->pages[cur_page++] = page;
+
+       }
+       page_vec->data_size = total_sz;
+       iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page);
+       return cur_page;
+}
+
+#define MASK_4K                        ((1UL << 12) - 1) /* 0xFFF */
+#define IS_4K_ALIGNED(addr)    ((((unsigned long)addr) & MASK_4K) == 0)
+
+/**
+ * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
+ * for RDMA sub-list of a scatter-gather list of memory buffers, and  returns
+ * the number of entries which are aligned correctly. Supports the case where
+ * consecutive SG elements are actually fragments of the same physcial page.
+ */
+static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data)
+{
+       struct scatterlist *sg;
+       dma_addr_t end_addr, next_addr;
+       int i, cnt;
+       unsigned int ret_len = 0;
+
+       sg = (struct scatterlist *)data->buf;
+
+       for (cnt = 0, i = 0; i < data->dma_nents; i++, cnt++) {
+               /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX "
+                  "offset: %ld sz: %ld\n", i,
+                  (unsigned long)page_to_phys(sg[i].page),
+                  (unsigned long)sg[i].offset,
+                  (unsigned long)sg[i].length); */
+               end_addr = sg_dma_address(&sg[i]) +
+                          sg_dma_len(&sg[i]);
+               /* iser_dbg("Checking sg iobuf end address "
+                      "0x%08lX\n", end_addr); */
+               if (i + 1 < data->dma_nents) {
+                       next_addr = sg_dma_address(&sg[i+1]);
+                       /* are i, i+1 fragments of the same page? */
+                       if (end_addr == next_addr)
+                               continue;
+                       else if (!IS_4K_ALIGNED(end_addr)) {
+                               ret_len = cnt + 1;
+                               break;
+                       }
+               }
+       }
+       if (i == data->dma_nents)
+               ret_len = cnt;  /* loop ended */
+       iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n",
+                ret_len, data->dma_nents, data);
+       return ret_len;
+}
+
+static void iser_data_buf_dump(struct iser_data_buf *data)
+{
+       struct scatterlist *sg = (struct scatterlist *)data->buf;
+       int i;
+
+       for (i = 0; i < data->size; i++)
+               iser_err("sg[%d] dma_addr:0x%lX page:0x%p "
+                        "off:%d sz:%d dma_len:%d\n",
+                        i, (unsigned long)sg_dma_address(&sg[i]),
+                        sg[i].page, sg[i].offset,
+                        sg[i].length,sg_dma_len(&sg[i]));
+}
+
+static void iser_dump_page_vec(struct iser_page_vec *page_vec)
+{
+       int i;
+
+       iser_err("page vec length %d data size %d\n",
+                page_vec->length, page_vec->data_size);
+       for (i = 0; i < page_vec->length; i++)
+               iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]);
+}
+
+static void iser_page_vec_build(struct iser_data_buf *data,
+                               struct iser_page_vec *page_vec)
+{
+       int page_vec_len = 0;
+
+       page_vec->length = 0;
+       page_vec->offset = 0;
+
+       iser_dbg("Translating sg sz: %d\n", data->dma_nents);
+       page_vec_len = iser_sg_to_page_vec(data,page_vec);
+       iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len);
+
+       page_vec->length = page_vec_len;
+
+       if (page_vec_len * PAGE_SIZE < page_vec->data_size) {
+               iser_err("page_vec too short to hold this SG\n");
+               iser_data_buf_dump(data);
+               iser_dump_page_vec(page_vec);
+               BUG();
+       }
+}
+
+/**
+ * iser_reg_rdma_mem - Registers memory intended for RDMA,
+ * obtaining rkey and va
+ *
+ * returns 0 on success, errno code on failure
+ */
+int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
+                     enum   iser_data_dir        cmd_dir)
+{
+       struct iser_conn     *ib_conn = iser_ctask->iser_conn->ib_conn;
+       struct iser_data_buf *mem = &iser_ctask->data[cmd_dir];
+       struct iser_regd_buf *regd_buf;
+       int aligned_len;
+       int err;
+
+       regd_buf = &iser_ctask->rdma_regd[cmd_dir];
+
+       aligned_len = iser_data_buf_aligned_len(mem);
+       if (aligned_len != mem->size) {
+               iser_err("rdma alignment violation %d/%d aligned\n",
+                        aligned_len, mem->size);
+               iser_data_buf_dump(mem);
+               /* allocate copy buf, if we are writing, copy the */
+               /* unaligned scatterlist, dma map the copy        */
+               if (iser_start_rdma_unaligned_sg(iser_ctask, cmd_dir) != 0)
+                               return -ENOMEM;
+               mem = &iser_ctask->data_copy[cmd_dir];
+       }
+
+       iser_page_vec_build(mem, ib_conn->page_vec);
+       err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg);
+       if (err)
+               return err;
+
+       /* take a reference on this regd buf such that it will not be released *
+        * (eg in send dto completion) before we get the scsi response         */
+       atomic_inc(&regd_buf->ref_count);
+       return 0;
+}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
new file mode 100644 (file)
index 0000000..72febf1
--- /dev/null
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     - Redistributions of source code must retain the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer.
+ *
+ *     - Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iser_verbs.c 7051 2006-05-10 12:29:11Z ogerlitz $
+ */
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+
+#include "iscsi_iser.h"
+
+#define ISCSI_ISER_MAX_CONN    8
+#define ISER_MAX_CQ_LEN                ((ISER_QP_MAX_RECV_DTOS + \
+                               ISER_QP_MAX_REQ_DTOS) *   \
+                                ISCSI_ISER_MAX_CONN)
+
+static void iser_cq_tasklet_fn(unsigned long data);
+static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
+static void iser_comp_error_worker(void *data);
+
+static void iser_cq_event_callback(struct ib_event *cause, void *context)
+{
+       iser_err("got cq event %d \n", cause->event);
+}
+
+static void iser_qp_event_callback(struct ib_event *cause, void *context)
+{
+       iser_err("got qp event %d\n",cause->event);
+}
+
+/**
+ * iser_create_device_ib_res - creates Protection Domain (PD), Completion
+ * Queue (CQ), DMA Memory Region (DMA MR) with the device associated with
+ * the adapator.
+ *
+ * returns 0 on success, -1 on failure
+ */
+static int iser_create_device_ib_res(struct iser_device *device)
+{
+       device->pd = ib_alloc_pd(device->ib_device);
+       if (IS_ERR(device->pd))
+               goto pd_err;
+
+       device->cq = ib_create_cq(device->ib_device,
+                                 iser_cq_callback,
+                                 iser_cq_event_callback,
+                                 (void *)device,
+                                 ISER_MAX_CQ_LEN);
+       if (IS_ERR(device->cq))
+               goto cq_err;
+
+       if (ib_req_notify_cq(device->cq, IB_CQ_NEXT_COMP))
+               goto cq_arm_err;
+
+       tasklet_init(&device->cq_tasklet,
+                    iser_cq_tasklet_fn,
+                    (unsigned long)device);
+
+       device->mr = ib_get_dma_mr(device->pd,
+                                  IB_ACCESS_LOCAL_WRITE);
+       if (IS_ERR(device->mr))
+               goto dma_mr_err;
+
+       return 0;
+
+dma_mr_err:
+       tasklet_kill(&device->cq_tasklet);
+cq_arm_err:
+       ib_destroy_cq(device->cq);
+cq_err:
+       ib_dealloc_pd(device->pd);
+pd_err:
+       iser_err("failed to allocate an IB resource\n");
+       return -1;
+}
+
+/**
+ * iser_free_device_ib_res - destory/dealloc/dereg the DMA MR,
+ * CQ and PD created with the device associated with the adapator.
+ */
+static void iser_free_device_ib_res(struct iser_device *device)
+{
+       BUG_ON(device->mr == NULL);
+
+       tasklet_kill(&device->cq_tasklet);
+
+       (void)ib_dereg_mr(device->mr);
+       (void)ib_destroy_cq(device->cq);
+       (void)ib_dealloc_pd(device->pd);
+
+       device->mr = NULL;
+       device->cq = NULL;
+       device->pd = NULL;
+}
+
+/**
+ * iser_create_ib_conn_res - Creates FMR pool and Queue-Pair (QP)
+ *
+ * returns 0 on success, -1 on failure
+ */
+static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
+{
+       struct iser_device      *device;
+       struct ib_qp_init_attr  init_attr;
+       int                     ret;
+       struct ib_fmr_pool_param params;
+
+       BUG_ON(ib_conn->device == NULL);
+
+       device = ib_conn->device;
+
+       ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
+                                   (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
+                                   GFP_KERNEL);
+       if (!ib_conn->page_vec) {
+               ret = -ENOMEM;
+               goto alloc_err;
+       }
+       ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec + 1);
+
+       params.page_shift        = PAGE_SHIFT;
+       /* when the first/last SG element are not start/end *
+        * page aligned, the map whould be of N+1 pages     */
+       params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1;
+       /* make the pool size twice the max number of SCSI commands *
+        * the ML is expected to queue, watermark for unmap at 50%  */
+       params.pool_size         = ISCSI_XMIT_CMDS_MAX * 2;
+       params.dirty_watermark   = ISCSI_XMIT_CMDS_MAX;
+       params.cache             = 0;
+       params.flush_function    = NULL;
+       params.access            = (IB_ACCESS_LOCAL_WRITE  |
+                                   IB_ACCESS_REMOTE_WRITE |
+                                   IB_ACCESS_REMOTE_READ);
+
+       ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, &params);
+       if (IS_ERR(ib_conn->fmr_pool)) {
+               ret = PTR_ERR(ib_conn->fmr_pool);
+               goto fmr_pool_err;
+       }
+
+       memset(&init_attr, 0, sizeof init_attr);
+
+       init_attr.event_handler = iser_qp_event_callback;
+       init_attr.qp_context    = (void *)ib_conn;
+       init_attr.send_cq       = device->cq;
+       init_attr.recv_cq       = device->cq;
+       init_attr.cap.max_send_wr  = ISER_QP_MAX_REQ_DTOS;
+       init_attr.cap.max_recv_wr  = ISER_QP_MAX_RECV_DTOS;
+       init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN;
+       init_attr.cap.max_recv_sge = 2;
+       init_attr.sq_sig_type   = IB_SIGNAL_REQ_WR;
+       init_attr.qp_type       = IB_QPT_RC;
+
+       ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr);
+       if (ret)
+               goto qp_err;
+
+       ib_conn->qp = ib_conn->cma_id->qp;
+       iser_err("setting conn %p cma_id %p: fmr_pool %p qp %p\n",
+                ib_conn, ib_conn->cma_id,
+                ib_conn->fmr_pool, ib_conn->cma_id->qp);
+       return ret;
+
+qp_err:
+       (void)ib_destroy_fmr_pool(ib_conn->fmr_pool);
+fmr_pool_err:
+       kfree(ib_conn->page_vec);
+alloc_err:
+       iser_err("unable to alloc mem or create resource, err %d\n", ret);
+       return ret;
+}
+
+/**
+ * releases the FMR pool, QP and CMA ID objects, returns 0 on success,
+ * -1 on failure
+ */
+static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
+{
+       BUG_ON(ib_conn == NULL);
+
+       iser_err("freeing conn %p cma_id %p fmr pool %p qp %p\n",
+                ib_conn, ib_conn->cma_id,
+                ib_conn->fmr_pool, ib_conn->qp);
+
+       /* qp is created only once both addr & route are resolved */
+       if (ib_conn->fmr_pool != NULL)
+               ib_destroy_fmr_pool(ib_conn->fmr_pool);
+
+       if (ib_conn->qp != NULL)
+               rdma_destroy_qp(ib_conn->cma_id);
+
+       if (ib_conn->cma_id != NULL)
+               rdma_destroy_id(ib_conn->cma_id);
+
+       ib_conn->fmr_pool = NULL;
+       ib_conn->qp       = NULL;
+       ib_conn->cma_id   = NULL;
+       kfree(ib_conn->page_vec);
+
+       return 0;
+}
+
+/**
+ * based on the resolved device node GUID see if there already allocated
+ * device for this device. If there's no such, create one.
+ */
+static
+struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id)
+{
+       struct list_head    *p_list;
+       struct iser_device  *device = NULL;
+
+       mutex_lock(&ig.device_list_mutex);
+
+       p_list = ig.device_list.next;
+       while (p_list != &ig.device_list) {
+               device = list_entry(p_list, struct iser_device, ig_list);
+               /* find if there's a match using the node GUID */
+               if (device->ib_device->node_guid == cma_id->device->node_guid)
+                       break;
+       }
+
+       if (device == NULL) {
+               device = kzalloc(sizeof *device, GFP_KERNEL);
+               if (device == NULL)
+                       goto out;
+               /* assign this device to the device */
+               device->ib_device = cma_id->device;
+               /* init the device and link it into ig device list */
+               if (iser_create_device_ib_res(device)) {
+                       kfree(device);
+                       device = NULL;
+                       goto out;
+               }
+               list_add(&device->ig_list, &ig.device_list);
+       }
+out:
+       BUG_ON(device == NULL);
+       device->refcount++;
+       mutex_unlock(&ig.device_list_mutex);
+       return device;
+}
+
+/* if there's no demand for this device, release it */
+static void iser_device_try_release(struct iser_device *device)
+{
+       mutex_lock(&ig.device_list_mutex);
+       device->refcount--;
+       iser_err("device %p refcount %d\n",device,device->refcount);
+       if (!device->refcount) {
+               iser_free_device_ib_res(device);
+               list_del(&device->ig_list);
+               kfree(device);
+       }
+       mutex_unlock(&ig.device_list_mutex);
+}
+
+int iser_conn_state_comp(struct iser_conn *ib_conn,
+                       enum iser_ib_conn_state comp)
+{
+       int ret;
+
+       spin_lock_bh(&ib_conn->lock);
+       ret = (ib_conn->state == comp);
+       spin_unlock_bh(&ib_conn->lock);
+       return ret;
+}
+
+static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
+                                    enum iser_ib_conn_state comp,
+                                    enum iser_ib_conn_state exch)
+{
+       int ret;
+
+       spin_lock_bh(&ib_conn->lock);
+       if ((ret = (ib_conn->state == comp)))
+               ib_conn->state = exch;
+       spin_unlock_bh(&ib_conn->lock);
+       return ret;
+}
+
+/**
+ * triggers start of the disconnect procedures and wait for them to be done
+ */
+void iser_conn_terminate(struct iser_conn *ib_conn)
+{
+       int err = 0;
+
+       /* change the ib conn state only if the conn is UP, however always call
+        * rdma_disconnect since this is the only way to cause the CMA to change
+        * the QP state to ERROR
+        */
+
+       iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING);
+       err = rdma_disconnect(ib_conn->cma_id);
+       if (err)
+               iser_err("Failed to disconnect, conn: 0x%p err %d\n",
+                        ib_conn,err);
+
+       wait_event_interruptible(ib_conn->wait,
+                                ib_conn->state == ISER_CONN_DOWN);
+
+       iser_conn_release(ib_conn);
+}
+
+static void iser_connect_error(struct rdma_cm_id *cma_id)
+{
+       struct iser_conn *ib_conn;
+       ib_conn = (struct iser_conn *)cma_id->context;
+
+       ib_conn->state = ISER_CONN_DOWN;
+       wake_up_interruptible(&ib_conn->wait);
+}
+
+static void iser_addr_handler(struct rdma_cm_id *cma_id)
+{
+       struct iser_device *device;
+       struct iser_conn   *ib_conn;
+       int    ret;
+
+       device = iser_device_find_by_ib_device(cma_id);
+       ib_conn = (struct iser_conn *)cma_id->context;
+       ib_conn->device = device;
+
+       ret = rdma_resolve_route(cma_id, 1000);
+       if (ret) {
+               iser_err("resolve route failed: %d\n", ret);
+               iser_connect_error(cma_id);
+       }
+       return;
+}
+
+static void iser_route_handler(struct rdma_cm_id *cma_id)
+{
+       struct rdma_conn_param conn_param;
+       int    ret;
+
+       ret = iser_create_ib_conn_res((struct iser_conn *)cma_id->context);
+       if (ret)
+               goto failure;
+
+       iser_dbg("path.mtu is %d setting it to %d\n",
+                cma_id->route.path_rec->mtu, IB_MTU_1024);
+
+       /* we must set the MTU to 1024 as this is what the target is assuming */
+       if (cma_id->route.path_rec->mtu > IB_MTU_1024)
+               cma_id->route.path_rec->mtu = IB_MTU_1024;
+
+       memset(&conn_param, 0, sizeof conn_param);
+       conn_param.responder_resources = 4;
+       conn_param.initiator_depth     = 1;
+       conn_param.retry_count         = 7;
+       conn_param.rnr_retry_count     = 6;
+
+       ret = rdma_connect(cma_id, &conn_param);
+       if (ret) {
+               iser_err("failure connecting: %d\n", ret);
+               goto failure;
+       }
+
+       return;
+failure:
+       iser_connect_error(cma_id);
+}
+
+static void iser_connected_handler(struct rdma_cm_id *cma_id)
+{
+       struct iser_conn *ib_conn;
+
+       ib_conn = (struct iser_conn *)cma_id->context;
+       ib_conn->state = ISER_CONN_UP;
+       wake_up_interruptible(&ib_conn->wait);
+}
+
+static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
+{
+       struct iser_conn *ib_conn;
+
+       ib_conn = (struct iser_conn *)cma_id->context;
+       ib_conn->disc_evt_flag = 1;
+
+       /* getting here when the state is UP means that the conn is being *
+        * terminated asynchronously from the iSCSI layer's perspective.  */
+       if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
+                                     ISER_CONN_TERMINATING))
+               iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+                                  ISCSI_ERR_CONN_FAILED);
+
+       /* Complete the termination process if no posts are pending */
+       if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) &&
+           (atomic_read(&ib_conn->post_send_buf_count) == 0)) {
+               ib_conn->state = ISER_CONN_DOWN;
+               wake_up_interruptible(&ib_conn->wait);
+       }
+}
+
+static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+{
+       int ret = 0;
+
+       iser_err("event %d conn %p id %p\n",event->event,cma_id->context,cma_id);
+
+       switch (event->event) {
+       case RDMA_CM_EVENT_ADDR_RESOLVED:
+               iser_addr_handler(cma_id);
+               break;
+       case RDMA_CM_EVENT_ROUTE_RESOLVED:
+               iser_route_handler(cma_id);
+               break;
+       case RDMA_CM_EVENT_ESTABLISHED:
+               iser_connected_handler(cma_id);
+               break;
+       case RDMA_CM_EVENT_ADDR_ERROR:
+       case RDMA_CM_EVENT_ROUTE_ERROR:
+       case RDMA_CM_EVENT_CONNECT_ERROR:
+       case RDMA_CM_EVENT_UNREACHABLE:
+       case RDMA_CM_EVENT_REJECTED:
+               iser_err("event: %d, error: %d\n", event->event, event->status);
+               iser_connect_error(cma_id);
+               break;
+       case RDMA_CM_EVENT_DISCONNECTED:
+               iser_disconnected_handler(cma_id);
+               break;
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:
+               BUG();
+               break;
+       case RDMA_CM_EVENT_CONNECT_RESPONSE:
+               BUG();
+               break;
+       case RDMA_CM_EVENT_CONNECT_REQUEST:
+       default:
+               break;
+       }
+       return ret;
+}
+
+int iser_conn_init(struct iser_conn **ibconn)
+{
+       struct iser_conn *ib_conn;
+
+       ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL);
+       if (!ib_conn) {
+               iser_err("can't alloc memory for struct iser_conn\n");
+               return -ENOMEM;
+       }
+       ib_conn->state = ISER_CONN_INIT;
+       init_waitqueue_head(&ib_conn->wait);
+       atomic_set(&ib_conn->post_recv_buf_count, 0);
+       atomic_set(&ib_conn->post_send_buf_count, 0);
+       INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker,
+                 ib_conn);
+       INIT_LIST_HEAD(&ib_conn->conn_list);
+       spin_lock_init(&ib_conn->lock);
+
+       *ibconn = ib_conn;
+       return 0;
+}
+
+ /**
+ * starts the process of connecting to the target
+ * sleeps untill the connection is established or rejected
+ */
+int iser_connect(struct iser_conn   *ib_conn,
+                struct sockaddr_in *src_addr,
+                struct sockaddr_in *dst_addr,
+                int                 non_blocking)
+{
+       struct sockaddr *src, *dst;
+       int err = 0;
+
+       sprintf(ib_conn->name,"%d.%d.%d.%d:%d",
+               NIPQUAD(dst_addr->sin_addr.s_addr), dst_addr->sin_port);
+
+       /* the device is known only --after-- address resolution */
+       ib_conn->device = NULL;
+
+       iser_err("connecting to: %d.%d.%d.%d, port 0x%x\n",
+                NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port);
+
+       ib_conn->state = ISER_CONN_PENDING;
+
+       ib_conn->cma_id = rdma_create_id(iser_cma_handler,
+                                            (void *)ib_conn,
+                                            RDMA_PS_TCP);
+       if (IS_ERR(ib_conn->cma_id)) {
+               err = PTR_ERR(ib_conn->cma_id);
+               iser_err("rdma_create_id failed: %d\n", err);
+               goto id_failure;
+       }
+
+       src = (struct sockaddr *)src_addr;
+       dst = (struct sockaddr *)dst_addr;
+       err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000);
+       if (err) {
+               iser_err("rdma_resolve_addr failed: %d\n", err);
+               goto addr_failure;
+       }
+
+       if (!non_blocking) {
+               wait_event_interruptible(ib_conn->wait,
+                                        (ib_conn->state != ISER_CONN_PENDING));
+
+               if (ib_conn->state != ISER_CONN_UP) {
+                       err =  -EIO;
+                       goto connect_failure;
+               }
+       }
+
+       mutex_lock(&ig.connlist_mutex);
+       list_add(&ib_conn->conn_list, &ig.connlist);
+       mutex_unlock(&ig.connlist_mutex);
+       return 0;
+
+id_failure:
+       ib_conn->cma_id = NULL;
+addr_failure:
+       ib_conn->state = ISER_CONN_DOWN;
+connect_failure:
+       iser_conn_release(ib_conn);
+       return err;
+}
+
+/**
+ * Frees all conn objects and deallocs conn descriptor
+ */
+void iser_conn_release(struct iser_conn *ib_conn)
+{
+       struct iser_device  *device = ib_conn->device;
+
+       BUG_ON(ib_conn->state != ISER_CONN_DOWN);
+
+       mutex_lock(&ig.connlist_mutex);
+       list_del(&ib_conn->conn_list);
+       mutex_unlock(&ig.connlist_mutex);
+
+       iser_free_ib_conn_res(ib_conn);
+       ib_conn->device = NULL;
+       /* on EVENT_ADDR_ERROR there's no device yet for this conn */
+       if (device != NULL)
+               iser_device_try_release(device);
+       kfree(ib_conn);
+}
+
+
+/**
+ * iser_reg_page_vec - Register physical memory
+ *
+ * returns: 0 on success, errno code on failure
+ */
+int iser_reg_page_vec(struct iser_conn     *ib_conn,
+                     struct iser_page_vec *page_vec,
+                     struct iser_mem_reg  *mem_reg)
+{
+       struct ib_pool_fmr *mem;
+       u64                io_addr;
+       u64                *page_list;
+       int                status;
+
+       page_list = page_vec->pages;
+       io_addr   = page_list[0];
+
+       mem  = ib_fmr_pool_map_phys(ib_conn->fmr_pool,
+                                   page_list,
+                                   page_vec->length,
+                                   io_addr);
+
+       if (IS_ERR(mem)) {
+               status = (int)PTR_ERR(mem);
+               iser_err("ib_fmr_pool_map_phys failed: %d\n", status);
+               return status;
+       }
+
+       mem_reg->lkey  = mem->fmr->lkey;
+       mem_reg->rkey  = mem->fmr->rkey;
+       mem_reg->len   = page_vec->length * PAGE_SIZE;
+       mem_reg->va    = io_addr;
+       mem_reg->mem_h = (void *)mem;
+
+       mem_reg->va   += page_vec->offset;
+       mem_reg->len   = page_vec->data_size;
+
+       iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, "
+                "entry[0]: (0x%08lx,%ld)] -> "
+                "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n",
+                page_vec, page_vec->length,
+                (unsigned long)page_vec->pages[0],
+                (unsigned long)page_vec->data_size,
+                (unsigned int)mem_reg->lkey, mem_reg->mem_h,
+                (unsigned long)mem_reg->va, (unsigned long)mem_reg->len);
+       return 0;
+}
+
+/**
+ * Unregister (previosuly registered) memory.
+ */
+void iser_unreg_mem(struct iser_mem_reg *reg)
+{
+       int ret;
+
+       iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h);
+
+       ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);
+       if (ret)
+               iser_err("ib_fmr_pool_unmap failed %d\n", ret);
+
+       reg->mem_h = NULL;
+}
+
+/**
+ * iser_dto_to_iov - builds IOV from a dto descriptor
+ */
+static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_len)
+{
+       int                  i;
+       struct ib_sge        *sge;
+       struct iser_regd_buf *regd_buf;
+
+       if (dto->regd_vector_len > iov_len) {
+               iser_err("iov size %d too small for posting dto of len %d\n",
+                        iov_len, dto->regd_vector_len);
+               BUG();
+       }
+
+       for (i = 0; i < dto->regd_vector_len; i++) {
+               sge         = &iov[i];
+               regd_buf  = dto->regd[i];
+
+               sge->addr   = regd_buf->reg.va;
+               sge->length = regd_buf->reg.len;
+               sge->lkey   = regd_buf->reg.lkey;
+
+               if (dto->used_sz[i] > 0)  /* Adjust size */
+                       sge->length = dto->used_sz[i];
+
+               /* offset and length should not exceed the regd buf length */
+               if (sge->length + dto->offset[i] > regd_buf->reg.len) {
+                       iser_err("Used len:%ld + offset:%d, exceed reg.buf.len:"
+                                "%ld in dto:0x%p [%d], va:0x%08lX\n",
+                                (unsigned long)sge->length, dto->offset[i],
+                                (unsigned long)regd_buf->reg.len, dto, i,
+                                (unsigned long)sge->addr);
+                       BUG();
+               }
+
+               sge->addr += dto->offset[i]; /* Adjust offset */
+       }
+}
+
+/**
+ * iser_post_recv - Posts a receive buffer.
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_post_recv(struct iser_desc *rx_desc)
+{
+       int               ib_ret, ret_val = 0;
+       struct ib_recv_wr recv_wr, *recv_wr_failed;
+       struct ib_sge     iov[2];
+       struct iser_conn  *ib_conn;
+       struct iser_dto   *recv_dto = &rx_desc->dto;
+
+       /* Retrieve conn */
+       ib_conn = recv_dto->conn->ib_conn;
+
+       iser_dto_to_iov(recv_dto, iov, 2);
+
+       recv_wr.next    = NULL;
+       recv_wr.sg_list = iov;
+       recv_wr.num_sge = recv_dto->regd_vector_len;
+       recv_wr.wr_id   = (unsigned long)rx_desc;
+
+       atomic_inc(&ib_conn->post_recv_buf_count);
+       ib_ret  = ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed);
+       if (ib_ret) {
+               iser_err("ib_post_recv failed ret=%d\n", ib_ret);
+               atomic_dec(&ib_conn->post_recv_buf_count);
+               ret_val = -1;
+       }
+
+       return ret_val;
+}
+
+/**
+ * iser_start_send - Initiate a Send DTO operation
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_post_send(struct iser_desc *tx_desc)
+{
+       int               ib_ret, ret_val = 0;
+       struct ib_send_wr send_wr, *send_wr_failed;
+       struct ib_sge     iov[MAX_REGD_BUF_VECTOR_LEN];
+       struct iser_conn  *ib_conn;
+       struct iser_dto   *dto = &tx_desc->dto;
+
+       ib_conn = dto->conn->ib_conn;
+
+       iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN);
+
+       send_wr.next       = NULL;
+       send_wr.wr_id      = (unsigned long)tx_desc;
+       send_wr.sg_list    = iov;
+       send_wr.num_sge    = dto->regd_vector_len;
+       send_wr.opcode     = IB_WR_SEND;
+       send_wr.send_flags = dto->notify_enable ? IB_SEND_SIGNALED : 0;
+
+       atomic_inc(&ib_conn->post_send_buf_count);
+
+       ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed);
+       if (ib_ret) {
+               iser_err("Failed to start SEND DTO, dto: 0x%p, IOV len: %d\n",
+                        dto, dto->regd_vector_len);
+               iser_err("ib_post_send failed, ret:%d\n", ib_ret);
+               atomic_dec(&ib_conn->post_send_buf_count);
+               ret_val = -1;
+       }
+
+       return ret_val;
+}
+
+static void iser_comp_error_worker(void *data)
+{
+       struct iser_conn *ib_conn = data;
+
+       /* getting here when the state is UP means that the conn is being *
+        * terminated asynchronously from the iSCSI layer's perspective.  */
+       if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
+                                     ISER_CONN_TERMINATING))
+               iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+                                       ISCSI_ERR_CONN_FAILED);
+
+       /* complete the termination process if disconnect event was delivered *
+        * note there are no more non completed posts to the QP               */
+       if (ib_conn->disc_evt_flag) {
+               ib_conn->state = ISER_CONN_DOWN;
+               wake_up_interruptible(&ib_conn->wait);
+       }
+}
+
+static void iser_handle_comp_error(struct iser_desc *desc)
+{
+       struct iser_dto  *dto     = &desc->dto;
+       struct iser_conn *ib_conn = dto->conn->ib_conn;
+
+       iser_dto_buffs_release(dto);
+
+       if (desc->type == ISCSI_RX) {
+               kfree(desc->data);
+               kmem_cache_free(ig.desc_cache, desc);
+               atomic_dec(&ib_conn->post_recv_buf_count);
+       } else { /* type is TX control/command/dataout */
+               if (desc->type == ISCSI_TX_DATAOUT)
+                       kmem_cache_free(ig.desc_cache, desc);
+               atomic_dec(&ib_conn->post_send_buf_count);
+       }
+
+       if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&
+           atomic_read(&ib_conn->post_send_buf_count) == 0)
+               schedule_work(&ib_conn->comperror_work);
+}
+
+static void iser_cq_tasklet_fn(unsigned long data)
+{
+        struct iser_device  *device = (struct iser_device *)data;
+        struct ib_cq        *cq = device->cq;
+        struct ib_wc        wc;
+        struct iser_desc    *desc;
+        unsigned long       xfer_len;
+
+       while (ib_poll_cq(cq, 1, &wc) == 1) {
+               desc     = (struct iser_desc *) (unsigned long) wc.wr_id;
+               BUG_ON(desc == NULL);
+
+               if (wc.status == IB_WC_SUCCESS) {
+                       if (desc->type == ISCSI_RX) {
+                               xfer_len = (unsigned long)wc.byte_len;
+                               iser_rcv_completion(desc, xfer_len);
+                       } else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */
+                               iser_snd_completion(desc);
+               } else {
+                       iser_err("comp w. error op %d status %d\n",desc->type,wc.status);
+                       iser_handle_comp_error(desc);
+               }
+       }
+       /* #warning "it is assumed here that arming CQ only once its empty" *
+        * " would not cause interrupts to be missed"                       */
+       ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+}
+
+static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
+{
+       struct iser_device  *device = (struct iser_device *)cq_context;
+
+       tasklet_schedule(&device->cq_tasklet);
+}
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
new file mode 100644 (file)
index 0000000..599878c
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * LEDs driver for Amstrad Delta (E3)
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can 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/leds.h>
+#include <asm/arch/board-ams-delta.h>
+
+/*
+ * Our context
+ */
+struct ams_delta_led {
+       struct led_classdev     cdev;
+       u8                      bitmask;
+};
+
+static void ams_delta_led_set(struct led_classdev *led_cdev,
+               enum led_brightness value)
+{
+       struct ams_delta_led *led_dev =
+               container_of(led_cdev, struct ams_delta_led, cdev);
+
+       if (value)
+               ams_delta_latch1_write(led_dev->bitmask, led_dev->bitmask);
+       else
+               ams_delta_latch1_write(led_dev->bitmask, 0);
+}
+
+static struct ams_delta_led ams_delta_leds[] = {
+       {
+               .cdev           = {
+                       .name           = "ams-delta:camera",
+                       .brightness_set = ams_delta_led_set,
+               },
+               .bitmask        = AMS_DELTA_LATCH1_LED_CAMERA,
+       },
+       {
+               .cdev           = {
+                       .name           = "ams-delta:advert",
+                       .brightness_set = ams_delta_led_set,
+               },
+               .bitmask        = AMS_DELTA_LATCH1_LED_ADVERT,
+       },
+       {
+               .cdev           = {
+                       .name           = "ams-delta:email",
+                       .brightness_set = ams_delta_led_set,
+               },
+               .bitmask        = AMS_DELTA_LATCH1_LED_EMAIL,
+       },
+       {
+               .cdev           = {
+                       .name           = "ams-delta:handsfree",
+                       .brightness_set = ams_delta_led_set,
+               },
+               .bitmask        = AMS_DELTA_LATCH1_LED_HANDSFREE,
+       },
+       {
+               .cdev           = {
+                       .name           = "ams-delta:voicemail",
+                       .brightness_set = ams_delta_led_set,
+               },
+               .bitmask        = AMS_DELTA_LATCH1_LED_VOICEMAIL,
+       },
+       {
+               .cdev           = {
+                       .name           = "ams-delta:voice",
+                       .brightness_set = ams_delta_led_set,
+               },
+               .bitmask        = AMS_DELTA_LATCH1_LED_VOICE,
+       },
+};
+
+#ifdef CONFIG_PM
+static int ams_delta_led_suspend(struct platform_device *dev,
+               pm_message_t state)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
+               led_classdev_suspend(&ams_delta_leds[i].cdev);
+
+       return 0;
+}
+
+static int ams_delta_led_resume(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
+               led_classdev_resume(&ams_delta_leds[i].cdev);
+
+       return 0;
+}
+#else
+#define ams_delta_led_suspend NULL
+#define ams_delta_led_resume NULL
+#endif
+
+static int ams_delta_led_probe(struct platform_device *pdev)
+{
+       int i;
+       int ret;
+
+       for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) {
+               ret = led_classdev_register(&pdev->dev,
+                               &ams_delta_leds[i].cdev);
+       }
+
+       if (ret < 0 && i > 1) {
+               for (i = i - 2; i >= 0; i--)
+                       led_classdev_unregister(&ams_delta_leds[i].cdev);
+       }
+
+       return ret;
+}
+
+static int ams_delta_led_remove(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = ARRAY_SIZE(ams_delta_leds) - 1; i >= 0; i--)
+               led_classdev_unregister(&ams_delta_leds[i].cdev);
+
+       return 0;
+}
+
+static struct platform_driver ams_delta_led_driver = {
+       .probe          = ams_delta_led_probe,
+       .remove         = ams_delta_led_remove,
+       .suspend        = ams_delta_led_suspend,
+       .resume         = ams_delta_led_resume,
+       .driver         = {
+               .name = "ams-delta-led",
+       },
+};
+
+static int __init ams_delta_led_init(void)
+{
+       return platform_driver_register(&ams_delta_led_driver);
+}
+
+static void __exit ams_delta_led_exit(void)
+{
+       return platform_driver_unregister(&ams_delta_led_driver);
+}
+
+module_init(ams_delta_led_init);
+module_exit(ams_delta_led_exit);
+
+MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
+MODULE_DESCRIPTION("Amstrad Delta LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
new file mode 100644 (file)
index 0000000..713c4a8
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * LEDs driver for Soekris net48xx
+ *
+ * Copyright (C) 2006 Chris Boot <bootc@bootc.net>
+ *
+ * Based on leds-ams-delta.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/leds.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <linux/scx200_gpio.h>
+
+#define DRVNAME "net48xx-led"
+#define NET48XX_ERROR_LED_GPIO 20
+
+static struct platform_device *pdev;
+
+static void net48xx_error_led_set(struct led_classdev *led_cdev,
+               enum led_brightness value)
+{
+       if (value)
+               scx200_gpio_set_high(NET48XX_ERROR_LED_GPIO);
+       else
+               scx200_gpio_set_low(NET48XX_ERROR_LED_GPIO);
+}
+
+static struct led_classdev net48xx_error_led = {
+       .name           = "net48xx:error",
+       .brightness_set = net48xx_error_led_set,
+};
+
+#ifdef CONFIG_PM
+static int net48xx_led_suspend(struct platform_device *dev,
+               pm_message_t state)
+{
+       led_classdev_suspend(&net48xx_error_led);
+       return 0;
+}
+
+static int net48xx_led_resume(struct platform_device *dev)
+{
+       led_classdev_resume(&net48xx_error_led);
+       return 0;
+}
+#else
+#define net48xx_led_suspend NULL
+#define net48xx_led_resume NULL
+#endif
+
+static int net48xx_led_probe(struct platform_device *pdev)
+{
+       return led_classdev_register(&pdev->dev, &net48xx_error_led);
+}
+
+static int net48xx_led_remove(struct platform_device *pdev)
+{
+       led_classdev_unregister(&net48xx_error_led);
+       return 0;
+}
+
+static struct platform_driver net48xx_led_driver = {
+       .probe          = net48xx_led_probe,
+       .remove         = net48xx_led_remove,
+       .suspend        = net48xx_led_suspend,
+       .resume         = net48xx_led_resume,
+       .driver         = {
+               .name           = DRVNAME,
+               .owner          = THIS_MODULE,
+       },
+};
+
+static int __init net48xx_led_init(void)
+{
+       int ret;
+
+       if (!scx200_gpio_present()) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       ret = platform_driver_register(&net48xx_led_driver);
+       if (ret < 0)
+               goto out;
+
+       pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+       if (IS_ERR(pdev)) {
+               ret = PTR_ERR(pdev);
+               platform_driver_unregister(&net48xx_led_driver);
+               goto out;
+       }
+
+out:
+       return ret;
+}
+
+static void __exit net48xx_led_exit(void)
+{
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&net48xx_led_driver);
+}
+
+module_init(net48xx_led_init);
+module_exit(net48xx_led_exit);
+
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_DESCRIPTION("Soekris net48xx LED driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c
new file mode 100644 (file)
index 0000000..4bf8cec
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * LED Heartbeat Trigger
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * Based on Richard Purdie's ledtrig-timer.c and some arch's
+ * CONFIG_HEARTBEAT 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+struct heartbeat_trig_data {
+       unsigned int phase;
+       unsigned int period;
+       struct timer_list timer;
+};
+
+static void led_heartbeat_function(unsigned long data)
+{
+       struct led_classdev *led_cdev = (struct led_classdev *) data;
+       struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+       unsigned long brightness = LED_OFF;
+       unsigned long delay = 0;
+
+       /* acts like an actual heart beat -- ie thump-thump-pause... */
+       switch (heartbeat_data->phase) {
+       case 0:
+               /*
+                * The hyperbolic function below modifies the
+                * heartbeat period length in dependency of the
+                * current (1min) load. It goes through the points
+                * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
+                */
+               heartbeat_data->period = 300 +
+                       (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
+               heartbeat_data->period =
+                       msecs_to_jiffies(heartbeat_data->period);
+               delay = msecs_to_jiffies(70);
+               heartbeat_data->phase++;
+               brightness = LED_FULL;
+               break;
+       case 1:
+               delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
+               heartbeat_data->phase++;
+               break;
+       case 2:
+               delay = msecs_to_jiffies(70);
+               heartbeat_data->phase++;
+               brightness = LED_FULL;
+               break;
+       default:
+               delay = heartbeat_data->period - heartbeat_data->period / 4 -
+                       msecs_to_jiffies(70);
+               heartbeat_data->phase = 0;
+               break;
+       }
+
+       led_set_brightness(led_cdev, brightness);
+       mod_timer(&heartbeat_data->timer, jiffies + delay);
+}
+
+static void heartbeat_trig_activate(struct led_classdev *led_cdev)
+{
+       struct heartbeat_trig_data *heartbeat_data;
+
+       heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
+       if (!heartbeat_data)
+               return;
+
+       led_cdev->trigger_data = heartbeat_data;
+       setup_timer(&heartbeat_data->timer,
+                   led_heartbeat_function, (unsigned long) led_cdev);
+       heartbeat_data->phase = 0;
+       led_heartbeat_function(heartbeat_data->timer.data);
+}
+
+static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
+{
+       struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+
+       if (heartbeat_data) {
+               del_timer_sync(&heartbeat_data->timer);
+               kfree(heartbeat_data);
+       }
+}
+
+static struct led_trigger heartbeat_led_trigger = {
+       .name     = "heartbeat",
+       .activate = heartbeat_trig_activate,
+       .deactivate = heartbeat_trig_deactivate,
+};
+
+static int __init heartbeat_trig_init(void)
+{
+       return led_trigger_register(&heartbeat_led_trigger);
+}
+
+static void __exit heartbeat_trig_exit(void)
+{
+       led_trigger_unregister(&heartbeat_led_trigger);
+}
+
+module_init(heartbeat_trig_init);
+module_exit(heartbeat_trig_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Heartbeat LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
new file mode 100644 (file)
index 0000000..6c29fe7
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Backlight code for via-pmu
+ *
+ * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
+ * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ * Copyright (C) 2006      Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ */
+
+#include <asm/ptrace.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/backlight.h>
+#include <asm/prom.h>
+
+#define MAX_PMU_LEVEL 0xFF
+
+static struct backlight_properties pmu_backlight_data;
+static DEFINE_SPINLOCK(pmu_backlight_lock);
+static int sleeping;
+static u8 bl_curve[FB_BACKLIGHT_LEVELS];
+
+static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
+{
+       unsigned int i, flat, count, range = (max - min);
+
+       bl_curve[0] = off;
+
+       for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+               bl_curve[flat] = min;
+
+       count = FB_BACKLIGHT_LEVELS * 15 / 16;
+       for (i = 0; i < count; ++i)
+               bl_curve[flat + i] = min + (range * (i + 1) / count);
+}
+
+static int pmu_backlight_curve_lookup(int value)
+{
+       int level = (FB_BACKLIGHT_LEVELS - 1);
+       int i, max = 0;
+
+       /* Look for biggest value */
+       for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
+               max = max((int)bl_curve[i], max);
+
+       /* Look for nearest value */
+       for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
+               int diff = abs(bl_curve[i] - value);
+               if (diff < max) {
+                       max = diff;
+                       level = i;
+               }
+       }
+       return level;
+}
+
+static int pmu_backlight_get_level_brightness(int level)
+{
+       int pmulevel;
+
+       /* Get and convert the value */
+       pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
+       if (pmulevel < 0)
+               pmulevel = 0;
+       else if (pmulevel > MAX_PMU_LEVEL)
+               pmulevel = MAX_PMU_LEVEL;
+
+       return pmulevel;
+}
+
+static int pmu_backlight_update_status(struct backlight_device *bd)
+{
+       struct adb_request req;
+       unsigned long flags;
+       int level = bd->props->brightness;
+
+       spin_lock_irqsave(&pmu_backlight_lock, flags);
+
+       /* Don't update brightness when sleeping */
+       if (sleeping)
+               goto out;
+
+       if (bd->props->power != FB_BLANK_UNBLANK ||
+           bd->props->fb_blank != FB_BLANK_UNBLANK)
+               level = 0;
+
+       if (level > 0) {
+               int pmulevel = pmu_backlight_get_level_brightness(level);
+
+               pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
+               pmu_wait_complete(&req);
+
+               pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+                       PMU_POW_BACKLIGHT | PMU_POW_ON);
+               pmu_wait_complete(&req);
+       } else {
+               pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+                       PMU_POW_BACKLIGHT | PMU_POW_OFF);
+               pmu_wait_complete(&req);
+       }
+
+out:
+       spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+
+       return 0;
+}
+
+static int pmu_backlight_get_brightness(struct backlight_device *bd)
+{
+       return bd->props->brightness;
+}
+
+static struct backlight_properties pmu_backlight_data = {
+       .owner          = THIS_MODULE,
+       .get_brightness = pmu_backlight_get_brightness,
+       .update_status  = pmu_backlight_update_status,
+       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+#ifdef CONFIG_PM
+void pmu_backlight_set_sleep(int sleep)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu_backlight_lock, flags);
+       sleeping = sleep;
+       spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+}
+#endif /* CONFIG_PM */
+
+void __init pmu_backlight_init()
+{
+       struct backlight_device *bd;
+       char name[10];
+       int level, autosave;
+
+       /* Special case for the old PowerBook since I can't test on it */
+       autosave =
+               machine_is_compatible("AAPL,3400/2400") ||
+               machine_is_compatible("AAPL,3500");
+
+       if (!autosave &&
+           !pmac_has_backlight_type("pmu") &&
+           !machine_is_compatible("AAPL,PowerBook1998") &&
+           !machine_is_compatible("PowerBook1,1"))
+               return;
+
+       snprintf(name, sizeof(name), "pmubl");
+
+       bd = backlight_device_register(name, NULL, &pmu_backlight_data);
+       if (IS_ERR(bd)) {
+               printk("pmubl: Backlight registration failed\n");
+               goto error;
+       }
+       pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
+
+       level = pmu_backlight_data.max_brightness;
+
+       if (autosave) {
+               /* read autosaved value if available */
+               struct adb_request req;
+               pmu_request(&req, NULL, 2, 0xd9, 0);
+               pmu_wait_complete(&req);
+
+               level = pmu_backlight_curve_lookup(
+                               (req.reply[0] >> 4) *
+                               pmu_backlight_data.max_brightness / 15);
+       }
+
+       down(&bd->sem);
+       bd->props->brightness = level;
+       bd->props->power = FB_BLANK_UNBLANK;
+       bd->props->update_status(bd);
+       up(&bd->sem);
+
+       mutex_lock(&pmac_backlight_mutex);
+       if (!pmac_backlight)
+               pmac_backlight = bd;
+       mutex_unlock(&pmac_backlight_mutex);
+
+       printk("pmubl: Backlight initialized (%s)\n", name);
+
+       return;
+
+error:
+       return;
+}
diff --git a/drivers/macintosh/via-pmu-event.c b/drivers/macintosh/via-pmu-event.c
new file mode 100644 (file)
index 0000000..25cd565
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * via-pmu event device for reporting some events that come through the PMU
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include "via-pmu-event.h"
+
+static struct input_dev *pmu_input_dev;
+
+static int __init via_pmu_event_init(void)
+{
+       int err;
+
+       /* do other models report button/lid status? */
+       if (pmu_get_model() != PMU_KEYLARGO_BASED)
+               return -ENODEV;
+
+       pmu_input_dev = input_allocate_device();
+       if (!pmu_input_dev)
+               return -ENOMEM;
+
+       pmu_input_dev->name = "PMU";
+       pmu_input_dev->id.bustype = BUS_HOST;
+       pmu_input_dev->id.vendor = 0x0001;
+       pmu_input_dev->id.product = 0x0001;
+       pmu_input_dev->id.version = 0x0100;
+
+       set_bit(EV_KEY, pmu_input_dev->evbit);
+       set_bit(EV_SW, pmu_input_dev->evbit);
+       set_bit(KEY_POWER, pmu_input_dev->keybit);
+       set_bit(SW_LID, pmu_input_dev->swbit);
+
+       err = input_register_device(pmu_input_dev);
+       if (err)
+               input_free_device(pmu_input_dev);
+       return err;
+}
+
+void via_pmu_event(int key, int down)
+{
+
+       if (unlikely(!pmu_input_dev))
+               return;
+
+       switch (key) {
+       case PMU_EVT_POWER:
+               input_report_key(pmu_input_dev, KEY_POWER, down);
+               break;
+       case PMU_EVT_LID:
+               input_report_switch(pmu_input_dev, SW_LID, down);
+               break;
+       default:
+               /* no such key handled */
+               return;
+       }
+
+       input_sync(pmu_input_dev);
+}
+
+late_initcall(via_pmu_event_init);
diff --git a/drivers/macintosh/via-pmu-event.h b/drivers/macintosh/via-pmu-event.h
new file mode 100644 (file)
index 0000000..72c54de
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __VIA_PMU_EVENT_H
+#define __VIA_PMU_EVENT_H
+
+#define PMU_EVT_POWER  0
+#define PMU_EVT_LID    1
+extern void via_pmu_event(int key, int down);
+
+#endif /* __VIA_PMU_EVENT_H */
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
new file mode 100644 (file)
index 0000000..5189d54
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * via-pmu LED class device
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/prom.h>
+
+static spinlock_t pmu_blink_lock;
+static struct adb_request pmu_blink_req;
+/* -1: no change, 0: request off, 1: request on */
+static int requested_change;
+static int sleeping;
+
+static void pmu_req_done(struct adb_request * req)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu_blink_lock, flags);
+       /* if someone requested a change in the meantime
+        * (we only see the last one which is fine)
+        * then apply it now */
+       if (requested_change != -1 && !sleeping)
+               pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
+       /* reset requested change */
+       requested_change = -1;
+       spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness brightness)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu_blink_lock, flags);
+       switch (brightness) {
+       case LED_OFF:
+               requested_change = 0;
+               break;
+       case LED_FULL:
+               requested_change = 1;
+               break;
+       default:
+               goto out;
+               break;
+       }
+       /* if request isn't done, then don't do anything */
+       if (pmu_blink_req.complete && !sleeping)
+               pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
+ out:
+       spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static struct led_classdev pmu_led = {
+       .name = "pmu-front-led",
+#ifdef CONFIG_ADB_PMU_LED_IDE
+       .default_trigger = "ide-disk",
+#endif
+       .brightness_set = pmu_led_set,
+};
+
+#ifdef CONFIG_PM
+static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu_blink_lock, flags);
+
+       switch (when) {
+       case PBOOK_SLEEP_REQUEST:
+               sleeping = 1;
+               break;
+       case PBOOK_WAKE:
+               sleeping = 0;
+               break;
+       default:
+               /* do nothing */
+               break;
+       }
+       spin_unlock_irqrestore(&pmu_blink_lock, flags);
+
+       return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
+       .notifier_call = pmu_led_sleep_call,
+};
+#endif
+
+static int __init via_pmu_led_init(void)
+{
+       struct device_node *dt;
+       const char *model;
+
+       /* only do this on keylargo based models */
+       if (pmu_get_model() != PMU_KEYLARGO_BASED)
+               return -ENODEV;
+
+       dt = of_find_node_by_path("/");
+       if (dt == NULL)
+               return -ENODEV;
+       model = (const char *)get_property(dt, "model", NULL);
+       if (model == NULL)
+               return -ENODEV;
+       if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
+           strncmp(model, "iBook", strlen("iBook")) != 0) {
+               of_node_put(dt);
+               /* ignore */
+               return -ENODEV;
+       }
+       of_node_put(dt);
+
+       spin_lock_init(&pmu_blink_lock);
+       /* no outstanding req */
+       pmu_blink_req.complete = 1;
+       pmu_blink_req.done = pmu_req_done;
+#ifdef CONFIG_PM
+       pmu_register_sleep_notifier(&via_pmu_led_sleep_notif);
+#endif
+       return led_classdev_register(NULL, &pmu_led);
+}
+
+late_initcall(via_pmu_led_init);
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c
new file mode 100644 (file)
index 0000000..beb7c93
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/bug.h>
+#include "dvb_math.h"
+
+static const unsigned short logtable[256] = {
+       0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
+       0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
+       0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
+       0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
+       0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
+       0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
+       0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
+       0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
+       0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
+       0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
+       0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
+       0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
+       0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
+       0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
+       0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
+       0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
+       0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
+       0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
+       0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
+       0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
+       0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
+       0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
+       0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
+       0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
+       0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
+       0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
+       0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
+       0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
+       0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
+       0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
+       0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
+       0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
+};
+
+unsigned int intlog2(u32 value)
+{
+       /**
+        *      returns: log2(value) * 2^24
+        *      wrong result if value = 0 (log2(0) is undefined)
+        */
+       unsigned int msb;
+       unsigned int logentry;
+       unsigned int significand;
+       unsigned int interpolation;
+
+       if (unlikely(value == 0)) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       /* first detect the msb (count begins at 0) */
+       msb = fls(value) - 1;
+
+       /**
+        *      now we use a logtable after the following method:
+        *
+        *      log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
+        *      where x = msb and therefore 1 <= y < 2
+        *      first y is determined by shifting the value left
+        *      so that msb is bit 31
+        *              0x00231f56 -> 0x8C7D5800
+        *      the result is y * 2^31 -> "significand"
+        *      then the highest 9 bits are used for a table lookup
+        *      the highest bit is discarded because it's always set
+        *      the highest nine bits in our example are 100011000
+        *      so we would use the entry 0x18
+        */
+       significand = value << (31 - msb);
+       logentry = (significand >> 23) & 0xff;
+
+       /**
+        *      last step we do is interpolation because of the
+        *      limitations of the log table the error is that part of
+        *      the significand which isn't used for lookup then we
+        *      compute the ratio between the error and the next table entry
+        *      and interpolate it between the log table entry used and the
+        *      next one the biggest error possible is 0x7fffff
+        *      (in our example it's 0x7D5800)
+        *      needed value for next table entry is 0x800000
+        *      so the interpolation is
+        *      (error / 0x800000) * (logtable_next - logtable_current)
+        *      in the implementation the division is moved to the end for
+        *      better accuracy there is also an overflow correction if
+        *      logtable_next is 256
+        */
+       interpolation = ((significand & 0x7fffff) *
+                       ((logtable[(logentry + 1) & 0xff] -
+                         logtable[logentry]) & 0xffff)) >> 15;
+
+       /* now we return the result */
+       return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
+}
+EXPORT_SYMBOL(intlog2);
+
+unsigned int intlog10(u32 value)
+{
+       /**
+        *      returns: log10(value) * 2^24
+        *      wrong result if value = 0 (log10(0) is undefined)
+        */
+       u64 log;
+
+       if (unlikely(value == 0)) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       log = intlog2(value);
+
+       /**
+        *      we use the following method:
+        *      log10(x) = log2(x) * log10(2)
+        */
+
+       return (log * 646456993) >> 31;
+}
+EXPORT_SYMBOL(intlog10);
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h
new file mode 100644 (file)
index 0000000..aecc867
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DVB_MATH_H
+#define __DVB_MATH_H
+
+#include <linux/types.h>
+
+/**
+ * computes log2 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog2(value) = intlog2(value * 2^x) - x * 2^24
+ *
+ * example: intlog2(8) will give 3 << 24 = 3 * 2^24
+ * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
+ * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
+ *
+ * @param value The value (must be != 0)
+ * @return log2(value) * 2^24
+ */
+extern unsigned int intlog2(u32 value);
+
+/**
+ * computes log10 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog10(value) = intlog10(value * 10^x) - x * 2^24
+ *
+ * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
+ *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24
+ *
+ * look at intlog2 for similar examples
+ *
+ * @param value The value (must be != 0)
+ * @return log10(value) * 2^24
+ */
+extern unsigned int intlog10(u32 value);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
new file mode 100644 (file)
index 0000000..6ccbdc9
--- /dev/null
@@ -0,0 +1,272 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *     This program is free software; 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
+ */
+#include "gp8psk.h"
+
+struct gp8psk_fe_state {
+       struct dvb_frontend fe;
+
+       struct dvb_usb_device *d;
+
+       u16 snr;
+
+       unsigned long next_snr_check;
+};
+
+static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+       u8 lock;
+
+       if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
+               return -EINVAL;
+
+       if (lock)
+               *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+       else
+               *status = 0;
+
+       return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+       (void) fe;
+       *ber = 0;
+       return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+       (void) fe;
+       *unc = 0;
+       return 0;
+}
+
+static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+       u8 buf[2];
+
+       if (time_after(jiffies,st->next_snr_check)) {
+               gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
+               *snr = (int)(buf[1]) << 8 | buf[0];
+               /* snr is reported in dBu*256 */
+               /* snr / 38.4 ~= 100% strength */
+               /* snr * 17 returns 100% strength as 65535 */
+               if (*snr <= 3855)
+                       *snr = (*snr<<4) + *snr; // snr * 17
+               else
+                       *snr = 65535;
+               st->next_snr_check = jiffies + (10*HZ)/1000;
+       } else {
+               *snr = st->snr;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+       return gp8psk_fe_read_snr(fe, strength);
+}
+
+static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 800;
+       return 0;
+}
+
+static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       struct gp8psk_fe_state *state = fe->demodulator_priv;
+       u8 cmd[10];
+       u32 freq = fep->frequency * 1000;
+
+       cmd[4] = freq         & 0xff;
+       cmd[5] = (freq >> 8)  & 0xff;
+       cmd[6] = (freq >> 16) & 0xff;
+       cmd[7] = (freq >> 24) & 0xff;
+
+       switch(fe->ops.info.type) {
+       case FE_QPSK:
+               cmd[0] =  fep->u.qpsk.symbol_rate        & 0xff;
+               cmd[1] = (fep->u.qpsk.symbol_rate >>  8) & 0xff;
+               cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
+               cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
+               cmd[8] = ADV_MOD_DVB_QPSK;
+               cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
+               break;
+       default:
+               // other modes are unsuported right now
+               cmd[0] = 0;
+               cmd[1] = 0;
+               cmd[2] = 0;
+               cmd[3] = 0;
+               cmd[8] = 0;
+               cmd[9] = 0;
+               break;
+       }
+
+       gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
+
+       state->next_snr_check = jiffies;
+
+       return 0;
+}
+
+static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       return 0;
+}
+
+
+static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+                                   struct dvb_diseqc_master_cmd *m)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+       deb_fe("%s\n",__FUNCTION__);
+
+       if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+                       m->msg, m->msg_len)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+                                   fe_sec_mini_cmd_t burst)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+       u8 cmd;
+
+       deb_fe("%s\n",__FUNCTION__);
+
+       /* These commands are certainly wrong */
+       cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+
+       if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
+                       &cmd, 0)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+       struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+       if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
+                (tone == SEC_TONE_ON), 0, NULL, 0)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+       struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+       if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
+                        voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
+{
+       struct gp8psk_fe_state* state = fe->demodulator_priv;
+       u8 cmd = sw_cmd & 0x7f;
+
+       if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
+                       NULL, 0)) {
+               return -EINVAL;
+       }
+       if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
+                       0, NULL, 0)) {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void gp8psk_fe_release(struct dvb_frontend* fe)
+{
+       struct gp8psk_fe_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops gp8psk_fe_ops;
+
+struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
+{
+       struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
+       if (s == NULL)
+               goto error;
+
+       s->d = d;
+       memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
+       s->fe.demodulator_priv = s;
+
+       goto success;
+error:
+       return NULL;
+success:
+       return &s->fe;
+}
+
+
+static struct dvb_frontend_ops gp8psk_fe_ops = {
+       .info = {
+               .name                   = "Genpix 8psk-USB DVB-S",
+               .type                   = FE_QPSK,
+               .frequency_min          = 950000,
+               .frequency_max          = 2150000,
+               .frequency_stepsize     = 100,
+               .symbol_rate_min        = 1000000,
+               .symbol_rate_max        = 45000000,
+               .symbol_rate_tolerance  = 500,  /* ppm */
+               .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
+       },
+
+       .release = gp8psk_fe_release,
+
+       .init = NULL,
+       .sleep = NULL,
+
+       .set_frontend = gp8psk_fe_set_frontend,
+       .get_frontend = gp8psk_fe_get_frontend,
+       .get_tune_settings = gp8psk_fe_get_tune_settings,
+
+       .read_status = gp8psk_fe_read_status,
+       .read_ber = gp8psk_fe_read_ber,
+       .read_signal_strength = gp8psk_fe_read_signal_strength,
+       .read_snr = gp8psk_fe_read_snr,
+       .read_ucblocks = gp8psk_fe_read_unc_blocks,
+
+       .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
+       .diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
+       .set_tone = gp8psk_fe_set_tone,
+       .set_voltage = gp8psk_fe_set_voltage,
+       .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
+};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
new file mode 100644 (file)
index 0000000..9a98f3f
--- /dev/null
@@ -0,0 +1,256 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *     This program is free software; 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
+ */
+#include "gp8psk.h"
+
+/* debug */
+static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
+int dvb_usb_gp8psk_debug;
+module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+       int ret = 0,try = 0;
+
+       if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+               return ret;
+
+       while (ret >= 0 && ret != blen && try < 3) {
+               ret = usb_control_msg(d->udev,
+                       usb_rcvctrlpipe(d->udev,0),
+                       req,
+                       USB_TYPE_VENDOR | USB_DIR_IN,
+                       value,index,b,blen,
+                       2000);
+               deb_info("reading number %d (ret: %d)\n",try,ret);
+               try++;
+       }
+
+       if (ret < 0 || ret != blen) {
+               warn("usb in operation failed.");
+               ret = -EIO;
+       } else
+               ret = 0;
+
+       deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+       debug_dump(b,blen,deb_xfer);
+
+       mutex_unlock(&d->usb_mutex);
+
+       return ret;
+}
+
+int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+                            u16 index, u8 *b, int blen)
+{
+       int ret;
+
+       deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+       debug_dump(b,blen,deb_xfer);
+
+       if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+               return ret;
+
+       if (usb_control_msg(d->udev,
+                       usb_sndctrlpipe(d->udev,0),
+                       req,
+                       USB_TYPE_VENDOR | USB_DIR_OUT,
+                       value,index,b,blen,
+                       2000) != blen) {
+               warn("usb out operation failed.");
+               ret = -EIO;
+       } else
+               ret = 0;
+       mutex_unlock(&d->usb_mutex);
+
+       return ret;
+}
+
+static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
+{
+       int ret;
+       const struct firmware *fw = NULL;
+       u8 *ptr, *buf;
+       if ((ret = request_firmware(&fw, bcm4500_firmware,
+                                       &d->udev->dev)) != 0) {
+               err("did not find the bcm4500 firmware file. (%s) "
+                       "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+                       bcm4500_firmware,ret);
+               return ret;
+       }
+
+       ret = -EINVAL;
+
+       if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
+               goto out_rel_fw;
+
+       info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
+
+       ptr = fw->data;
+       buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
+
+       while (ptr[0] != 0xff) {
+               u16 buflen = ptr[0] + 4;
+               if (ptr + buflen >= fw->data + fw->size) {
+                       err("failed to load bcm4500 firmware.");
+                       goto out_free;
+               }
+               memcpy(buf, ptr, buflen);
+               if (dvb_usb_generic_write(d, buf, buflen)) {
+                       err("failed to load bcm4500 firmware.");
+                       goto out_free;
+               }
+               ptr += buflen;
+       }
+
+       ret = 0;
+
+out_free:
+       kfree(buf);
+out_rel_fw:
+       release_firmware(fw);
+
+       return ret;
+}
+
+static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       u8 status, buf;
+       if (onoff) {
+               gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+               if (! (status & 0x01))  /* started */
+                       if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+                               return -EINVAL;
+
+               if (! (status & 0x02)) /* BCM4500 firmware loaded */
+                       if(gp8psk_load_bcm4500fw(d))
+                               return EINVAL;
+
+               if (! (status & 0x04)) /* LNB Power */
+                       if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
+                                       &buf, 1))
+                               return EINVAL;
+
+               /* Set DVB mode */
+               if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
+                       return -EINVAL;
+               gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+       } else {
+               /* Turn off LNB power */
+               if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
+                       return EINVAL;
+               /* Turn off 8psk power */
+               if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+                       return -EINVAL;
+
+       }
+       return 0;
+}
+
+
+static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
+}
+
+static int gp8psk_frontend_attach(struct dvb_usb_device *d)
+{
+       d->fe = gp8psk_fe_attach(d);
+
+       return 0;
+}
+
+static struct dvb_usb_properties gp8psk_properties;
+
+static int gp8psk_usb_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id gp8psk_usb_table [] = {
+           { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
+           { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
+           { 0 },
+};
+MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
+
+static struct dvb_usb_properties gp8psk_properties = {
+       .caps = 0,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-gp8psk-01.fw",
+
+       .streaming_ctrl   = gp8psk_streaming_ctrl,
+       .power_ctrl       = gp8psk_power_ctrl,
+       .frontend_attach  = gp8psk_frontend_attach,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_BULK,
+               .count = 7,
+               .endpoint = 0x82,
+               .u = {
+                       .bulk = {
+                               .buffersize = 8192,
+                       }
+               }
+       },
+
+       .num_device_descs = 1,
+       .devices = {
+               { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
+                 .cold_ids = { &gp8psk_usb_table[0], NULL },
+                 .warm_ids = { &gp8psk_usb_table[1], NULL },
+               },
+               { 0 },
+       }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gp8psk_usb_driver = {
+       .name           = "dvb_usb_gp8psk",
+       .probe          = gp8psk_usb_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table       = gp8psk_usb_table,
+};
+
+/* module stuff */
+static int __init gp8psk_usb_module_init(void)
+{
+       int result;
+       if ((result = usb_register(&gp8psk_usb_driver))) {
+               err("usb_register failed. (%d)",result);
+               return result;
+       }
+
+       return 0;
+}
+
+static void __exit gp8psk_usb_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&gp8psk_usb_driver);
+}
+
+module_init(gp8psk_usb_module_init);
+module_exit(gp8psk_usb_module_exit);
+
+MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
+MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
new file mode 100644 (file)
index 0000000..3eba706
--- /dev/null
@@ -0,0 +1,79 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *     This program is free software; 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 _DVB_USB_GP8PSK_H_
+#define _DVB_USB_GP8PSK_H_
+
+#define DVB_USB_LOG_PREFIX "gp8psk"
+#include "dvb-usb.h"
+
+extern int dvb_usb_gp8psk_debug;
+#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
+#define deb_rc(args...)   dprintk(dvb_usb_gp8psk_debug,0x04,args)
+#define deb_fe(args...)   dprintk(dvb_usb_gp8psk_debug,0x08,args)
+/* gp8psk commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN                     0xC0
+#define TH_COMMAND_OUT                    0xC1
+
+/* command bytes */
+#define GET_8PSK_CONFIG                 0x80
+#define SET_8PSK_CONFIG                 0x81
+#define ARM_TRANSFER                    0x85
+#define TUNE_8PSK                       0x86
+#define GET_SIGNAL_STRENGTH             0x87
+#define LOAD_BCM4500                    0x88
+#define BOOT_8PSK                       0x89
+#define START_INTERSIL                  0x8A
+#define SET_LNB_VOLTAGE                 0x8B
+#define SET_22KHZ_TONE                  0x8C
+#define SEND_DISEQC_COMMAND             0x8D
+#define SET_DVB_MODE                    0x8E
+#define SET_DN_SWITCH                   0x8F
+#define GET_SIGNAL_LOCK                 0x90
+
+/* Satellite modulation modes */
+#define ADV_MOD_DVB_QPSK 0     /* DVB-S QPSK */
+#define ADV_MOD_TURBO_QPSK 1   /* Turbo QPSK */
+#define ADV_MOD_TURBO_8PSK 2   /* Turbo 8PSK (also used for Trellis 8PSK) */
+#define ADV_MOD_TURBO_16QAM 3  /* Turbo 16QAM (also used for Trellis 8PSK) */
+
+#define ADV_MOD_DCII_C_QPSK 4  /* Digicipher II Combo */
+#define ADV_MOD_DCII_I_QPSK 5  /* Digicipher II I-stream */
+#define ADV_MOD_DCII_Q_QPSK 6  /* Digicipher II Q-stream */
+#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
+#define ADV_MOD_DSS_QPSK 8     /* DSS (DIRECTV) QPSK */
+#define ADV_MOD_DVB_BPSK 9     /* DVB-S BPSK */
+
+#define GET_USB_SPEED                     0x07
+ #define USB_SPEED_LOW                    0
+ #define USB_SPEED_FULL                   1
+ #define USB_SPEED_HIGH                   2
+
+#define RESET_FX2                         0x13
+
+#define FW_VERSION_READ                   0x0B
+#define VENDOR_STRING_READ                0x0C
+#define PRODUCT_STRING_READ               0x0D
+#define FW_BCD_VERSION_READ               0x14
+
+extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
+extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+                            u16 index, u8 *b, int blen);
+
+#endif
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
new file mode 100644 (file)
index 0000000..58c34db
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6421.h"
+
+struct isl6421 {
+       u8                      config;
+       u8                      override_or;
+       u8                      override_and;
+       struct i2c_adapter      *i2c;
+       u8                      i2c_addr;
+       void                    (*release_chain)(struct dvb_frontend* fe);
+};
+
+static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
+                               .buf = &isl6421->config,
+                               .len = sizeof(isl6421->config) };
+
+       isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
+
+       switch(voltage) {
+       case SEC_VOLTAGE_OFF:
+               break;
+       case SEC_VOLTAGE_13:
+               isl6421->config |= ISL6421_EN1;
+               break;
+       case SEC_VOLTAGE_18:
+               isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       isl6421->config |= isl6421->override_or;
+       isl6421->config &= isl6421->override_and;
+
+       return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
+                               .buf = &isl6421->config,
+                               .len = sizeof(isl6421->config) };
+
+       if (arg)
+               isl6421->config |= ISL6421_LLC1;
+       else
+               isl6421->config &= ~ISL6421_LLC1;
+
+       isl6421->config |= isl6421->override_or;
+       isl6421->config &= isl6421->override_and;
+
+       return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6421_release(struct dvb_frontend *fe)
+{
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+
+       /* power off */
+       isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+       /* free data & call next release routine */
+       fe->ops.release = isl6421->release_chain;
+       kfree(fe->misc_priv);
+       fe->misc_priv = NULL;
+       if (fe->ops.release)
+               fe->ops.release(fe);
+}
+
+int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+                  u8 override_set, u8 override_clear)
+{
+       struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
+       if (!isl6421)
+               return -ENOMEM;
+
+       /* default configuration */
+       isl6421->config = ISL6421_ISEL1;
+       isl6421->i2c = i2c;
+       isl6421->i2c_addr = i2c_addr;
+       fe->misc_priv = isl6421;
+
+       /* bits which should be forced to '1' */
+       isl6421->override_or = override_set;
+
+       /* bits which should be forced to '0' */
+       isl6421->override_and = ~override_clear;
+
+       /* detect if it is present or not */
+       if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+               kfree(isl6421);
+               fe->misc_priv = NULL;
+               return -EIO;
+       }
+
+       /* install release callback */
+       isl6421->release_chain = fe->ops.release;
+       fe->ops.release = isl6421_release;
+
+       /* override frontend ops */
+       fe->ops.set_voltage = isl6421_set_voltage;
+       fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+
+       return 0;
+}
+EXPORT_SYMBOL(isl6421_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
+MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
new file mode 100644 (file)
index 0000000..675f80a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 _ISL6421_H
+#define _ISL6421_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+#define ISL6421_OLF1   0x01
+#define ISL6421_EN1    0x02
+#define ISL6421_VSEL1  0x04
+#define ISL6421_LLC1   0x08
+#define ISL6421_ENT1   0x10
+#define ISL6421_ISEL1  0x20
+#define ISL6421_DCL    0x40
+
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+                         u8 override_set, u8 override_clear);
+
+#endif
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h
new file mode 100644 (file)
index 0000000..754d51d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 _LG_H06XF_H_
+#define _LG_H06XF_H_
+#include "dvb-pll.h"
+
+static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
+                    struct dvb_frontend_parameters* params)
+{
+       u8 buf[4];
+       struct i2c_msg msg = { .addr = 0x61, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+       int err;
+
+       dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lg_h06xf: %s error "
+                       "(addr %02x <- %02x, err = %i)\n",
+                       __FUNCTION__, buf[0], buf[1], err);
+               if (err < 0)
+                       return err;
+               else
+                       return -EREMOTEIO;
+       }
+
+       /* Set the Auxiliary Byte. */
+       buf[0] = buf[2];
+       buf[0] &= ~0x20;
+       buf[0] |= 0x18;
+       buf[1] = 0x50;
+       msg.len = 2;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lg_h06xf: %s error "
+                       "(addr %02x <- %02x, err = %i)\n",
+                       __FUNCTION__, buf[0], buf[1], err);
+               if (err < 0)
+                       return err;
+               else
+                       return -EREMOTEIO;
+       }
+
+       return 0;
+}
+#endif
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
new file mode 100644 (file)
index 0000000..e933edc
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * lnbp21.h - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp21.h"
+
+struct lnbp21 {
+       u8                      config;
+       u8                      override_or;
+       u8                      override_and;
+       struct i2c_adapter      *i2c;
+       void                    (*release_chain)(struct dvb_frontend* fe);
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
+                               .buf = &lnbp21->config,
+                               .len = sizeof(lnbp21->config) };
+
+       lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
+
+       switch(voltage) {
+       case SEC_VOLTAGE_OFF:
+               break;
+       case SEC_VOLTAGE_13:
+               lnbp21->config |= LNBP21_EN;
+               break;
+       case SEC_VOLTAGE_18:
+               lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       lnbp21->config |= lnbp21->override_or;
+       lnbp21->config &= lnbp21->override_and;
+
+       return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
+                               .buf = &lnbp21->config,
+                               .len = sizeof(lnbp21->config) };
+
+       if (arg)
+               lnbp21->config |= LNBP21_LLC;
+       else
+               lnbp21->config &= ~LNBP21_LLC;
+
+       lnbp21->config |= lnbp21->override_or;
+       lnbp21->config &= lnbp21->override_and;
+
+       return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp21_release(struct dvb_frontend *fe)
+{
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+
+       /* LNBP power off */
+       lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+       /* free data & call next release routine */
+       fe->ops.release = lnbp21->release_chain;
+       kfree(fe->misc_priv);
+       fe->misc_priv = NULL;
+       if (fe->ops.release)
+               fe->ops.release(fe);
+}
+
+int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+       struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
+       if (!lnbp21)
+               return -ENOMEM;
+
+       /* default configuration */
+       lnbp21->config = LNBP21_ISEL;
+       lnbp21->i2c = i2c;
+       fe->misc_priv = lnbp21;
+
+       /* bits which should be forced to '1' */
+       lnbp21->override_or = override_set;
+
+       /* bits which should be forced to '0' */
+       lnbp21->override_and = ~override_clear;
+
+       /* detect if it is present or not */
+       if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+               kfree(lnbp21);
+               fe->misc_priv = NULL;
+               return -EIO;
+       }
+
+       /* install release callback */
+       lnbp21->release_chain = fe->ops.release;
+       fe->ops.release = lnbp21_release;
+
+       /* override frontend ops */
+       fe->ops.set_voltage = lnbp21_set_voltage;
+       fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+
+       return 0;
+}
+EXPORT_SYMBOL(lnbp21_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
+MODULE_AUTHOR("Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
new file mode 100644 (file)
index 0000000..f7e33f9
--- /dev/null
@@ -0,0 +1,430 @@
+/* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
+ into both the USB and an analog audio input, so this thing
+ only deals with initialisation and frequency setting, the
+ audio data has to be handled by a sound driver.
+
+ Major issue: I can't find out where the device reports the signal
+ strength, and indeed the windows software appearantly just looks
+ at the stereo indicator as well.  So, scanning will only find
+ stereo stations.  Sad, but I can't help it.
+
+ Also, the windows program sends oodles of messages over to the
+ device, and I couldn't figure out their meaning.  My suspicion
+ is that they don't have any:-)
+
+ You might find some interesting stuff about this module at
+ http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
+
+ Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.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
+
+ History:
+
+ Version 0.40:
+  Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
+
+ Version 0.30:
+       Markus: Updates for 2.5.x kernel and more ISO compliant source
+
+ Version 0.25:
+       PSL and Markus: Cleanup, radio now doesn't stop on device close
+
+ Version 0.24:
+       Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
+       right.  Some minor cleanup, improved standalone compilation
+
+ Version 0.23:
+       Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
+
+ Version 0.22:
+       Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
+       thanks to Mike Cox for pointing the problem out.
+
+ Version 0.21:
+       Markus: Minor cleanup, warnings if something goes wrong, lame attempt
+       to adhere to Documentation/CodingStyle
+
+ Version 0.2:
+       Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
+       Markus: Copyright clarification
+
+ Version 0.01: Markus: initial release
+
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.40"
+#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
+#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
+
+#define DSB100_VENDOR 0x04b4
+#define DSB100_PRODUCT 0x1002
+
+/* Commands the device appears to understand */
+#define DSB100_TUNE 1
+#define DSB100_ONOFF 2
+
+#define TB_LEN 16
+
+/* 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
+
+
+static int usb_dsbr100_probe(struct usb_interface *intf,
+                            const struct usb_device_id *id);
+static void usb_dsbr100_disconnect(struct usb_interface *intf);
+static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg);
+static int usb_dsbr100_open(struct inode *inode, struct file *file);
+static int usb_dsbr100_close(struct inode *inode, struct file *file);
+
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+
+/* Data for one (physical) device */
+typedef struct {
+       struct usb_device *usbdev;
+       struct video_device *videodev;
+       unsigned char transfer_buffer[TB_LEN];
+       int curfreq;
+       int stereo;
+       int users;
+       int removed;
+} dsbr100_device;
+
+
+/* File system interface */
+static struct file_operations usb_dsbr100_fops = {
+       .owner =        THIS_MODULE,
+       .open =         usb_dsbr100_open,
+       .release =      usb_dsbr100_close,
+       .ioctl =        usb_dsbr100_ioctl,
+       .compat_ioctl = v4l_compat_ioctl32,
+       .llseek =       no_llseek,
+};
+
+/* V4L interface */
+static struct video_device dsbr100_videodev_template=
+{
+       .owner =        THIS_MODULE,
+       .name =         "D-Link DSB-R 100",
+       .type =         VID_TYPE_TUNER,
+       .hardware =     VID_HARDWARE_AZTECH,
+       .fops =         &usb_dsbr100_fops,
+       .release = video_device_release,
+};
+
+static struct usb_device_id usb_dsbr100_device_table [] = {
+       { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
+       { }                                             /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
+
+/* USB subsystem interface */
+static struct usb_driver usb_dsbr100_driver = {
+       .name =         "dsbr100",
+       .probe =        usb_dsbr100_probe,
+       .disconnect =   usb_dsbr100_disconnect,
+       .id_table =     usb_dsbr100_device_table,
+};
+
+/* Low-level device interface begins here */
+
+/* switch on radio */
+static int dsbr100_start(dsbr100_device *radio)
+{
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
+       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       DSB100_ONOFF,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
+               return -1;
+       return (radio->transfer_buffer)[0];
+}
+
+
+/* switch off radio */
+static int dsbr100_stop(dsbr100_device *radio)
+{
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
+       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       DSB100_ONOFF,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
+               return -1;
+       return (radio->transfer_buffer)[0];
+}
+
+/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static int dsbr100_setfreq(dsbr100_device *radio, int freq)
+{
+       freq = (freq/16*80)/1000+856;
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       DSB100_TUNE,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       (freq>>8)&0x00ff, freq&0xff,
+                       radio->transfer_buffer, 8, 300)<0 ||
+          usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+                       0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
+       usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
+                       0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
+               radio->stereo = -1;
+               return -1;
+       }
+       radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
+       return (radio->transfer_buffer)[0];
+}
+
+/* return the device status.  This is, in effect, just whether it
+sees a stereo signal or not.  Pity. */
+static void dsbr100_getstat(dsbr100_device *radio)
+{
+       if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+               USB_REQ_GET_STATUS,
+               USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+               0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
+               radio->stereo = -1;
+       else
+               radio->stereo = ! (radio->transfer_buffer[0]&0x01);
+}
+
+
+/* USB subsystem interface begins here */
+
+/* check if the device is present and register with v4l and
+usb if it is */
+static int usb_dsbr100_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       dsbr100_device *radio;
+
+       if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL)))
+               return -ENOMEM;
+       if (!(radio->videodev = video_device_alloc())) {
+               kfree(radio);
+               return -ENOMEM;
+       }
+       memcpy(radio->videodev, &dsbr100_videodev_template,
+               sizeof(dsbr100_videodev_template));
+       radio->removed = 0;
+       radio->users = 0;
+       radio->usbdev = interface_to_usbdev(intf);
+       radio->curfreq = FREQ_MIN*FREQ_MUL;
+       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);
+               return -EIO;
+       }
+       usb_set_intfdata(intf, radio);
+       return 0;
+}
+
+/* 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.  stv680.c does not relase its private
+data, so I don't do this here either.  Checking out the
+code I'd expect I better did that, but if there's a memory
+leak here it's tiny (~50 bytes per disconnect) */
+static void usb_dsbr100_disconnect(struct usb_interface *intf)
+{
+       dsbr100_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);
+               } else {
+                       radio->removed = 1;
+               }
+       }
+}
+
+
+/* Video for Linux interface */
+
+static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, void *arg)
+{
+       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+
+       if (!radio)
+               return -EIO;
+
+       switch(cmd) {
+               case VIDIOCGCAP: {
+                       struct video_capability *v = arg;
+
+                       memset(v, 0, sizeof(*v));
+                       v->type = VID_TYPE_TUNER;
+                       v->channels = 1;
+                       v->audios = 1;
+                       strcpy(v->name, "D-Link R-100 USB FM Radio");
+                       return 0;
+               }
+               case VIDIOCGTUNER: {
+                       struct video_tuner *v = arg;
+
+                       dsbr100_getstat(radio);
+                       if(v->tuner)    /* Only 1 tuner */
+                               return -EINVAL;
+                       v->rangelow = FREQ_MIN*FREQ_MUL;
+                       v->rangehigh = FREQ_MAX*FREQ_MUL;
+                       v->flags = VIDEO_TUNER_LOW;
+                       v->mode = VIDEO_MODE_AUTO;
+                       v->signal = radio->stereo*0x7000;
+                               /* Don't know how to get signal strength */
+                       v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;
+                       strcpy(v->name, "DSB R-100");
+                       return 0;
+               }
+               case VIDIOCSTUNER: {
+                       struct video_tuner *v = arg;
+
+                       if(v->tuner!=0)
+                               return -EINVAL;
+                       /* Only 1 tuner so no setting needed ! */
+                       return 0;
+               }
+               case VIDIOCGFREQ: {
+                       int *freq = arg;
+
+                       if (radio->curfreq==-1)
+                               return -EINVAL;
+                       *freq = radio->curfreq;
+                       return 0;
+               }
+               case VIDIOCSFREQ: {
+                       int *freq = arg;
+
+                       radio->curfreq = *freq;
+                       if (dsbr100_setfreq(radio, radio->curfreq)==-1)
+                               warn("Set frequency failed");
+                       return 0;
+               }
+               case VIDIOCGAUDIO: {
+                       struct video_audio *v = arg;
+
+                       memset(v, 0, sizeof(*v));
+                       v->flags |= VIDEO_AUDIO_MUTABLE;
+                       v->mode = VIDEO_SOUND_STEREO;
+                       v->volume = 1;
+                       v->step = 1;
+                       strcpy(v->name, "Radio");
+                       return 0;
+               }
+               case VIDIOCSAUDIO: {
+                       struct video_audio *v = arg;
+
+                       if (v->audio)
+                               return -EINVAL;
+                       if (v->flags&VIDEO_AUDIO_MUTE) {
+                               if (dsbr100_stop(radio)==-1)
+                                       warn("Radio did not respond properly");
+                       }
+                       else
+                               if (dsbr100_start(radio)==-1)
+                                       warn("Radio did not respond properly");
+                       return 0;
+               }
+               default:
+                       return -ENOIOCTLCMD;
+       }
+}
+
+static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
+                            unsigned int cmd, unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
+}
+
+static int usb_dsbr100_open(struct inode *inode, struct file *file)
+{
+       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+
+       radio->users = 1;
+       if (dsbr100_start(radio)<0) {
+               warn("Radio did not start up properly");
+               radio->users = 0;
+               return -EIO;
+       }
+       dsbr100_setfreq(radio, radio->curfreq);
+       return 0;
+}
+
+static int usb_dsbr100_close(struct inode *inode, struct file *file)
+{
+       dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+
+       if (!radio)
+               return -ENODEV;
+       radio->users = 0;
+       if (radio->removed) {
+               kfree(radio);
+       }
+       return 0;
+}
+
+static int __init dsbr100_init(void)
+{
+       int retval = usb_register(&usb_dsbr100_driver);
+       info(DRIVER_VERSION ":" DRIVER_DESC);
+       return retval;
+}
+
+static void __exit dsbr100_exit(void)
+{
+       usb_deregister(&usb_dsbr100_driver);
+}
+
+module_init (dsbr100_init);
+module_exit (dsbr100_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
new file mode 100644 (file)
index 0000000..05e42bb
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+    bt866 - BT866 Digital Video Encoder (Rockwell Part)
+
+    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Modifications for LML33/DC10plus unified driver
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+
+    This code was modify/ported from the saa7111 driver written
+    by Dave Perks.
+
+    This code was adapted for the bt866 by Christer Weinigel and ported
+    to 2.6 by Martin Samuelsson.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU 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/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+#include <linux/videodev.h>
+#include <asm/uaccess.h>
+
+#include <linux/video_encoder.h>
+
+MODULE_LICENSE("GPL");
+
+#define        BT866_DEVNAME   "bt866"
+#define I2C_BT866      0x88
+
+MODULE_LICENSE("GPL");
+
+#define DEBUG(x)               /* Debug driver */
+
+/* ----------------------------------------------------------------------- */
+
+struct bt866 {
+       struct i2c_client *i2c;
+       int addr;
+       unsigned char reg[128];
+
+       int norm;
+       int enable;
+       int bright;
+       int contrast;
+       int hue;
+       int sat;
+};
+
+static int bt866_write(struct bt866 *dev,
+                       unsigned char subaddr, unsigned char data);
+
+static int bt866_do_command(struct bt866 *encoder,
+                       unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case ENCODER_GET_CAPABILITIES:
+       {
+               struct video_encoder_capability *cap = arg;
+
+               DEBUG(printk
+                     (KERN_INFO "%s: get capabilities\n",
+                      encoder->i2c->name));
+
+               cap->flags
+                       = VIDEO_ENCODER_PAL
+                       | VIDEO_ENCODER_NTSC
+                       | VIDEO_ENCODER_CCIR;
+               cap->inputs = 2;
+               cap->outputs = 1;
+       }
+       break;
+
+       case ENCODER_SET_NORM:
+       {
+               int *iarg = arg;
+
+               DEBUG(printk(KERN_INFO "%s: set norm %d\n",
+                            encoder->i2c->name, *iarg));
+
+               switch (*iarg) {
+
+               case VIDEO_MODE_NTSC:
+                       break;
+
+               case VIDEO_MODE_PAL:
+                       break;
+
+               default:
+                       return -EINVAL;
+
+               }
+               encoder->norm = *iarg;
+       }
+       break;
+
+       case ENCODER_SET_INPUT:
+       {
+               int *iarg = arg;
+               static const __u8 init[] = {
+                       0xc8, 0xcc, /* CRSCALE */
+                       0xca, 0x91, /* CBSCALE */
+                       0xcc, 0x24, /* YC16 | OSDNUM */
+                       0xda, 0x00, /*  */
+                       0xdc, 0x24, /* SETMODE | PAL */
+                       0xde, 0x02, /* EACTIVE */
+
+                       /* overlay colors */
+                       0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
+                       0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
+                       0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
+                       0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
+                       0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
+                       0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
+                       0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
+                       0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
+
+                       0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
+                       0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
+                       0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
+                       0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
+                       0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
+                       0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
+                       0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
+                       0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
+               };
+               int i;
+               u8 val;
+
+               for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
+                       bt866_write(encoder, init[i], init[i+1]);
+
+               val = encoder->reg[0xdc];
+
+               if (*iarg == 0)
+                       val |= 0x40; /* CBSWAP */
+               else
+                       val &= ~0x40; /* !CBSWAP */
+
+               bt866_write(encoder, 0xdc, val);
+
+               val = encoder->reg[0xcc];
+               if (*iarg == 2)
+                       val |= 0x01; /* OSDBAR */
+               else
+                       val &= ~0x01; /* !OSDBAR */
+               bt866_write(encoder, 0xcc, val);
+
+               DEBUG(printk(KERN_INFO "%s: set input %d\n",
+                            encoder->i2c->name, *iarg));
+
+               switch (*iarg) {
+               case 0:
+                       break;
+               case 1:
+                       break;
+               default:
+                       return -EINVAL;
+
+               }
+       }
+       break;
+
+       case ENCODER_SET_OUTPUT:
+       {
+               int *iarg = arg;
+
+               DEBUG(printk(KERN_INFO "%s: set output %d\n",
+                            encoder->i2c->name, *iarg));
+
+               /* not much choice of outputs */
+               if (*iarg != 0)
+                       return -EINVAL;
+       }
+       break;
+
+       case ENCODER_ENABLE_OUTPUT:
+       {
+               int *iarg = arg;
+               encoder->enable = !!*iarg;
+
+               DEBUG(printk
+                     (KERN_INFO "%s: enable output %d\n",
+                      encoder->i2c->name, encoder->enable));
+       }
+       break;
+
+       case 4711:
+       {
+               int *iarg = arg;
+               __u8 val;
+
+               printk("bt866: square = %d\n", *iarg);
+
+               val = encoder->reg[0xdc];
+               if (*iarg)
+                       val |= 1; /* SQUARE */
+               else
+                       val &= ~1; /* !SQUARE */
+               bt866_write(encoder, 0xdc, val);
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int bt866_write(struct bt866 *encoder,
+                       unsigned char subaddr, unsigned char data)
+{
+       unsigned char buffer[2];
+       int err;
+
+       buffer[0] = subaddr;
+       buffer[1] = data;
+
+       encoder->reg[subaddr] = data;
+
+       DEBUG(printk
+             ("%s: write 0x%02X = 0x%02X\n",
+              encoder->i2c->name, subaddr, data));
+
+       for (err = 0; err < 3;) {
+               if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
+                       break;
+               err++;
+               printk(KERN_WARNING "%s: I/O error #%d "
+                      "(write 0x%02x/0x%02x)\n",
+                      encoder->i2c->name, err, encoder->addr, subaddr);
+               schedule_timeout_interruptible(HZ/10);
+       }
+       if (err == 3) {
+               printk(KERN_WARNING "%s: giving up\n",
+                      encoder->i2c->name);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int bt866_attach(struct i2c_adapter *adapter);
+static int bt866_detach(struct i2c_client *client);
+static int bt866_command(struct i2c_client *client,
+                        unsigned int cmd, void *arg);
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[]     = {I2C_BT866>>1, I2C_CLIENT_END};
+static unsigned short probe[2]         = {I2C_CLIENT_END, I2C_CLIENT_END};
+static unsigned short ignore[2]                = {I2C_CLIENT_END, I2C_CLIENT_END};
+
+static struct i2c_client_address_data addr_data = {
+       normal_i2c,
+       probe,
+       ignore,
+};
+
+static struct i2c_driver i2c_driver_bt866 = {
+       .driver.name = BT866_DEVNAME,
+       .id = I2C_DRIVERID_BT866,
+       .attach_adapter = bt866_attach,
+       .detach_client = bt866_detach,
+       .command = bt866_command
+};
+
+
+static struct i2c_client bt866_client_tmpl =
+{
+       .name = "(nil)",
+       .addr = 0,
+       .adapter = NULL,
+       .driver = &i2c_driver_bt866,
+       .usage_count = 0
+};
+
+static int bt866_found_proc(struct i2c_adapter *adapter,
+                           int addr, int kind)
+{
+       struct bt866 *encoder;
+       struct i2c_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (client == NULL)
+               return -ENOMEM;
+       memcpy(client, &bt866_client_tmpl, sizeof(*client));
+
+       encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
+       if (encoder == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(client, encoder);
+       client->adapter = adapter;
+       client->addr = addr;
+       sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
+
+       encoder->i2c = client;
+       encoder->addr = addr;
+       //encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
+
+       /* initialize */
+
+       i2c_attach_client(client);
+
+       return 0;
+}
+
+static int bt866_attach(struct i2c_adapter *adapter)
+{
+       if (adapter->id == I2C_HW_B_ZR36067)
+               return i2c_probe(adapter, &addr_data, bt866_found_proc);
+       return 0;
+}
+
+static int bt866_detach(struct i2c_client *client)
+{
+       struct bt866 *encoder = i2c_get_clientdata(client);
+
+       i2c_detach_client(client);
+       kfree(encoder);
+       kfree(client);
+
+       return 0;
+}
+
+static int bt866_command(struct i2c_client *client,
+                        unsigned int cmd, void *arg)
+{
+       struct bt866 *encoder = i2c_get_clientdata(client);
+       return bt866_do_command(encoder, cmd, arg);
+}
+
+static int __devinit bt866_init(void)
+{
+       i2c_add_driver(&i2c_driver_bt866);
+       return 0;
+}
+
+static void __devexit bt866_exit(void)
+{
+       i2c_del_driver(&i2c_driver_bt866);
+}
+
+module_init(bt866_init);
+module_exit(bt866_exit);
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
new file mode 100644 (file)
index 0000000..65f00fc
--- /dev/null
@@ -0,0 +1,932 @@
+/*
+ * cx2341x - generic code for cx23415/6 based devices
+ *
+ * Copyright (C) 2006 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/tuner.h>
+#include <media/cx2341x.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("cx23415/6 driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+const u32 cx2341x_mpeg_ctrls[] = {
+       V4L2_CID_MPEG_CLASS,
+       V4L2_CID_MPEG_STREAM_TYPE,
+       V4L2_CID_MPEG_STREAM_VBI_FMT,
+       V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+       V4L2_CID_MPEG_AUDIO_ENCODING,
+       V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+       V4L2_CID_MPEG_AUDIO_MODE,
+       V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+       V4L2_CID_MPEG_AUDIO_EMPHASIS,
+       V4L2_CID_MPEG_AUDIO_CRC,
+       V4L2_CID_MPEG_VIDEO_ENCODING,
+       V4L2_CID_MPEG_VIDEO_ASPECT,
+       V4L2_CID_MPEG_VIDEO_B_FRAMES,
+       V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+       V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+       V4L2_CID_MPEG_VIDEO_PULLDOWN,
+       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+       V4L2_CID_MPEG_VIDEO_BITRATE,
+       V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+       V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+       V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+       V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+       V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+       V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+       V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+       V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+       0
+};
+
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
+               struct v4l2_ext_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               ctrl->value = params->audio_sampling_freq;
+               break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               ctrl->value = params->audio_encoding;
+               break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               ctrl->value = params->audio_l2_bitrate;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE:
+               ctrl->value = params->audio_mode;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               ctrl->value = params->audio_mode_extension;
+               break;
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+               ctrl->value = params->audio_emphasis;
+               break;
+       case V4L2_CID_MPEG_AUDIO_CRC:
+               ctrl->value = params->audio_crc;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               ctrl->value = params->video_encoding;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               ctrl->value = params->video_aspect;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               ctrl->value = params->video_b_frames;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               ctrl->value = params->video_gop_size;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               ctrl->value = params->video_gop_closure;
+               break;
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+               ctrl->value = params->video_pulldown;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               ctrl->value = params->video_bitrate_mode;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               ctrl->value = params->video_bitrate;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               ctrl->value = params->video_bitrate_peak;
+               break;
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+               ctrl->value = params->video_temporal_decimation;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               ctrl->value = params->stream_type;
+               break;
+       case V4L2_CID_MPEG_STREAM_VBI_FMT:
+               ctrl->value = params->stream_vbi_fmt;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               ctrl->value = params->video_spatial_filter_mode;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               ctrl->value = params->video_spatial_filter;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               ctrl->value = params->video_luma_spatial_filter_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               ctrl->value = params->video_chroma_spatial_filter_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               ctrl->value = params->video_temporal_filter_mode;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               ctrl->value = params->video_temporal_filter;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               ctrl->value = params->video_median_filter_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               ctrl->value = params->video_luma_median_filter_top;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               ctrl->value = params->video_luma_median_filter_bottom;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               ctrl->value = params->video_chroma_median_filter_top;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               ctrl->value = params->video_chroma_median_filter_bottom;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
+               struct v4l2_ext_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               params->audio_sampling_freq = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               params->audio_encoding = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               params->audio_l2_bitrate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE:
+               params->audio_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               params->audio_mode_extension = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+               params->audio_emphasis = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_CRC:
+               params->audio_crc = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               params->video_aspect = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
+               int b = ctrl->value + 1;
+               int gop = params->video_gop_size;
+               params->video_b_frames = ctrl->value;
+               params->video_gop_size = b * ((gop + b - 1) / b);
+               /* Max GOP size = 34 */
+               while (params->video_gop_size > 34)
+                       params->video_gop_size -= b;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
+               int b = params->video_b_frames + 1;
+               int gop = ctrl->value;
+               params->video_gop_size = b * ((gop + b - 1) / b);
+               /* Max GOP size = 34 */
+               while (params->video_gop_size > 34)
+                       params->video_gop_size -= b;
+               ctrl->value = params->video_gop_size;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               params->video_gop_closure = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+               params->video_pulldown = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               /* MPEG-1 only allows CBR */
+               if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
+                   ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+                       return -EINVAL;
+               params->video_bitrate_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               params->video_bitrate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               params->video_bitrate_peak = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+               params->video_temporal_decimation = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               params->stream_type = ctrl->value;
+               params->video_encoding =
+                       (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
+                        params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
+                       V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+               if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+                       /* MPEG-1 implies CBR */
+                       params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+               }
+               break;
+       case V4L2_CID_MPEG_STREAM_VBI_FMT:
+               params->stream_vbi_fmt = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               params->video_spatial_filter_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               params->video_spatial_filter = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               params->video_luma_spatial_filter_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               params->video_chroma_spatial_filter_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               params->video_temporal_filter_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               params->video_temporal_filter = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               params->video_median_filter_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               params->video_luma_median_filter_top = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               params->video_luma_median_filter_bottom = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               params->video_chroma_median_filter_top = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               params->video_chroma_median_filter_bottom = ctrl->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+       const char *name;
+
+       qctrl->flags = 0;
+       switch (qctrl->id) {
+       /* MPEG controls */
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               name = "Spatial Filter Mode";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               name = "Spatial Filter";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               name = "Spatial Luma Filter Type";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               name = "Spatial Chroma Filter Type";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               name = "Temporal Filter Mode";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               name = "Temporal Filter";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               name = "Median Filter Type";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               name = "Median Luma Filter Maximum";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               name = "Median Luma Filter Minimum";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               name = "Median Chroma Filter Maximum";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               name = "Median Chroma Filter Minimum";
+               break;
+
+       default:
+               return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
+       }
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               qctrl->type = V4L2_CTRL_TYPE_MENU;
+               min = 0;
+               step = 1;
+               break;
+       default:
+               qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+               break;
+       }
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
+               break;
+       }
+       qctrl->minimum = min;
+       qctrl->maximum = max;
+       qctrl->step = step;
+       qctrl->default_value = def;
+       qctrl->reserved[0] = qctrl->reserved[1] = 0;
+       snprintf(qctrl->name, sizeof(qctrl->name), name);
+       return 0;
+}
+
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
+{
+       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);
+
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_192K,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+               return -EINVAL;
+
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               /* 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);
+               if (err == 0)
+                       qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+               return err;
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       case V4L2_CID_MPEG_STREAM_VBI_FMT:
+               if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
+                       return v4l2_ctrl_query_fill_std(qctrl);
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_STREAM_VBI_FMT_NONE,
+                               V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
+                               V4L2_MPEG_STREAM_VBI_FMT_NONE);
+
+       /* CX23415/6 specific */
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+                               V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
+                               V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
+               if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
+                               V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
+               if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+                               V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+                               V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       default:
+               return v4l2_ctrl_query_fill_std(qctrl);
+
+       }
+}
+
+const char **cx2341x_ctrl_get_menu(u32 id)
+{
+       static const char *mpeg_stream_type[] = {
+               "MPEG-2 Program Stream",
+               "",
+               "MPEG-1 System Stream",
+               "MPEG-2 DVD-compatible Stream",
+               "MPEG-1 VCD-compatible Stream",
+               "MPEG-2 SVCD-compatible Stream",
+               NULL
+       };
+
+       static const char *cx2341x_video_spatial_filter_mode_menu[] = {
+               "Manual",
+               "Auto",
+               NULL
+       };
+
+       static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
+               "Off",
+               "1D Horizontal",
+               "1D Vertical",
+               "2D H/V Separable",
+               "2D Symmetric non-separable",
+               NULL
+       };
+
+       static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
+               "Off",
+               "1D Horizontal",
+               NULL
+       };
+
+       static const char *cx2341x_video_temporal_filter_mode_menu[] = {
+               "Manual",
+               "Auto",
+               NULL
+       };
+
+       static const char *cx2341x_video_median_filter_type_menu[] = {
+               "Off",
+               "Horizontal",
+               "Vertical",
+               "Horizontal/Vertical",
+               "Diagonal",
+               NULL
+       };
+
+       switch (id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               return mpeg_stream_type;
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+               return NULL;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               return cx2341x_video_spatial_filter_mode_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               return cx2341x_video_luma_spatial_filter_type_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               return cx2341x_video_chroma_spatial_filter_type_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               return cx2341x_video_temporal_filter_mode_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               return cx2341x_video_median_filter_type_menu;
+       default:
+               return v4l2_ctrl_get_menu(id);
+       }
+}
+
+static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
+{
+       params->audio_properties = (params->audio_sampling_freq << 0) |
+               ((3 - params->audio_encoding) << 2) |
+               ((1 + params->audio_l2_bitrate) << 4) |
+               (params->audio_mode << 8) |
+               (params->audio_mode_extension << 10) |
+               (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
+                 3 :
+                 params->audio_emphasis) << 12) |
+               (params->audio_crc << 14);
+}
+
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+                 struct v4l2_ext_controls *ctrls, unsigned int cmd)
+{
+       int err = 0;
+       int i;
+
+       if (cmd == VIDIOC_G_EXT_CTRLS) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = cx2341x_get_ctrl(params, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+       }
+       for (i = 0; i < ctrls->count; i++) {
+               struct v4l2_ext_control *ctrl = ctrls->controls + i;
+               struct v4l2_queryctrl qctrl;
+               const char **menu_items = NULL;
+
+               qctrl.id = ctrl->id;
+               err = cx2341x_ctrl_query(params, &qctrl);
+               if (err)
+                       break;
+               if (qctrl.type == V4L2_CTRL_TYPE_MENU)
+                       menu_items = cx2341x_ctrl_get_menu(qctrl.id);
+               err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
+               if (err)
+                       break;
+               err = cx2341x_set_ctrl(params, ctrl);
+               if (err)
+                       break;
+       }
+       if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+                       params->video_bitrate_peak < params->video_bitrate) {
+               err = -ERANGE;
+               ctrls->error_idx = ctrls->count;
+       }
+       if (err) {
+               ctrls->error_idx = i;
+       }
+       else {
+               cx2341x_calc_audio_properties(params);
+       }
+       return err;
+}
+
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
+{
+       static struct cx2341x_mpeg_params default_params = {
+       /* misc */
+       .capabilities = 0,
+       .port = CX2341X_PORT_MEMORY,
+       .width = 720,
+       .height = 480,
+       .is_50hz = 0,
+
+       /* stream */
+       .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+       .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
+
+       /* audio */
+       .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+       .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+       .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+       .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
+       .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+       .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+       .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
+
+       /* video */
+       .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+       .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
+       .video_b_frames = 2,
+       .video_gop_size = 12,
+       .video_gop_closure = 1,
+       .video_pulldown = 0,
+       .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+       .video_bitrate = 6000000,
+       .video_bitrate_peak = 8000000,
+       .video_temporal_decimation = 0,
+
+       /* encoding filters */
+       .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+       .video_spatial_filter = 0,
+       .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
+       .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+       .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+       .video_temporal_filter = 0,
+       .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+       .video_luma_median_filter_top = 255,
+       .video_luma_median_filter_bottom = 0,
+       .video_chroma_median_filter_top = 255,
+       .video_chroma_median_filter_bottom = 0,
+       };
+
+       *p = default_params;
+       cx2341x_calc_audio_properties(p);
+}
+
+static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i;
+
+       va_start(vargs, args);
+
+       for (i = 0; i < args; i++) {
+               data[i] = va_arg(vargs, int);
+       }
+       va_end(vargs);
+       return func(priv, cmd, args, 0, data);
+}
+
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+               const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
+{
+       static int mpeg_stream_type[] = {
+               0,      /* MPEG-2 PS */
+               1,      /* MPEG-2 TS */
+               2,      /* MPEG-1 SS */
+               14,     /* DVD */
+               11,     /* VCD */
+               12,     /* SVCD */
+       };
+
+       int err = 0;
+
+       cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
+
+       if (old == NULL || old->is_50hz != new->is_50hz) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
+               if (err) return err;
+       }
+
+       if (old == NULL || old->width != new->width || old->height != new->height ||
+                       old->video_encoding != new->video_encoding) {
+               u16 w = new->width;
+               u16 h = new->height;
+
+               if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+                       w /= 2;
+                       h /= 2;
+               }
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
+               if (err) return err;
+       }
+
+       if (old == NULL || old->stream_type != new->stream_type) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_aspect != new->video_aspect) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_b_frames != new->video_b_frames ||
+               old->video_gop_size != new->video_gop_size) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
+                               new->video_gop_size, new->video_b_frames + 1);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_pulldown != new->video_pulldown) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
+               if (err) return err;
+       }
+       if (old == NULL || old->audio_properties != new->audio_properties) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
+               old->video_bitrate != new->video_bitrate ||
+               old->video_bitrate_peak != new->video_bitrate_peak) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
+                               new->video_bitrate_mode, new->video_bitrate,
+                               new->video_bitrate_peak / 400, 0, 0);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
+               old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
+               old->video_median_filter_type != new->video_median_filter_type) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
+                               new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
+                               new->video_median_filter_type);
+               if (err) return err;
+       }
+       if (old == NULL ||
+               old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
+               old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
+               old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
+               old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
+                               new->video_luma_median_filter_bottom,
+                               new->video_luma_median_filter_top,
+                               new->video_chroma_median_filter_bottom,
+                               new->video_chroma_median_filter_top);
+               if (err) return err;
+       }
+       if (old == NULL ||
+               old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
+               old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
+                       new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
+               if (err) return err;
+       }
+       if (old == NULL ||
+               old->video_spatial_filter != new->video_spatial_filter ||
+               old->video_temporal_filter != new->video_temporal_filter) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
+                       new->video_spatial_filter, new->video_temporal_filter);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
+                       new->video_temporal_decimation);
+               if (err) return err;
+       }
+       return 0;
+}
+
+static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
+{
+       const char **menu = cx2341x_ctrl_get_menu(id);
+       struct v4l2_ext_control ctrl;
+
+       if (menu == NULL)
+               goto invalid;
+       ctrl.id = id;
+       if (cx2341x_get_ctrl(p, &ctrl))
+               goto invalid;
+       while (ctrl.value-- && *menu) menu++;
+       if (*menu == NULL)
+               goto invalid;
+       return *menu;
+
+invalid:
+       return "<invalid>";
+}
+
+void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
+{
+       int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+
+       /* Stream */
+       printk(KERN_INFO "%s: Stream: %s\n",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
+
+       /* Video */
+       printk(KERN_INFO "%s: Video:  %dx%d, %d fps\n",
+               prefix,
+               p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
+               p->is_50hz ? 25 : 30);
+       printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
+               p->video_bitrate);
+       if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+               printk(", Peak %d", p->video_bitrate_peak);
+       }
+       printk("\n");
+       printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
+               prefix,
+               p->video_gop_size, p->video_b_frames,
+               p->video_gop_closure ? "" : "No ",
+               p->video_pulldown ? "" : "No ");
+       if (p->video_temporal_decimation) {
+               printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
+                       prefix, p->video_temporal_decimation);
+       }
+
+       /* Audio */
+       printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
+       if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
+               printk(", %s",
+                       cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
+       }
+       printk(", %s, %s\n",
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
+
+       /* Encoding filters */
+       printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
+               p->video_spatial_filter);
+       printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
+               p->video_temporal_filter);
+       printk(KERN_INFO "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
+               prefix,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
+               p->video_luma_median_filter_bottom,
+               p->video_luma_median_filter_top,
+               p->video_chroma_median_filter_bottom,
+               p->video_chroma_median_filter_top);
+}
+
+EXPORT_SYMBOL(cx2341x_fill_defaults);
+EXPORT_SYMBOL(cx2341x_ctrl_query);
+EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
+EXPORT_SYMBOL(cx2341x_ext_ctrls);
+EXPORT_SYMBOL(cx2341x_update);
+EXPORT_SYMBOL(cx2341x_log_status);
+EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
new file mode 100644 (file)
index 0000000..3bf7ac4
--- /dev/null
@@ -0,0 +1,846 @@
+/*
+ * Video Capture Driver (Video for Linux 1/2)
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.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.
+ *
+ *****************************************************************************
+ *
+ * Modified and extended by
+ *     Mike Bernson <mike@mlb.org>
+ *     Gerard v.d. Horst
+ *     Leon van Stuivenberg <l.vanstuivenberg@chello.nl>
+ *     Gernot Ziegler <gz@lysator.liu.se>
+ *
+ * Version History:
+ * V1.0 Ryan Drake        Initial version by Ryan Drake
+ * V1.1 Gerard v.d. Horst  Added some debugoutput, reset the video-standard
+ */
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include "ks0127.h"
+
+#include <linux/i2c.h>
+#include <linux/video_decoder.h>
+
+#define dprintk     if (debug) printk
+
+/* i2c identification */
+#define I2C_KS0127_ADDON   0xD8
+#define I2C_KS0127_ONBOARD 0xDA
+
+#define KS_TYPE_UNKNOWN        0
+#define KS_TYPE_0122S  1
+#define KS_TYPE_0127   2
+#define KS_TYPE_0127B  3
+
+/* ks0127 control registers */
+#define KS_STAT     0x00
+#define KS_CMDA     0x01
+#define KS_CMDB     0x02
+#define KS_CMDC     0x03
+#define KS_CMDD     0x04
+#define KS_HAVB     0x05
+#define KS_HAVE     0x06
+#define KS_HS1B     0x07
+#define KS_HS1E     0x08
+#define KS_HS2B     0x09
+#define KS_HS2E     0x0a
+#define KS_AGC      0x0b
+#define KS_HXTRA    0x0c
+#define KS_CDEM     0x0d
+#define KS_PORTAB   0x0e
+#define KS_LUMA     0x0f
+#define KS_CON      0x10
+#define KS_BRT      0x11
+#define KS_CHROMA   0x12
+#define KS_CHROMB   0x13
+#define KS_DEMOD    0x14
+#define KS_SAT      0x15
+#define KS_HUE      0x16
+#define KS_VERTIA   0x17
+#define KS_VERTIB   0x18
+#define KS_VERTIC   0x19
+#define KS_HSCLL    0x1a
+#define KS_HSCLH    0x1b
+#define KS_VSCLL    0x1c
+#define KS_VSCLH    0x1d
+#define KS_OFMTA    0x1e
+#define KS_OFMTB    0x1f
+#define KS_VBICTL   0x20
+#define KS_CCDAT2   0x21
+#define KS_CCDAT1   0x22
+#define KS_VBIL30   0x23
+#define KS_VBIL74   0x24
+#define KS_VBIL118  0x25
+#define KS_VBIL1512 0x26
+#define KS_TTFRAM   0x27
+#define KS_TESTA    0x28
+#define KS_UVOFFH   0x29
+#define KS_UVOFFL   0x2a
+#define KS_UGAIN    0x2b
+#define KS_VGAIN    0x2c
+#define KS_VAVB     0x2d
+#define KS_VAVE     0x2e
+#define KS_CTRACK   0x2f
+#define KS_POLCTL   0x30
+#define KS_REFCOD   0x31
+#define KS_INVALY   0x32
+#define KS_INVALU   0x33
+#define KS_INVALV   0x34
+#define KS_UNUSEY   0x35
+#define KS_UNUSEU   0x36
+#define KS_UNUSEV   0x37
+#define KS_USRSAV   0x38
+#define KS_USREAV   0x39
+#define KS_SHS1A    0x3a
+#define KS_SHS1B    0x3b
+#define KS_SHS1C    0x3c
+#define KS_CMDE     0x3d
+#define KS_VSDEL    0x3e
+#define KS_CMDF     0x3f
+#define KS_GAMMA0   0x40
+#define KS_GAMMA1   0x41
+#define KS_GAMMA2   0x42
+#define KS_GAMMA3   0x43
+#define KS_GAMMA4   0x44
+#define KS_GAMMA5   0x45
+#define KS_GAMMA6   0x46
+#define KS_GAMMA7   0x47
+#define KS_GAMMA8   0x48
+#define KS_GAMMA9   0x49
+#define KS_GAMMA10  0x4a
+#define KS_GAMMA11  0x4b
+#define KS_GAMMA12  0x4c
+#define KS_GAMMA13  0x4d
+#define KS_GAMMA14  0x4e
+#define KS_GAMMA15  0x4f
+#define KS_GAMMA16  0x50
+#define KS_GAMMA17  0x51
+#define KS_GAMMA18  0x52
+#define KS_GAMMA19  0x53
+#define KS_GAMMA20  0x54
+#define KS_GAMMA21  0x55
+#define KS_GAMMA22  0x56
+#define KS_GAMMA23  0x57
+#define KS_GAMMA24  0x58
+#define KS_GAMMA25  0x59
+#define KS_GAMMA26  0x5a
+#define KS_GAMMA27  0x5b
+#define KS_GAMMA28  0x5c
+#define KS_GAMMA29  0x5d
+#define KS_GAMMA30  0x5e
+#define KS_GAMMA31  0x5f
+#define KS_GAMMAD0  0x60
+#define KS_GAMMAD1  0x61
+#define KS_GAMMAD2  0x62
+#define KS_GAMMAD3  0x63
+#define KS_GAMMAD4  0x64
+#define KS_GAMMAD5  0x65
+#define KS_GAMMAD6  0x66
+#define KS_GAMMAD7  0x67
+#define KS_GAMMAD8  0x68
+#define KS_GAMMAD9  0x69
+#define KS_GAMMAD10 0x6a
+#define KS_GAMMAD11 0x6b
+#define KS_GAMMAD12 0x6c
+#define KS_GAMMAD13 0x6d
+#define KS_GAMMAD14 0x6e
+#define KS_GAMMAD15 0x6f
+#define KS_GAMMAD16 0x70
+#define KS_GAMMAD17 0x71
+#define KS_GAMMAD18 0x72
+#define KS_GAMMAD19 0x73
+#define KS_GAMMAD20 0x74
+#define KS_GAMMAD21 0x75
+#define KS_GAMMAD22 0x76
+#define KS_GAMMAD23 0x77
+#define KS_GAMMAD24 0x78
+#define KS_GAMMAD25 0x79
+#define KS_GAMMAD26 0x7a
+#define KS_GAMMAD27 0x7b
+#define KS_GAMMAD28 0x7c
+#define KS_GAMMAD29 0x7d
+#define KS_GAMMAD30 0x7e
+#define KS_GAMMAD31 0x7f
+
+
+/****************************************************************************
+* mga_dev : represents one ks0127 chip.
+****************************************************************************/
+
+struct adjust {
+       int     contrast;
+       int     bright;
+       int     hue;
+       int     ugain;
+       int     vgain;
+};
+
+struct ks0127 {
+       struct i2c_client *client;
+       unsigned char   addr;
+       int             format_width;
+       int             format_height;
+       int             cap_width;
+       int             cap_height;
+       int             norm;
+       int             ks_type;
+       u8              regs[256];
+};
+
+
+static int debug; /* insmod parameter */
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug output");
+MODULE_LICENSE("GPL");
+
+static u8 reg_defaults[64];
+
+
+
+static void init_reg_defaults(void)
+{
+       u8 *table = reg_defaults;
+
+       table[KS_CMDA]     = 0x2c;  /* VSE=0, CCIR 601, autodetect standard */
+       table[KS_CMDB]     = 0x12;  /* VALIGN=0, AGC control and input */
+       table[KS_CMDC]     = 0x00;  /* Test options */
+       /* clock & input select, write 1 to PORTA */
+       table[KS_CMDD]     = 0x01;
+       table[KS_HAVB]     = 0x00;  /* HAV Start Control */
+       table[KS_HAVE]     = 0x00;  /* HAV End Control */
+       table[KS_HS1B]     = 0x10;  /* HS1 Start Control */
+       table[KS_HS1E]     = 0x00;  /* HS1 End Control */
+       table[KS_HS2B]     = 0x00;  /* HS2 Start Control */
+       table[KS_HS2E]     = 0x00;  /* HS2 End Control */
+       table[KS_AGC]      = 0x53;  /* Manual setting for AGC */
+       table[KS_HXTRA]    = 0x00;  /* Extra Bits for HAV and HS1/2 */
+       table[KS_CDEM]     = 0x00;  /* Chroma Demodulation Control */
+       table[KS_PORTAB]   = 0x0f;  /* port B is input, port A output GPPORT */
+       table[KS_LUMA]     = 0x01;  /* Luma control */
+       table[KS_CON]      = 0x00;  /* Contrast Control */
+       table[KS_BRT]      = 0x00;  /* Brightness Control */
+       table[KS_CHROMA]   = 0x2a;  /* Chroma control A */
+       table[KS_CHROMB]   = 0x90;  /* Chroma control B */
+       table[KS_DEMOD]    = 0x00;  /* Chroma Demodulation Control & Status */
+       table[KS_SAT]      = 0x00;  /* Color Saturation Control*/
+       table[KS_HUE]      = 0x00;  /* Hue Control */
+       table[KS_VERTIA]   = 0x00;  /* Vertical Processing Control A */
+       /* Vertical Processing Control B, luma 1 line delayed */
+       table[KS_VERTIB]   = 0x12;
+       table[KS_VERTIC]   = 0x0b;  /* Vertical Processing Control C */
+       table[KS_HSCLL]    = 0x00;  /* Horizontal Scaling Ratio Low */
+       table[KS_HSCLH]    = 0x00;  /* Horizontal Scaling Ratio High */
+       table[KS_VSCLL]    = 0x00;  /* Vertical Scaling Ratio Low */
+       table[KS_VSCLH]    = 0x00;  /* Vertical Scaling Ratio High */
+       /* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */
+       table[KS_OFMTA]    = 0x30;
+       table[KS_OFMTB]    = 0x00;  /* Output Control B */
+       /* VBI Decoder Control; 4bit fmt: avoid Y overflow */
+       table[KS_VBICTL]   = 0x5d;
+       table[KS_CCDAT2]   = 0x00;  /* Read Only register */
+       table[KS_CCDAT1]   = 0x00;  /* Read Only register */
+       table[KS_VBIL30]   = 0xa8;  /* VBI data decoding options */
+       table[KS_VBIL74]   = 0xaa;  /* VBI data decoding options */
+       table[KS_VBIL118]  = 0x2a;  /* VBI data decoding options */
+       table[KS_VBIL1512] = 0x00;  /* VBI data decoding options */
+       table[KS_TTFRAM]   = 0x00;  /* Teletext frame alignment pattern */
+       table[KS_TESTA]    = 0x00;  /* test register, shouldn't be written */
+       table[KS_UVOFFH]   = 0x00;  /* UV Offset Adjustment High */
+       table[KS_UVOFFL]   = 0x00;  /* UV Offset Adjustment Low */
+       table[KS_UGAIN]    = 0x00;  /* U Component Gain Adjustment */
+       table[KS_VGAIN]    = 0x00;  /* V Component Gain Adjustment */
+       table[KS_VAVB]     = 0x07;  /* VAV Begin */
+       table[KS_VAVE]     = 0x00;  /* VAV End */
+       table[KS_CTRACK]   = 0x00;  /* Chroma Tracking Control */
+       table[KS_POLCTL]   = 0x41;  /* Timing Signal Polarity Control */
+       table[KS_REFCOD]   = 0x80;  /* Reference Code Insertion Control */
+       table[KS_INVALY]   = 0x10;  /* Invalid Y Code */
+       table[KS_INVALU]   = 0x80;  /* Invalid U Code */
+       table[KS_INVALV]   = 0x80;  /* Invalid V Code */
+       table[KS_UNUSEY]   = 0x10;  /* Unused Y Code */
+       table[KS_UNUSEU]   = 0x80;  /* Unused U Code */
+       table[KS_UNUSEV]   = 0x80;  /* Unused V Code */
+       table[KS_USRSAV]   = 0x00;  /* reserved */
+       table[KS_USREAV]   = 0x00;  /* reserved */
+       table[KS_SHS1A]    = 0x00;  /* User Defined SHS1 A */
+       /* User Defined SHS1 B, ALT656=1 on 0127B */
+       table[KS_SHS1B]    = 0x80;
+       table[KS_SHS1C]    = 0x00;  /* User Defined SHS1 C */
+       table[KS_CMDE]     = 0x00;  /* Command Register E */
+       table[KS_VSDEL]    = 0x00;  /* VS Delay Control */
+       /* Command Register F, update -immediately- */
+       /* (there might come no vsync)*/
+       table[KS_CMDF]     = 0x02;
+}
+
+
+/* We need to manually read because of a bug in the KS0127 chip.
+ *
+ * An explanation from kayork@mail.utexas.edu:
+ *
+ * During I2C reads, the KS0127 only samples for a stop condition
+ * during the place where the acknoledge bit should be. Any standard
+ * I2C implementation (correctly) throws in another clock transition
+ * at the 9th bit, and the KS0127 will not recognize the stop condition
+ * and will continue to clock out data.
+ *
+ * So we have to do the read ourself.  Big deal.
+          workaround in i2c-algo-bit
+ */
+
+
+static u8 ks0127_read(struct ks0127 *ks, u8 reg)
+{
+       struct i2c_client *c = ks->client;
+       char val = 0;
+       struct i2c_msg msgs[] = {
+               {c->addr, 0, sizeof(reg), &reg},
+               {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}};
+       int ret;
+
+       ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs));
+       if (ret != ARRAY_SIZE(msgs))
+               dprintk("ks0127_write error\n");
+
+       return val;
+}
+
+
+static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val)
+{
+       char msg[] = {reg, val};
+
+       if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg))
+               dprintk("ks0127_write error\n");
+
+       ks->regs[reg] = val;
+}
+
+
+/* generic bit-twiddling */
+static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v)
+{
+       u8 val = ks->regs[reg];
+       val = (val & and_v) | or_v;
+       ks0127_write(ks, reg, val);
+}
+
+
+
+/****************************************************************************
+* ks0127 private api
+****************************************************************************/
+static void ks0127_reset(struct ks0127* ks)
+{
+       int i;
+       u8 *table = reg_defaults;
+
+       ks->ks_type = KS_TYPE_UNKNOWN;
+
+       dprintk("ks0127: reset\n");
+       msleep(1);
+
+       /* initialize all registers to known values */
+       /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
+
+       for(i = 1; i < 33; i++)
+               ks0127_write(ks, i, table[i]);
+
+       for(i = 35; i < 40; i++)
+               ks0127_write(ks, i, table[i]);
+
+       for(i = 41; i < 56; i++)
+               ks0127_write(ks, i, table[i]);
+
+       for(i = 58; i < 64; i++)
+               ks0127_write(ks, i, table[i]);
+
+
+       if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) {
+               ks->ks_type = KS_TYPE_0122S;
+               dprintk("ks0127: ks0122s Found\n");
+               return;
+       }
+
+       switch(ks0127_read(ks, KS_CMDE) & 0x0f) {
+
+       case 0:
+               ks->ks_type = KS_TYPE_0127;
+               dprintk("ks0127: ks0127 found\n");
+               break;
+
+       case 9:
+               ks->ks_type = KS_TYPE_0127B;
+               dprintk("ks0127: ks0127B Revision A found\n");
+               break;
+
+       default:
+               dprintk("ks0127: unknown revision\n");
+               break;
+       }
+}
+
+static int ks0127_command(struct i2c_client *client,
+                         unsigned int cmd, void *arg)
+{
+       struct ks0127 *ks = i2c_get_clientdata(client);
+
+       int             *iarg = (int*)arg;
+
+       int             status;
+
+       if (!ks)
+               return -ENODEV;
+
+       switch (cmd) {
+
+       case DECODER_INIT:
+               dprintk("ks0127: command DECODER_INIT\n");
+               ks0127_reset(ks);
+               break;
+
+       case DECODER_SET_INPUT:
+               switch(*iarg) {
+               case KS_INPUT_COMPOSITE_1:
+               case KS_INPUT_COMPOSITE_2:
+               case KS_INPUT_COMPOSITE_3:
+               case KS_INPUT_COMPOSITE_4:
+               case KS_INPUT_COMPOSITE_5:
+               case KS_INPUT_COMPOSITE_6:
+                       dprintk("ks0127: command DECODER_SET_INPUT %d: "
+                               "Composite\n", *iarg);
+                       /* autodetect 50/60 Hz */
+                       ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+                       /* VSE=0 */
+                       ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+                       /* set input line */
+                       ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+                       /* non-freerunning mode */
+                       ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+                       /* analog input */
+                       ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+                       /* enable chroma demodulation */
+                       ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+                       /* chroma trap, HYBWR=1 */
+                       ks0127_and_or(ks, KS_LUMA,   0x00,
+                                      (reg_defaults[KS_LUMA])|0x0c);
+                       /* scaler fullbw, luma comb off */
+                       ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+                       /* manual chroma comb .25 .5 .25 */
+                       ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90);
+
+                       /* chroma path delay */
+                       ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90);
+
+                       ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
+                       ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
+                       ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+                       ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+                       break;
+
+               case KS_INPUT_SVIDEO_1:
+               case KS_INPUT_SVIDEO_2:
+               case KS_INPUT_SVIDEO_3:
+                       dprintk("ks0127: command DECODER_SET_INPUT %d: "
+                               "S-Video\n", *iarg);
+                       /* autodetect 50/60 Hz */
+                       ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+                       /* VSE=0 */
+                       ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+                       /* set input line */
+                       ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+                       /* non-freerunning mode */
+                       ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+                       /* analog input */
+                       ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+                       /* enable chroma demodulation */
+                       ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+                       ks0127_and_or(ks, KS_LUMA, 0x00,
+                                      reg_defaults[KS_LUMA]);
+                       /* disable luma comb */
+                       ks0127_and_or(ks, KS_VERTIA, 0x08,
+                                      (reg_defaults[KS_VERTIA]&0xf0)|0x01);
+                       ks0127_and_or(ks, KS_VERTIC, 0x0f,
+                                      reg_defaults[KS_VERTIC]&0xf0);
+
+                       ks0127_and_or(ks, KS_CHROMB, 0x0f,
+                                      reg_defaults[KS_CHROMB]&0xf0);
+
+                       ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
+                       ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
+                       ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+                       ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+                       break;
+
+               case KS_INPUT_YUV656:
+                       dprintk("ks0127: command DECODER_SET_INPUT 15: "
+                               "YUV656\n");
+                       if (ks->norm == VIDEO_MODE_NTSC ||
+                           ks->norm == KS_STD_PAL_M)
+                               /* force 60 Hz */
+                               ks0127_and_or(ks, KS_CMDA,   0xfc, 0x03);
+                       else
+                               /* force 50 Hz */
+                               ks0127_and_or(ks, KS_CMDA,   0xfc, 0x02);
+
+                       ks0127_and_or(ks, KS_CMDA,   0xff, 0x40); /* VSE=1 */
+                       /* set input line and VALIGN */
+                       ks0127_and_or(ks, KS_CMDB,   0xb0, (*iarg | 0x40));
+                       /* freerunning mode, */
+                       /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/
+                       ks0127_and_or(ks, KS_CMDC,   0x70, 0x87);
+                       /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
+                       ks0127_and_or(ks, KS_CMDD,   0x03, 0x08);
+                       /* disable chroma demodulation */
+                       ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30);
+                       /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
+                       ks0127_and_or(ks, KS_LUMA,   0x00, 0x71);
+                       ks0127_and_or(ks, KS_VERTIC, 0x0f,
+                                      reg_defaults[KS_VERTIC]&0xf0);
+
+                       /* scaler fullbw, luma comb off */
+                       ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+
+                       ks0127_and_or(ks, KS_CHROMB, 0x0f,
+                                      reg_defaults[KS_CHROMB]&0xf0);
+
+                       ks0127_and_or(ks, KS_CON, 0x00, 0x00);
+                       ks0127_and_or(ks, KS_BRT, 0x00, 32);    /* spec: 34 */
+                               /* spec: 229 (e5) */
+                       ks0127_and_or(ks, KS_SAT, 0x00, 0xe8);
+                       ks0127_and_or(ks, KS_HUE, 0x00, 0);
+
+                       ks0127_and_or(ks, KS_UGAIN, 0x00, 238);
+                       ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00);
+
+                       /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
+                       ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f);
+                       ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00);
+                       break;
+
+               default:
+                       dprintk("ks0127: command DECODER_SET_INPUT: "
+                               "Unknown input %d\n", *iarg);
+                       break;
+               }
+
+               /* hack: CDMLPF sometimes spontaneously switches on; */
+               /* force back off */
+               ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]);
+               break;
+
+       case DECODER_SET_OUTPUT:
+               switch(*iarg) {
+               case KS_OUTPUT_YUV656E:
+                       dprintk("ks0127: command DECODER_SET_OUTPUT: "
+                               "OUTPUT_YUV656E (Missing)\n");
+                       return -EINVAL;
+                       break;
+
+               case KS_OUTPUT_EXV:
+                       dprintk("ks0127: command DECODER_SET_OUTPUT: "
+                               "OUTPUT_EXV\n");
+                       ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09);
+                       break;
+               }
+               break;
+
+       case DECODER_SET_NORM: //sam This block mixes old and new norm names...
+               /* Set to automatic SECAM/Fsc mode */
+               ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+
+               ks->norm = *iarg;
+               switch(*iarg)
+               {
+               /* this is untested !! */
+               /* It just detects PAL_N/NTSC_M (no special frequencies) */
+               /* And you have to set the standard a second time afterwards */
+               case VIDEO_MODE_AUTO:
+                       dprintk("ks0127: command DECODER_SET_NORM: AUTO\n");
+
+                       /* The chip determines the format */
+                       /* based on the current field rate */
+                       ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+                       /* This is wrong for PAL ! As I said, */
+                       /* you need to set the standard once again !! */
+                       ks->format_height = 240;
+                       ks->format_width = 704;
+                       break;
+
+               case VIDEO_MODE_NTSC:
+                       dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+                       ks->format_height = 240;
+                       ks->format_width = 704;
+                       break;
+
+               case KS_STD_NTSC_N:
+                       dprintk("ks0127: command KS0127_SET_STANDARD: "
+                               "NTSC_N (fixme)\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+                       ks->format_height = 240;
+                       ks->format_width = 704;
+                       break;
+
+               case VIDEO_MODE_PAL:
+                       dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+                       ks->format_height = 290;
+                       ks->format_width = 704;
+                       break;
+
+               case KS_STD_PAL_M:
+                       dprintk("ks0127: command KS0127_SET_STANDARD: "
+                               "PAL_M (fixme)\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+                       ks->format_height = 290;
+                       ks->format_width = 704;
+                       break;
+
+               case VIDEO_MODE_SECAM:
+                       dprintk("ks0127: command KS0127_SET_STANDARD: "
+                               "SECAM\n");
+                       ks->format_height = 290;
+                       ks->format_width = 704;
+
+                       /* set to secam autodetection */
+                       ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20);
+                       ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+                       schedule_timeout_interruptible(HZ/10+1);
+
+                       /* did it autodetect? */
+                       if (ks0127_read(ks, KS_DEMOD) & 0x40)
+                               break;
+
+                       /* force to secam mode */
+                       ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f);
+                       break;
+
+               default:
+                       dprintk("ks0127: command DECODER_SET_NORM: "
+                               "Unknown norm %d\n", *iarg);
+                       break;
+               }
+               break;
+
+       case DECODER_SET_PICTURE:
+               dprintk("ks0127: command DECODER_SET_PICTURE "
+                       "not yet supported (fixme)\n");
+               return -EINVAL;
+
+       //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE
+       //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE
+       //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE?
+       //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE
+       //sam todo: KS0127_SET_AGC_MODE:
+       //sam todo: KS0127_SET_AGC:
+       //sam todo: KS0127_SET_CHROMA_MODE:
+       //sam todo: KS0127_SET_PIXCLK_MODE:
+       //sam todo: KS0127_SET_GAMMA_MODE:
+       //sam todo: KS0127_SET_UGAIN:
+       //sam todo: KS0127_SET_VGAIN:
+       //sam todo: KS0127_SET_INVALY:
+       //sam todo: KS0127_SET_INVALU:
+       //sam todo: KS0127_SET_INVALV:
+       //sam todo: KS0127_SET_UNUSEY:
+       //sam todo: KS0127_SET_UNUSEU:
+       //sam todo: KS0127_SET_UNUSEV:
+       //sam todo: KS0127_SET_VSALIGN_MODE:
+
+       case DECODER_ENABLE_OUTPUT:
+       {
+
+               int *iarg = arg;
+               int enable = (*iarg != 0);
+                       if (enable) {
+                               dprintk("ks0127: command "
+                                       "DECODER_ENABLE_OUTPUT on "
+                                       "(%d)\n", enable);
+                               /* All output pins on */
+                               ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
+                               /* Obey the OEN pin */
+                               ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
+                       } else {
+                               dprintk("ks0127: command "
+                                       "DECODER_ENABLE_OUTPUT off "
+                                       "(%d)\n", enable);
+                               /* Video output pins off */
+                               ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
+                               /* Ignore the OEN pin */
+                               ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
+                       }
+       }
+               break;
+
+       //sam todo: KS0127_SET_OUTPUT_MODE:
+       //sam todo: KS0127_SET_WIDTH:
+       //sam todo: KS0127_SET_HEIGHT:
+       //sam todo: KS0127_SET_HSCALE:
+
+       case DECODER_GET_STATUS:
+               dprintk("ks0127: command DECODER_GET_STATUS\n");
+               *iarg = 0;
+               status = ks0127_read(ks, KS_STAT);
+               if (!(status & 0x20))            /* NOVID not set */
+                       *iarg = (*iarg & DECODER_STATUS_GOOD);
+               if ((status & 0x01))                  /* CLOCK set */
+                       *iarg = (*iarg & DECODER_STATUS_COLOR);
+               if ((status & 0x08))               /* PALDET set */
+                       *iarg = (*iarg & DECODER_STATUS_PAL);
+               else
+                       *iarg = (*iarg & DECODER_STATUS_NTSC);
+               break;
+
+       //Catch any unknown command
+       default:
+               dprintk("ks0127: command unknown: %04X\n", cmd);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+
+
+
+static int ks0127_probe(struct i2c_adapter *adapter);
+static int ks0127_detach(struct i2c_client *client);
+static int ks0127_command(struct i2c_client *client,
+                         unsigned int cmd, void *arg);
+
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1,
+                                      I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END};
+static unsigned short probe[2] =       {I2C_CLIENT_END, I2C_CLIENT_END};
+static unsigned short ignore[2] =      {I2C_CLIENT_END, I2C_CLIENT_END};
+static struct i2c_client_address_data addr_data = {
+       normal_i2c,
+       probe,
+       ignore,
+};
+
+static struct i2c_driver i2c_driver_ks0127 = {
+       .driver.name = "ks0127",
+       .id             = I2C_DRIVERID_KS0127,
+       .attach_adapter = ks0127_probe,
+       .detach_client  = ks0127_detach,
+       .command        = ks0127_command
+};
+
+static struct i2c_client ks0127_client_tmpl =
+{
+       .name = "(ks0127 unset)",
+       .addr = 0,
+       .adapter = NULL,
+       .driver = &i2c_driver_ks0127,
+       .usage_count = 0
+};
+
+static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind)
+{
+       struct ks0127 *ks;
+       struct i2c_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (client == NULL)
+               return -ENOMEM;
+       memcpy(client, &ks0127_client_tmpl, sizeof(*client));
+
+       ks = kzalloc(sizeof(*ks), GFP_KERNEL);
+       if (ks == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(client, ks);
+       client->adapter = adapter;
+       client->addr = addr;
+       sprintf(client->name, "ks0127-%02x", adapter->id);
+
+       ks->client = client;
+       ks->addr = addr;
+       ks->ks_type = KS_TYPE_UNKNOWN;
+
+       /* power up */
+       ks0127_write(ks, KS_CMDA, 0x2c);
+       mdelay(10);
+
+       /* reset the device */
+       ks0127_reset(ks);
+       printk(KERN_INFO "ks0127: attach: %s video decoder\n",
+              ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board");
+
+       i2c_attach_client(client);
+       return 0;
+}
+
+
+static int ks0127_probe(struct i2c_adapter *adapter)
+{
+       if (adapter->id == I2C_HW_B_ZR36067)
+               return i2c_probe(adapter, &addr_data, ks0127_found_proc);
+       return 0;
+}
+
+static int ks0127_detach(struct i2c_client *client)
+{
+       struct ks0127 *ks = i2c_get_clientdata(client);
+
+       ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/
+       ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */
+
+       i2c_detach_client(client);
+       kfree(ks);
+       kfree(client);
+
+       dprintk("ks0127: detach\n");
+       return 0;
+}
+
+
+static int __devinit ks0127_init_module(void)
+{
+       init_reg_defaults();
+       i2c_add_driver(&i2c_driver_ks0127);
+       return 0;
+}
+
+static void __devexit ks0127_cleanup_module(void)
+{
+       i2c_del_driver(&i2c_driver_ks0127);
+}
+
+
+module_init(ks0127_init_module);
+module_exit(ks0127_cleanup_module);
diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h
new file mode 100644 (file)
index 0000000..1ec5788
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Video Capture Driver ( Video for Linux 1/2 )
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.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 KS0127_H
+#define KS0127_H
+
+#include <linux/videodev.h>
+
+/* input channels */
+#define KS_INPUT_COMPOSITE_1    0
+#define KS_INPUT_COMPOSITE_2    1
+#define KS_INPUT_COMPOSITE_3    2
+#define KS_INPUT_COMPOSITE_4    4
+#define KS_INPUT_COMPOSITE_5    5
+#define KS_INPUT_COMPOSITE_6    6
+
+#define KS_INPUT_SVIDEO_1       8
+#define KS_INPUT_SVIDEO_2       9
+#define KS_INPUT_SVIDEO_3       10
+
+#define KS_INPUT_YUV656                15
+#define KS_INPUT_COUNT          10
+
+/* output channels */
+#define KS_OUTPUT_YUV656E       0
+#define KS_OUTPUT_EXV           1
+
+/* video standards */
+#define KS_STD_NTSC_N           112       /* 50 Hz NTSC */
+#define KS_STD_PAL_M            113       /* 60 Hz PAL  */
+
+#endif /* KS0127_H */
+
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
new file mode 100644 (file)
index 0000000..e43a979
--- /dev/null
@@ -0,0 +1,57 @@
+config VIDEO_PVRUSB2
+       tristate "Hauppauge WinTV-PVR USB2 support"
+       depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
+       select FW_LOADER
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_CX2341X
+       select VIDEO_SAA711X
+       select VIDEO_MSP3400
+       ---help---
+         This is a video4linux driver for Conexant 23416 based
+         usb2 personal video recorder devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pvrusb2
+
+config VIDEO_PVRUSB2_24XXX
+       bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series"
+       depends on VIDEO_PVRUSB2 && EXPERIMENTAL
+       select VIDEO_CX25840
+       select VIDEO_WM8775
+       ---help---
+         This option enables inclusion of additional logic to operate
+         newer WinTV-PVR USB2 devices whose model number is of the
+         form "24xxx" (leading prefix of "24" followed by 3 digits).
+         To see if you may need this option, examine the white
+         sticker on the underside of your device.  Enabling this
+         option will not harm support for older devices.
+
+         If you are in doubt, say Y.
+
+config VIDEO_PVRUSB2_SYSFS
+       bool "pvrusb2 sysfs support (EXPERIMENTAL)"
+       default y
+       depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
+       ---help---
+         This option enables the operation of a sysfs based
+         interface for query and control of the pvrusb2 driver.
+
+         This is not generally needed for v4l applications,
+         although certain applications are optimized to take
+         advantage of this feature.
+
+         If you are in doubt, say Y.
+
+         Note: This feature is experimental and subject to change.
+
+config VIDEO_PVRUSB2_DEBUGIFC
+       bool "pvrusb2 debug interface"
+       depends on VIDEO_PVRUSB2_SYSFS
+       ---help---
+         This option enables the inclusion of a debug interface
+         in the pvrusb2 driver, hosted through sysfs.
+
+         You do not need to select this option unless you plan
+         on debugging the driver or performing a manual firmware
+         extraction.
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
new file mode 100644 (file)
index 0000000..02e4142
--- /dev/null
@@ -0,0 +1,18 @@
+obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
+obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
+
+obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \
+                  pvrusb2-cx2584x-v4l.o \
+                  pvrusb2-wm8775.o
+
+pvrusb2-objs   := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
+                  pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
+                  pvrusb2-encoder.o pvrusb2-video-v4l.o \
+                  pvrusb2-eeprom.o pvrusb2-tuner.o \
+                  pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
+                  pvrusb2-ctrl.o pvrusb2-std.o \
+                  pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
+                  $(obj-pvrusb2-24xxx-y) \
+                  $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
+
+obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
new file mode 100644 (file)
index 0000000..9846c46
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-audio.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/msp3400.h>
+#include <media/v4l2-common.h>
+
+struct pvr2_msp3400_handler {
+       struct pvr2_hdw *hdw;
+       struct pvr2_i2c_client *client;
+       struct pvr2_i2c_handler i2c_handler;
+       struct pvr2_audio_stat astat;
+       unsigned long stale_mask;
+};
+
+
+/* This function selects the correct audio input source */
+static void set_stereo(struct pvr2_msp3400_handler *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       struct v4l2_routing route;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
+
+       if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
+               struct v4l2_tuner vt;
+               memset(&vt,0,sizeof(vt));
+               vt.audmode = hdw->audiomode_val;
+               pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
+       }
+
+       route.input = MSP_INPUT_DEFAULT;
+       route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+       switch (hdw->input_val) {
+       case PVR2_CVAL_INPUT_TV:
+               break;
+       case PVR2_CVAL_INPUT_RADIO:
+               /* Assume that msp34xx also handle FM decoding, in which case
+                  we're still using the tuner. */
+               /* HV: actually it is more likely to be the SCART2 input if
+                  the ivtv experience is any indication. */
+               route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+               break;
+       case PVR2_CVAL_INPUT_SVIDEO:
+       case PVR2_CVAL_INPUT_COMPOSITE:
+               /* SCART 1 input */
+               route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+                                   MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+               break;
+       }
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
+}
+
+
+static int check_stereo(struct pvr2_msp3400_handler *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       return (hdw->input_dirty ||
+               hdw->audiomode_dirty);
+}
+
+
+struct pvr2_msp3400_ops {
+       void (*update)(struct pvr2_msp3400_handler *);
+       int (*check)(struct pvr2_msp3400_handler *);
+};
+
+
+static const struct pvr2_msp3400_ops msp3400_ops[] = {
+       { .update = set_stereo, .check = check_stereo},
+};
+
+
+static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (ctxt->stale_mask & msk) continue;
+               if (msp3400_ops[idx].check(ctxt)) {
+                       ctxt->stale_mask |= msk;
+               }
+       }
+       return ctxt->stale_mask != 0;
+}
+
+
+static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (!(ctxt->stale_mask & msk)) continue;
+               ctxt->stale_mask &= ~msk;
+               msp3400_ops[idx].update(ctxt);
+       }
+}
+
+
+/* This reads back the current signal type */
+static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
+{
+       struct v4l2_tuner vt;
+       int stat;
+
+       memset(&vt,0,sizeof(vt));
+       stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
+       if (stat < 0) return stat;
+
+       ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0;
+       ctxt->hdw->flag_bilingual =
+               (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0;
+       return 0;
+}
+
+
+static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
+{
+       ctxt->client->handler = NULL;
+       ctxt->hdw->audio_stat = NULL;
+       kfree(ctxt);
+}
+
+
+static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
+                                         char *buf,unsigned int cnt)
+{
+       return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2");
+}
+
+
+const static struct pvr2_i2c_handler_functions msp3400_funcs = {
+       .detach = (void (*)(void *))pvr2_msp3400_detach,
+       .check = (int (*)(void *))msp3400_check,
+       .update = (void (*)(void *))msp3400_update,
+       .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe,
+};
+
+
+int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+       struct pvr2_msp3400_handler *ctxt;
+       if (hdw->audio_stat) return 0;
+       if (cp->handler) return 0;
+
+       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       if (!ctxt) return 0;
+       memset(ctxt,0,sizeof(*ctxt));
+
+       ctxt->i2c_handler.func_data = ctxt;
+       ctxt->i2c_handler.func_table = &msp3400_funcs;
+       ctxt->client = cp;
+       ctxt->hdw = hdw;
+       ctxt->astat.ctxt = ctxt;
+       ctxt->astat.status = (int (*)(void *))get_audio_status;
+       ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach;
+       ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
+                                 sizeof(msp3400_ops[0]))) - 1;
+       cp->handler = &ctxt->i2c_handler;
+       hdw->audio_stat = &ctxt->astat;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
+                  cp->client->addr);
+       return !0;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h
new file mode 100644 (file)
index 0000000..536339b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_AUDIO_H
+#define __PVRUSB2_AUDIO_H
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+#endif /* __PVRUSB2_AUDIO_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
new file mode 100644 (file)
index 0000000..f129f31
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-context.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-ioread.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+
+
+static void pvr2_context_destroy(struct pvr2_context *mp)
+{
+       if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
+       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
+       flush_workqueue(mp->workqueue);
+       destroy_workqueue(mp->workqueue);
+       kfree(mp);
+}
+
+
+static void pvr2_context_trigger_poll(struct pvr2_context *mp)
+{
+       queue_work(mp->workqueue,&mp->workpoll);
+}
+
+
+static void pvr2_context_poll(struct pvr2_context *mp)
+{
+       pvr2_context_enter(mp); do {
+               pvr2_hdw_poll(mp->hdw);
+       } while (0); pvr2_context_exit(mp);
+}
+
+
+static void pvr2_context_setup(struct pvr2_context *mp)
+{
+       pvr2_context_enter(mp); do {
+               if (!pvr2_hdw_dev_ok(mp->hdw)) break;
+               pvr2_hdw_setup(mp->hdw);
+               pvr2_hdw_setup_poll_trigger(
+                       mp->hdw,
+                       (void (*)(void *))pvr2_context_trigger_poll,
+                       mp);
+               if (!pvr2_hdw_dev_ok(mp->hdw)) break;
+               if (!pvr2_hdw_init_ok(mp->hdw)) break;
+               mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
+               if (mp->setup_func) {
+                       mp->setup_func(mp);
+               }
+       } while (0); pvr2_context_exit(mp);
+}
+
+
+struct pvr2_context *pvr2_context_create(
+       struct usb_interface *intf,
+       const struct usb_device_id *devid,
+       void (*setup_func)(struct pvr2_context *))
+{
+       struct pvr2_context *mp = NULL;
+       mp = kmalloc(sizeof(*mp),GFP_KERNEL);
+       if (!mp) goto done;
+       memset(mp,0,sizeof(*mp));
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
+       mp->setup_func = setup_func;
+       mutex_init(&mp->mutex);
+       mp->hdw = pvr2_hdw_create(intf,devid);
+       if (!mp->hdw) {
+               pvr2_context_destroy(mp);
+               mp = NULL;
+               goto done;
+       }
+
+       mp->workqueue = create_singlethread_workqueue("pvrusb2");
+       INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp);
+       INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp);
+       queue_work(mp->workqueue,&mp->workinit);
+ done:
+       return mp;
+}
+
+
+void pvr2_context_enter(struct pvr2_context *mp)
+{
+       mutex_lock(&mp->mutex);
+       pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
+}
+
+
+void pvr2_context_exit(struct pvr2_context *mp)
+{
+       int destroy_flag = 0;
+       if (!(mp->mc_first || !mp->disconnect_flag)) {
+               destroy_flag = !0;
+       }
+       pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
+       mutex_unlock(&mp->mutex);
+       if (destroy_flag) pvr2_context_destroy(mp);
+}
+
+
+static void pvr2_context_run_checks(struct pvr2_context *mp)
+{
+       struct pvr2_channel *ch1,*ch2;
+       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+               ch2 = ch1->mc_next;
+               if (ch1->check_func) {
+                       ch1->check_func(ch1);
+               }
+       }
+}
+
+
+void pvr2_context_disconnect(struct pvr2_context *mp)
+{
+       pvr2_context_enter(mp); do {
+               pvr2_hdw_disconnect(mp->hdw);
+               mp->disconnect_flag = !0;
+               pvr2_context_run_checks(mp);
+       } while (0); pvr2_context_exit(mp);
+}
+
+
+void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+{
+       cp->hdw = mp->hdw;
+       cp->mc_head = mp;
+       cp->mc_next = NULL;
+       cp->mc_prev = mp->mc_last;
+       if (mp->mc_last) {
+               mp->mc_last->mc_next = cp;
+       } else {
+               mp->mc_first = cp;
+       }
+       mp->mc_last = cp;
+}
+
+
+static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
+{
+       if (!cp->stream) return;
+       pvr2_stream_kill(cp->stream->stream);
+       cp->stream->user = NULL;
+       cp->stream = NULL;
+}
+
+
+void pvr2_channel_done(struct pvr2_channel *cp)
+{
+       struct pvr2_context *mp = cp->mc_head;
+       pvr2_channel_disclaim_stream(cp);
+       if (cp->mc_next) {
+               cp->mc_next->mc_prev = cp->mc_prev;
+       } else {
+               mp->mc_last = cp->mc_prev;
+       }
+       if (cp->mc_prev) {
+               cp->mc_prev->mc_next = cp->mc_next;
+       } else {
+               mp->mc_first = cp->mc_next;
+       }
+       cp->hdw = NULL;
+}
+
+
+int pvr2_channel_claim_stream(struct pvr2_channel *cp,
+                             struct pvr2_context_stream *sp)
+{
+       int code = 0;
+       pvr2_context_enter(cp->mc_head); do {
+               if (sp == cp->stream) break;
+               if (sp->user) {
+                       code = -EBUSY;
+                       break;
+               }
+               pvr2_channel_disclaim_stream(cp);
+               if (!sp) break;
+               sp->user = cp;
+               cp->stream = sp;
+       } while (0); pvr2_context_exit(cp->mc_head);
+       return code;
+}
+
+
+// This is the marker for the real beginning of a legitimate mpeg2 stream.
+static char stream_sync_key[] = {
+       0x00, 0x00, 0x01, 0xba,
+};
+
+struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+       struct pvr2_context_stream *sp)
+{
+       struct pvr2_ioread *cp;
+       cp = pvr2_ioread_create();
+       if (!cp) return NULL;
+       pvr2_ioread_setup(cp,sp->stream);
+       pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
+       return cp;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
new file mode 100644 (file)
index 0000000..6327fa1
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_BASE_H
+#define __PVRUSB2_BASE_H
+
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+
+struct pvr2_hdw;     /* hardware interface - defined elsewhere */
+struct pvr2_stream;  /* stream interface - defined elsewhere */
+
+struct pvr2_context;        /* All central state */
+struct pvr2_channel;        /* One I/O pathway to a user */
+struct pvr2_context_stream; /* Wrapper for a stream */
+struct pvr2_crit_reg;       /* Critical region pointer */
+struct pvr2_ioread;         /* Low level stream structure */
+
+struct pvr2_context_stream {
+       struct pvr2_channel *user;
+       struct pvr2_stream *stream;
+};
+
+struct pvr2_context {
+       struct pvr2_channel *mc_first;
+       struct pvr2_channel *mc_last;
+       struct pvr2_hdw *hdw;
+       struct pvr2_context_stream video_stream;
+       struct mutex mutex;
+       int disconnect_flag;
+
+       /* Called after pvr2_context initialization is complete */
+       void (*setup_func)(struct pvr2_context *);
+
+       /* Work queue overhead for out-of-line processing */
+       struct workqueue_struct *workqueue;
+       struct work_struct workinit;
+       struct work_struct workpoll;
+};
+
+struct pvr2_channel {
+       struct pvr2_context *mc_head;
+       struct pvr2_channel *mc_next;
+       struct pvr2_channel *mc_prev;
+       struct pvr2_context_stream *stream;
+       struct pvr2_hdw *hdw;
+       void (*check_func)(struct pvr2_channel *);
+};
+
+void pvr2_context_enter(struct pvr2_context *);
+void pvr2_context_exit(struct pvr2_context *);
+
+struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
+                                        const struct usb_device_id *devid,
+                                        void (*setup_func)(struct pvr2_context *));
+void pvr2_context_disconnect(struct pvr2_context *);
+
+void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
+void pvr2_channel_done(struct pvr2_channel *);
+int pvr2_channel_claim_stream(struct pvr2_channel *,
+                             struct pvr2_context_stream *);
+struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+       struct pvr2_context_stream *);
+
+
+#endif /* __PVRUSB2_CONTEXT_H */
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
new file mode 100644 (file)
index 0000000..c77de85
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-ctrl.h"
+#include "pvrusb2-hdw-internal.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
+{
+       return pvr2_ctrl_set_mask_value(cptr,~0,val);
+}
+
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
+{
+       int ret = 0;
+       if (!cptr) return -EINVAL;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->set_value != 0) {
+                       if (cptr->info->type == pvr2_ctl_bitmask) {
+                               mask &= cptr->info->def.type_bitmask.valid_bits;
+                       } else if (cptr->info->type == pvr2_ctl_int) {
+                               int lim;
+                               lim = cptr->info->def.type_int.min_value;
+                               if (cptr->info->get_min_value) {
+                                       cptr->info->get_min_value(cptr,&lim);
+                               }
+                               if (val < lim) break;
+                               lim = cptr->info->def.type_int.max_value;
+                               if (cptr->info->get_max_value) {
+                                       cptr->info->get_max_value(cptr,&lim);
+                               }
+                               if (val > lim) break;
+                       } else if (cptr->info->type == pvr2_ctl_enum) {
+                               if (val >= cptr->info->def.type_enum.count) {
+                                       break;
+                               }
+                       } else if (cptr->info->type != pvr2_ctl_bool) {
+                               break;
+                       }
+                       ret = cptr->info->set_value(cptr,mask,val);
+               } else {
+                       ret = -EPERM;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
+{
+       int ret = 0;
+       if (!cptr) return -EINVAL;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               ret = cptr->info->get_value(cptr,valptr);
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return pvr2_ctl_int;
+       return cptr->info->type;
+}
+
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->get_max_value) {
+                       cptr->info->get_max_value(cptr,&ret);
+               } else if (cptr->info->type == pvr2_ctl_int) {
+                       ret = cptr->info->def.type_int.max_value;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->get_min_value) {
+                       cptr->info->get_min_value(cptr,&ret);
+               } else if (cptr->info->type == pvr2_ctl_int) {
+                       ret = cptr->info->def.type_int.min_value;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
+{
+       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;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_enum) {
+                       ret = cptr->info->def.type_enum.count;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_bitmask) {
+                       ret = cptr->info->def.type_bitmask.valid_bits;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return NULL;
+       return cptr->info->name;
+}
+
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return NULL;
+       return cptr->info->desc;
+}
+
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
+                         char *bptr,unsigned int bmax,
+                         unsigned int *blen)
+{
+       int ret = -EINVAL;
+       if (!cptr) return 0;
+       *blen = 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_enum) {
+                       const char **names;
+                       names = cptr->info->def.type_enum.value_names;
+                       if ((val >= 0) &&
+                           (val < cptr->info->def.type_enum.count)) {
+                               if (names[val]) {
+                                       *blen = scnprintf(
+                                               bptr,bmax,"%s",
+                                               names[val]);
+                               } else {
+                                       *blen = 0;
+                               }
+                               ret = 0;
+                       }
+               } else if (cptr->info->type == pvr2_ctl_bitmask) {
+                       const char **names;
+                       unsigned int idx;
+                       int msk;
+                       names = cptr->info->def.type_bitmask.bit_names;
+                       val &= cptr->info->def.type_bitmask.valid_bits;
+                       for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
+                               if (val & msk) {
+                                       *blen = scnprintf(bptr,bmax,"%s",
+                                                         names[idx]);
+                                       ret = 0;
+                                       break;
+                               }
+                       }
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return 0;
+       return cptr->info->v4l_id;
+}
+
+
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
+{
+       unsigned int flags = 0;
+
+       if (cptr->info->get_v4lflags) {
+               flags = cptr->info->get_v4lflags(cptr);
+       }
+
+       if (cptr->info->set_value) {
+               flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+       } else {
+               flags |= V4L2_CTRL_FLAG_READ_ONLY;
+       }
+
+       return flags;
+}
+
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return 0;
+       return cptr->info->set_value != 0;
+}
+
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return 0;
+       if (!cptr->info->val_to_sym) return 0;
+       if (!cptr->info->sym_to_val) return 0;
+       return !0;
+}
+
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
+                                 int mask,int val,
+                                 char *buf,unsigned int maxlen,
+                                 unsigned int *len)
+{
+       if (!cptr) return -EINVAL;
+       if (!cptr->info->val_to_sym) return -EINVAL;
+       return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
+                                 const char *buf,unsigned int len,
+                                 int *maskptr,int *valptr)
+{
+       if (!cptr) return -EINVAL;
+       if (!cptr->info->sym_to_val) return -EINVAL;
+       return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
+}
+
+
+static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
+                                      const char **names,
+                                      char *ptr,unsigned int len)
+{
+       unsigned int idx;
+       long sm,um;
+       int spcFl;
+       unsigned int uc,cnt;
+       const char *idStr;
+
+       spcFl = 0;
+       uc = 0;
+       um = 0;
+       for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
+               if (sm & msk) {
+                       msk &= ~sm;
+                       idStr = names[idx];
+                       if (idStr) {
+                               cnt = scnprintf(ptr,len,"%s%s%s",
+                                               (spcFl ? " " : ""),
+                                               (msk_only ? "" :
+                                                ((val & sm) ? "+" : "-")),
+                                               idStr);
+                               ptr += cnt; len -= cnt; uc += cnt;
+                               spcFl = !0;
+                       } else {
+                               um |= sm;
+                       }
+               }
+       }
+       if (um) {
+               if (msk_only) {
+                       cnt = scnprintf(ptr,len,"%s0x%lx",
+                                       (spcFl ? " " : ""),
+                                       um);
+                       ptr += cnt; len -= cnt; uc += cnt;
+                       spcFl = !0;
+               } else if (um & val) {
+                       cnt = scnprintf(ptr,len,"%s+0x%lx",
+                                       (spcFl ? " " : ""),
+                                       um & val);
+                       ptr += cnt; len -= cnt; uc += cnt;
+                       spcFl = !0;
+               } else if (um & ~val) {
+                       cnt = scnprintf(ptr,len,"%s+0x%lx",
+                                       (spcFl ? " " : ""),
+                                       um & ~val);
+                       ptr += cnt; len -= cnt; uc += cnt;
+                       spcFl = !0;
+               }
+       }
+       return uc;
+}
+
+
+static const char *boolNames[] = {
+       "false",
+       "true",
+       "no",
+       "yes",
+};
+
+
+static int parse_token(const char *ptr,unsigned int len,
+                      int *valptr,
+                      const char **names,unsigned int namecnt)
+{
+       char buf[33];
+       unsigned int slen;
+       unsigned int idx;
+       int negfl;
+       char *p2;
+       *valptr = 0;
+       if (!names) namecnt = 0;
+       for (idx = 0; idx < namecnt; idx++) {
+               if (!names[idx]) continue;
+               slen = strlen(names[idx]);
+               if (slen != len) continue;
+               if (memcmp(names[idx],ptr,slen)) continue;
+               *valptr = idx;
+               return 0;
+       }
+       negfl = 0;
+       if ((*ptr == '-') || (*ptr == '+')) {
+               negfl = (*ptr == '-');
+               ptr++; len--;
+       }
+       if (len >= sizeof(buf)) return -EINVAL;
+       memcpy(buf,ptr,len);
+       buf[len] = 0;
+       *valptr = simple_strtol(buf,&p2,0);
+       if (negfl) *valptr = -(*valptr);
+       if (*p2) return -EINVAL;
+       return 1;
+}
+
+
+static int parse_mtoken(const char *ptr,unsigned int len,
+                       int *valptr,
+                       const char **names,int valid_bits)
+{
+       char buf[33];
+       unsigned int slen;
+       unsigned int idx;
+       char *p2;
+       int msk;
+       *valptr = 0;
+       for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
+               if (!msk & valid_bits) continue;
+               valid_bits &= ~msk;
+               if (!names[idx]) continue;
+               slen = strlen(names[idx]);
+               if (slen != len) continue;
+               if (memcmp(names[idx],ptr,slen)) continue;
+               *valptr = msk;
+               return 0;
+       }
+       if (len >= sizeof(buf)) return -EINVAL;
+       memcpy(buf,ptr,len);
+       buf[len] = 0;
+       *valptr = simple_strtol(buf,&p2,0);
+       if (*p2) return -EINVAL;
+       return 0;
+}
+
+
+static int parse_tlist(const char *ptr,unsigned int len,
+                      int *maskptr,int *valptr,
+                      const char **names,int valid_bits)
+{
+       unsigned int cnt;
+       int mask,val,kv,mode,ret;
+       mask = 0;
+       val = 0;
+       ret = 0;
+       while (len) {
+               cnt = 0;
+               while ((cnt < len) &&
+                      ((ptr[cnt] <= 32) ||
+                       (ptr[cnt] >= 127))) cnt++;
+               ptr += cnt;
+               len -= cnt;
+               mode = 0;
+               if ((*ptr == '-') || (*ptr == '+')) {
+                       mode = (*ptr == '-') ? -1 : 1;
+                       ptr++;
+                       len--;
+               }
+               cnt = 0;
+               while (cnt < len) {
+                       if (ptr[cnt] <= 32) break;
+                       if (ptr[cnt] >= 127) break;
+                       cnt++;
+               }
+               if (!cnt) break;
+               if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ptr += cnt;
+               len -= cnt;
+               switch (mode) {
+               case 0:
+                       mask = valid_bits;
+                       val |= kv;
+                       break;
+               case -1:
+                       mask |= kv;
+                       val &= ~kv;
+                       break;
+               case 1:
+                       mask |= kv;
+                       val |= kv;
+                       break;
+               default:
+                       break;
+               }
+       }
+       *maskptr = mask;
+       *valptr = val;
+       return ret;
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
+                          const char *ptr,unsigned int len,
+                          int *maskptr,int *valptr)
+{
+       int ret = -EINVAL;
+       unsigned int cnt;
+
+       *maskptr = 0;
+       *valptr = 0;
+
+       cnt = 0;
+       while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
+       len -= cnt; ptr += cnt;
+       cnt = 0;
+       while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
+                              (ptr[len-(cnt+1)] >= 127))) cnt++;
+       len -= cnt;
+
+       if (!len) return -EINVAL;
+
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_int) {
+                       ret = parse_token(ptr,len,valptr,NULL,0);
+                       if ((ret >= 0) &&
+                           ((*valptr < cptr->info->def.type_int.min_value) ||
+                            (*valptr > cptr->info->def.type_int.max_value))) {
+                               ret = -ERANGE;
+                       }
+                       if (maskptr) *maskptr = ~0;
+               } else if (cptr->info->type == pvr2_ctl_bool) {
+                       ret = parse_token(
+                               ptr,len,valptr,boolNames,
+                               sizeof(boolNames)/sizeof(boolNames[0]));
+                       if (ret == 1) {
+                               *valptr = *valptr ? !0 : 0;
+                       } else if (ret == 0) {
+                               *valptr = (*valptr & 1) ? !0 : 0;
+                       }
+                       if (maskptr) *maskptr = 1;
+               } else if (cptr->info->type == pvr2_ctl_enum) {
+                       ret = parse_token(
+                               ptr,len,valptr,
+                               cptr->info->def.type_enum.value_names,
+                               cptr->info->def.type_enum.count);
+                       if ((ret >= 0) &&
+                           ((*valptr < 0) ||
+                            (*valptr >= cptr->info->def.type_enum.count))) {
+                               ret = -ERANGE;
+                       }
+                       if (maskptr) *maskptr = ~0;
+               } else if (cptr->info->type == pvr2_ctl_bitmask) {
+                       ret = parse_tlist(
+                               ptr,len,maskptr,valptr,
+                               cptr->info->def.type_bitmask.bit_names,
+                               cptr->info->def.type_bitmask.valid_bits);
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
+                                   int mask,int val,
+                                   char *buf,unsigned int maxlen,
+                                   unsigned int *len)
+{
+       int ret = -EINVAL;
+
+       *len = 0;
+       if (cptr->info->type == pvr2_ctl_int) {
+               *len = scnprintf(buf,maxlen,"%d",val);
+               ret = 0;
+       } else if (cptr->info->type == pvr2_ctl_bool) {
+               *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
+               ret = 0;
+       } else if (cptr->info->type == pvr2_ctl_enum) {
+               const char **names;
+               names = cptr->info->def.type_enum.value_names;
+               if ((val >= 0) &&
+                   (val < cptr->info->def.type_enum.count)) {
+                       if (names[val]) {
+                               *len = scnprintf(
+                                       buf,maxlen,"%s",
+                                       names[val]);
+                       } else {
+                               *len = 0;
+                       }
+                       ret = 0;
+               }
+       } else if (cptr->info->type == pvr2_ctl_bitmask) {
+               *len = gen_bitmask_string(
+                       val & mask & cptr->info->def.type_bitmask.valid_bits,
+                       ~0,!0,
+                       cptr->info->def.type_bitmask.bit_names,
+                       buf,maxlen);
+       }
+       return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
+                          int mask,int val,
+                          char *buf,unsigned int maxlen,
+                          unsigned int *len)
+{
+       int ret;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
+                                                     buf,maxlen,len);
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
new file mode 100644 (file)
index 0000000..c168005
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_CTRL_H
+#define __PVRUSB2_CTRL_H
+
+struct pvr2_ctrl;
+
+enum pvr2_ctl_type {
+       pvr2_ctl_int = 0,
+       pvr2_ctl_enum = 1,
+       pvr2_ctl_bitmask = 2,
+       pvr2_ctl_bool = 3,
+};
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val);
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr);
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *);
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *);
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *);
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *);
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *);
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int,
+                         unsigned int *);
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *);
+
+/* Return V4L flags value for control (or zero if there is no v4l control
+   actually under this control) */
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *);
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *);
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *);
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *,
+                                 int mask,int val,
+                                 char *buf,unsigned int maxlen,
+                                 unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *,
+                                 const char *buf,unsigned int len,
+                                 int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *,
+                          int mask,int val,
+                          char *buf,unsigned int maxlen,
+                          unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *,
+                          const char *buf,unsigned int len,
+                          int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value - must already be
+   inside of critical region. */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
+                          int mask,int val,
+                          char *buf,unsigned int maxlen,
+                          unsigned int *len);
+
+#endif /* __PVRUSB2_CTRL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
new file mode 100644 (file)
index 0000000..c80c26b
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   cx2584x, in kernels 2.6.16 or newer.
+
+*/
+
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <media/cx25840.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct pvr2_v4l_cx2584x {
+       struct pvr2_i2c_handler handler;
+       struct pvr2_decoder_ctrl ctrl;
+       struct pvr2_i2c_client *client;
+       struct pvr2_hdw *hdw;
+       unsigned long stale_mask;
+};
+
+
+static void set_input(struct pvr2_v4l_cx2584x *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       struct v4l2_routing route;
+       enum cx25840_video_input vid_input;
+       enum cx25840_audio_input aud_input;
+
+       memset(&route,0,sizeof(route));
+
+       switch(hdw->input_val) {
+       case PVR2_CVAL_INPUT_TV:
+               vid_input = CX25840_COMPOSITE7;
+               aud_input = CX25840_AUDIO8;
+               break;
+       case PVR2_CVAL_INPUT_COMPOSITE:
+               vid_input = CX25840_COMPOSITE3;
+               aud_input = CX25840_AUDIO_SERIAL;
+               break;
+       case PVR2_CVAL_INPUT_SVIDEO:
+               vid_input = CX25840_SVIDEO1;
+               aud_input = CX25840_AUDIO_SERIAL;
+               break;
+       case PVR2_CVAL_INPUT_RADIO:
+       default:
+               // Just set it to be composite input for now...
+               vid_input = CX25840_COMPOSITE3;
+               aud_input = CX25840_AUDIO_SERIAL;
+               break;
+       }
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
+                  vid_input,aud_input);
+       route.input = (u32)vid_input;
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
+       route.input = (u32)aud_input;
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
+}
+
+
+static int check_input(struct pvr2_v4l_cx2584x *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       return hdw->input_dirty != 0;
+}
+
+
+static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
+{
+       u32 val;
+       struct pvr2_hdw *hdw = ctxt->hdw;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
+                  hdw->srate_val);
+       switch (hdw->srate_val) {
+       default:
+       case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+               val = 48000;
+               break;
+       case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+               val = 44100;
+               break;
+       case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+               val = 32000;
+               break;
+       }
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
+}
+
+
+static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       return hdw->srate_dirty != 0;
+}
+
+
+struct pvr2_v4l_cx2584x_ops {
+       void (*update)(struct pvr2_v4l_cx2584x *);
+       int (*check)(struct pvr2_v4l_cx2584x *);
+};
+
+
+static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
+       { .update = set_input, .check = check_input},
+       { .update = set_audio, .check = check_audio},
+};
+
+
+static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
+{
+       ctxt->client->handler = NULL;
+       ctxt->hdw->decoder_ctrl = NULL;
+       kfree(ctxt);
+}
+
+
+static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (ctxt->stale_mask & msk) continue;
+               if (decoder_ops[idx].check(ctxt)) {
+                       ctxt->stale_mask |= msk;
+               }
+       }
+       return ctxt->stale_mask != 0;
+}
+
+
+static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (!(ctxt->stale_mask & msk)) continue;
+               ctxt->stale_mask &= ~msk;
+               decoder_ops[idx].update(ctxt);
+       }
+}
+
+
+static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl)
+{
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl);
+       pvr2_v4l2_cmd_stream(ctxt->client,fl);
+}
+
+
+static int decoder_detect(struct pvr2_i2c_client *cp)
+{
+       int ret;
+       /* Attempt to query the decoder - let's see if it will answer */
+       struct v4l2_queryctrl qc;
+
+       memset(&qc,0,sizeof(qc));
+
+       qc.id = V4L2_CID_BRIGHTNESS;
+
+       ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc);
+       return ret == 0; /* Return true if it answered */
+}
+
+
+static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt)
+{
+       struct v4l2_tuner vt;
+       int ret;
+
+       memset(&vt,0,sizeof(vt));
+       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
+       if (ret < 0) return -EINVAL;
+       return vt.signal ? 1 : 0;
+}
+
+
+static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
+                                    char *buf,unsigned int cnt)
+{
+       return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l");
+}
+
+
+static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
+{
+       int ret;
+       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL);
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
+}
+
+
+const static struct pvr2_i2c_handler_functions hfuncs = {
+       .detach = (void (*)(void *))decoder_detach,
+       .check = (int (*)(void *))decoder_check,
+       .update = (void (*)(void *))decoder_update,
+       .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
+};
+
+
+int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
+                              struct pvr2_i2c_client *cp)
+{
+       struct pvr2_v4l_cx2584x *ctxt;
+
+       if (hdw->decoder_ctrl) return 0;
+       if (cp->handler) return 0;
+       if (!decoder_detect(cp)) return 0;
+
+       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       if (!ctxt) return 0;
+       memset(ctxt,0,sizeof(*ctxt));
+
+       ctxt->handler.func_data = ctxt;
+       ctxt->handler.func_table = &hfuncs;
+       ctxt->ctrl.ctxt = ctxt;
+       ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
+       ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
+       ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
+       ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
+       ctxt->client = cp;
+       ctxt->hdw = hdw;
+       ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
+                                 sizeof(decoder_ops[0]))) - 1;
+       hdw->decoder_ctrl = &ctxt->ctrl;
+       cp->handler = &ctxt->handler;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
+                  cp->client->addr);
+       return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
new file mode 100644 (file)
index 0000000..54b2844
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_CX2584X_V4L_H
+#define __PVRUSB2_CX2584X_V4L_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles combined device audio & video processing.
+   This interface is used internally by the driver; higher level code
+   should only interact through the interface provided by
+   pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+
+#endif /* __PVRUSB2_CX2584X_V4L_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
new file mode 100644 (file)
index 0000000..d95a858
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_DEBUG_H
+#define __PVRUSB2_DEBUG_H
+
+extern int pvrusb2_debug;
+
+#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0)
+
+/* These are listed in *rough* order of decreasing usefulness and
+   increasing noise level. */
+#define PVR2_TRACE_INFO       (1 <<  0) // Normal messages
+#define PVR2_TRACE_ERROR_LEGS (1 <<  1) // error messages
+#define PVR2_TRACE_TOLERANCE  (1 <<  2) // track tolerance-affected errors
+#define PVR2_TRACE_TRAP       (1 <<  3) // Trap & report misbehavior from app
+#define PVR2_TRACE_INIT       (1 <<  4) // misc initialization steps
+#define PVR2_TRACE_START_STOP (1 <<  5) // Streaming start / stop
+#define PVR2_TRACE_CTL        (1 <<  6) // commit of control changes
+#define PVR2_TRACE_DEBUG      (1 <<  7) // Temporary debug code
+#define PVR2_TRACE_EEPROM     (1 <<  8) // eeprom parsing / report
+#define PVR2_TRACE_STRUCT     (1 <<  9) // internal struct creation
+#define PVR2_TRACE_OPEN_CLOSE (1 << 10) // application open / close
+#define PVR2_TRACE_CREG       (1 << 11) // Main critical region entry / exit
+#define PVR2_TRACE_SYSFS      (1 << 12) // Sysfs driven I/O
+#define PVR2_TRACE_FIRMWARE   (1 << 13) // firmware upload actions
+#define PVR2_TRACE_CHIPS      (1 << 14) // chip broadcast operation
+#define PVR2_TRACE_I2C        (1 << 15) // I2C related stuff
+#define PVR2_TRACE_I2C_CMD    (1 << 16) // Software commands to I2C modules
+#define PVR2_TRACE_I2C_CORE   (1 << 17) // I2C core debugging
+#define PVR2_TRACE_I2C_TRAF   (1 << 18) // I2C traffic through the adapter
+#define PVR2_TRACE_V4LIOCTL   (1 << 19) // v4l ioctl details
+#define PVR2_TRACE_ENCODER    (1 << 20) // mpeg2 encoder operation
+#define PVR2_TRACE_BUF_POOL   (1 << 21) // Track buffer pool management
+#define PVR2_TRACE_BUF_FLOW   (1 << 22) // Track buffer flow in system
+#define PVR2_TRACE_DATA_FLOW  (1 << 23) // Track data flow
+#define PVR2_TRACE_DEBUGIFC   (1 << 24) // Debug interface actions
+#define PVR2_TRACE_GPIO       (1 << 25) // GPIO state bit changes
+
+
+#endif /* __PVRUSB2_HDW_INTERNAL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
new file mode 100644 (file)
index 0000000..f985f00
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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/string.h>
+#include <linux/slab.h>
+#include "pvrusb2-debugifc.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-i2c-core.h"
+
+struct debugifc_mask_item {
+       const char *name;
+       unsigned long msk;
+};
+
+static struct debugifc_mask_item mask_items[] = {
+       {"ENC_FIRMWARE",(1<<PVR2_SUBSYS_B_ENC_FIRMWARE)},
+       {"ENC_CFG",(1<<PVR2_SUBSYS_B_ENC_CFG)},
+       {"DIG_RUN",(1<<PVR2_SUBSYS_B_DIGITIZER_RUN)},
+       {"USB_RUN",(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)},
+       {"ENC_RUN",(1<<PVR2_SUBSYS_B_ENC_RUN)},
+};
+
+
+static unsigned int debugifc_count_whitespace(const char *buf,
+                                             unsigned int count)
+{
+       unsigned int scnt;
+       char ch;
+
+       for (scnt = 0; scnt < count; scnt++) {
+               ch = buf[scnt];
+               if (ch == ' ') continue;
+               if (ch == '\t') continue;
+               if (ch == '\n') continue;
+               break;
+       }
+       return scnt;
+}
+
+
+static unsigned int debugifc_count_nonwhitespace(const char *buf,
+                                                unsigned int count)
+{
+       unsigned int scnt;
+       char ch;
+
+       for (scnt = 0; scnt < count; scnt++) {
+               ch = buf[scnt];
+               if (ch == ' ') break;
+               if (ch == '\t') break;
+               if (ch == '\n') break;
+       }
+       return scnt;
+}
+
+
+static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
+                                         const char **wstrPtr,
+                                         unsigned int *wlenPtr)
+{
+       const char *wptr;
+       unsigned int consume_cnt = 0;
+       unsigned int wlen;
+       unsigned int scnt;
+
+       wptr = NULL;
+       wlen = 0;
+       scnt = debugifc_count_whitespace(buf,count);
+       consume_cnt += scnt; count -= scnt; buf += scnt;
+       if (!count) goto done;
+
+       scnt = debugifc_count_nonwhitespace(buf,count);
+       if (!scnt) goto done;
+       wptr = buf;
+       wlen = scnt;
+       consume_cnt += scnt; count -= scnt; buf += scnt;
+
+ done:
+       *wstrPtr = wptr;
+       *wlenPtr = wlen;
+       return consume_cnt;
+}
+
+
+static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
+                                         u32 *num_ptr)
+{
+       u32 result = 0;
+       u32 val;
+       int ch;
+       int radix = 10;
+       if ((count >= 2) && (buf[0] == '0') &&
+           ((buf[1] == 'x') || (buf[1] == 'X'))) {
+               radix = 16;
+               count -= 2;
+               buf += 2;
+       } else if ((count >= 1) && (buf[0] == '0')) {
+               radix = 8;
+       }
+
+       while (count--) {
+               ch = *buf++;
+               if ((ch >= '0') && (ch <= '9')) {
+                       val = ch - '0';
+               } else if ((ch >= 'a') && (ch <= 'f')) {
+                       val = ch - 'a' + 10;
+               } else if ((ch >= 'A') && (ch <= 'F')) {
+                       val = ch - 'A' + 10;
+               } else {
+                       return -EINVAL;
+               }
+               if (val >= radix) return -EINVAL;
+               result *= radix;
+               result += val;
+       }
+       *num_ptr = result;
+       return 0;
+}
+
+
+static int debugifc_match_keyword(const char *buf,unsigned int count,
+                                 const char *keyword)
+{
+       unsigned int kl;
+       if (!keyword) return 0;
+       kl = strlen(keyword);
+       if (kl != count) return 0;
+       return !memcmp(buf,keyword,kl);
+}
+
+
+static unsigned long debugifc_find_mask(const char *buf,unsigned int count)
+{
+       struct debugifc_mask_item *mip;
+       unsigned int idx;
+       for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+               mip = mask_items + idx;
+               if (debugifc_match_keyword(buf,count,mip->name)) {
+                       return mip->msk;
+               }
+       }
+       return 0;
+}
+
+
+static int debugifc_print_mask(char *buf,unsigned int sz,
+                              unsigned long msk,unsigned long val)
+{
+       struct debugifc_mask_item *mip;
+       unsigned int idx;
+       int bcnt = 0;
+       int ccnt;
+       for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+               mip = mask_items + idx;
+               if (!(mip->msk & msk)) continue;
+               ccnt = scnprintf(buf,sz,"%s%c%s",
+                                (bcnt ? " " : ""),
+                                ((mip->msk & val) ? '+' : '-'),
+                                mip->name);
+               sz -= ccnt;
+               buf += ccnt;
+               bcnt += ccnt;
+       }
+       return bcnt;
+}
+
+static unsigned int debugifc_parse_subsys_mask(const char *buf,
+                                              unsigned int count,
+                                              unsigned long *mskPtr,
+                                              unsigned long *valPtr)
+{
+       const char *wptr;
+       unsigned int consume_cnt = 0;
+       unsigned int scnt;
+       unsigned int wlen;
+       int mode;
+       unsigned long m1,msk,val;
+
+       msk = 0;
+       val = 0;
+
+       while (count) {
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) break;
+               consume_cnt += scnt; count -= scnt; buf += scnt;
+               if (!wptr) break;
+
+               mode = 0;
+               if (wlen) switch (wptr[0]) {
+               case '+':
+                       wptr++;
+                       wlen--;
+                       break;
+               case '-':
+                       mode = 1;
+                       wptr++;
+                       wlen--;
+                       break;
+               }
+               if (!wlen) continue;
+               m1 = debugifc_find_mask(wptr,wlen);
+               if (!m1) break;
+               msk |= m1;
+               if (!mode) val |= m1;
+       }
+       *mskPtr = msk;
+       *valPtr = val;
+       return consume_cnt;
+}
+
+
+int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
+{
+       int bcnt = 0;
+       int ccnt;
+       struct pvr2_hdw_debug_info dbg;
+
+       pvr2_hdw_get_debug_info(hdw,&dbg);
+
+       ccnt = scnprintf(buf,acnt,"big lock %s; ctl lock %s",
+                        (dbg.big_lock_held ? "held" : "free"),
+                        (dbg.ctl_lock_held ? "held" : "free"));
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       if (dbg.ctl_lock_held) {
+               ccnt = scnprintf(buf,acnt,"; cmd_state=%d cmd_code=%d"
+                                " cmd_wlen=%d cmd_rlen=%d"
+                                " wpend=%d rpend=%d tmout=%d rstatus=%d"
+                                " wstatus=%d",
+                                dbg.cmd_debug_state,dbg.cmd_code,
+                                dbg.cmd_debug_write_len,
+                                dbg.cmd_debug_read_len,
+                                dbg.cmd_debug_write_pend,
+                                dbg.cmd_debug_read_pend,
+                                dbg.cmd_debug_timeout,
+                                dbg.cmd_debug_rstatus,
+                                dbg.cmd_debug_wstatus);
+               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       }
+       ccnt = scnprintf(buf,acnt,"\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(
+               buf,acnt,"driver flags: %s %s %s\n",
+               (dbg.flag_init_ok ? "initialized" : "uninitialized"),
+               (dbg.flag_ok ? "ok" : "fail"),
+               (dbg.flag_disconnected ? "disconnected" : "connected"));
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: ");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = debugifc_print_mask(buf,acnt,dbg.subsys_flags,dbg.subsys_flags);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: ");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = debugifc_print_mask(buf,acnt,~dbg.subsys_flags,dbg.subsys_flags);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = pvr2_i2c_report(hdw,buf,acnt);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       return bcnt;
+}
+
+
+int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+                              char *buf,unsigned int acnt)
+{
+       int bcnt = 0;
+       int ccnt;
+       unsigned long msk;
+       int ret;
+       u32 gpio_dir,gpio_in,gpio_out;
+
+       ret = pvr2_hdw_is_hsm(hdw);
+       ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
+                        (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       gpio_dir = 0; gpio_in = 0; gpio_out = 0;
+       pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
+       pvr2_hdw_gpio_get_out(hdw,&gpio_out);
+       pvr2_hdw_gpio_get_in(hdw,&gpio_in);
+       ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
+                        gpio_dir,gpio_in,gpio_out);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
+                        pvr2_hdw_get_streaming(hdw) ? "on" : "off");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       msk = pvr2_hdw_subsys_get(hdw);
+       ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: ");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = debugifc_print_mask(buf,acnt,msk,msk);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: ");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = debugifc_print_mask(buf,acnt,~msk,msk);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       msk = pvr2_hdw_subsys_stream_get(hdw);
+       ccnt = scnprintf(buf,acnt,"Subsystems stopped on stream shutdown: ");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = debugifc_print_mask(buf,acnt,msk,msk);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       return bcnt;
+}
+
+
+static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
+                               unsigned int count)
+{
+       const char *wptr;
+       unsigned int wlen;
+       unsigned int scnt;
+
+       scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+       if (!scnt) return 0;
+       count -= scnt; buf += scnt;
+       if (!wptr) return 0;
+
+       pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
+       if (debugifc_match_keyword(wptr,wlen,"reset")) {
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               if (debugifc_match_keyword(wptr,wlen,"cpu")) {
+                       pvr2_hdw_cpureset_assert(hdw,!0);
+                       pvr2_hdw_cpureset_assert(hdw,0);
+                       return 0;
+               } else if (debugifc_match_keyword(wptr,wlen,"bus")) {
+                       pvr2_hdw_device_reset(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"soft")) {
+                       return pvr2_hdw_cmd_powerup(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"deep")) {
+                       return pvr2_hdw_cmd_deep_reset(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
+                       return pvr2_upload_firmware2(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
+                       return pvr2_hdw_cmd_decoder_reset(hdw);
+               }
+               return -EINVAL;
+       } else if (debugifc_match_keyword(wptr,wlen,"subsys_flags")) {
+               unsigned long msk = 0;
+               unsigned long val = 0;
+               if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) {
+                       pvr2_trace(PVR2_TRACE_DEBUGIFC,
+                                  "debugifc parse error on subsys mask");
+                       return -EINVAL;
+               }
+               pvr2_hdw_subsys_bit_chg(hdw,msk,val);
+               return 0;
+       } else if (debugifc_match_keyword(wptr,wlen,"stream_flags")) {
+               unsigned long msk = 0;
+               unsigned long val = 0;
+               if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) {
+                       pvr2_trace(PVR2_TRACE_DEBUGIFC,
+                                  "debugifc parse error on stream mask");
+                       return -EINVAL;
+               }
+               pvr2_hdw_subsys_stream_bit_chg(hdw,msk,val);
+               return 0;
+       } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               if (debugifc_match_keyword(wptr,wlen,"fetch")) {
+                       pvr2_hdw_cpufw_set_enabled(hdw,!0);
+                       return 0;
+               } else if (debugifc_match_keyword(wptr,wlen,"done")) {
+                       pvr2_hdw_cpufw_set_enabled(hdw,0);
+                       return 0;
+               } else {
+                       return -EINVAL;
+               }
+       } else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
+               int dir_fl = 0;
+               int ret;
+               u32 msk,val;
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               if (debugifc_match_keyword(wptr,wlen,"dir")) {
+                       dir_fl = !0;
+               } else if (!debugifc_match_keyword(wptr,wlen,"out")) {
+                       return -EINVAL;
+               }
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
+               if (ret) return ret;
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (wptr) {
+                       ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
+                       if (ret) return ret;
+               } else {
+                       val = msk;
+                       msk = 0xffffffff;
+               }
+               if (dir_fl) {
+                       ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
+               } else {
+                       ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
+               }
+               return ret;
+       }
+       pvr2_trace(PVR2_TRACE_DEBUGIFC,
+                  "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
+       return -EINVAL;
+}
+
+
+int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
+                       unsigned int count)
+{
+       unsigned int bcnt = 0;
+       int ret;
+
+       while (count) {
+               for (bcnt = 0; bcnt < count; bcnt++) {
+                       if (buf[bcnt] == '\n') break;
+               }
+
+               ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
+               if (ret < 0) return ret;
+               if (bcnt < count) bcnt++;
+               buf += bcnt;
+               count -= bcnt;
+       }
+
+       return 0;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
new file mode 100644 (file)
index 0000000..990b02d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_DEBUGIFC_H
+#define __PVRUSB2_DEBUGIFC_H
+
+struct pvr2_hdw;
+
+/* Non-intrusively print some useful debugging info from inside the
+   driver.  This should work even if the driver appears to be
+   wedged. */
+int pvr2_debugifc_print_info(struct pvr2_hdw *,
+                            char *buf_ptr,unsigned int buf_size);
+
+/* Print general status of driver.  This will also trigger a probe of
+   the USB link.  Unlike print_info(), this one synchronizes with the
+   driver so the information should be self-consistent (but it will
+   hang if the driver is wedged). */
+int pvr2_debugifc_print_status(struct pvr2_hdw *,
+                              char *buf_ptr,unsigned int buf_size);
+
+/* Parse a string command into a driver action. */
+int pvr2_debugifc_docmd(struct pvr2_hdw *,
+                       const char *buf_ptr,unsigned int buf_size);
+
+#endif /* __PVRUSB2_DEBUGIFC_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
new file mode 100644 (file)
index 0000000..6cff8e7
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-eeprom.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
+
+
+
+/*
+
+   Read and analyze data in the eeprom.  Use tveeprom to figure out
+   the packet structure, since this is another Hauppauge device and
+   internally it has a family resemblence to ivtv-type devices
+
+*/
+
+#include <media/tveeprom.h>
+
+/* We seem to only be interested in the last 128 bytes of the EEPROM */
+#define EEPROM_SIZE 128
+
+/* Grab EEPROM contents, needed for direct method. */
+static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
+{
+       struct i2c_msg msg[2];
+       u8 *eeprom;
+       u8 iadd[2];
+       u8 addr;
+       u16 eepromSize;
+       unsigned int offs;
+       int ret;
+       int mode16 = 0;
+       unsigned pcnt,tcnt;
+       eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
+       if (!eeprom) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to allocate memory"
+                          " required to read eeprom");
+               return NULL;
+       }
+
+       trace_eeprom("Value for eeprom addr from controller was 0x%x",
+                    hdw->eeprom_addr);
+       addr = hdw->eeprom_addr;
+       /* Seems that if the high bit is set, then the *real* eeprom
+          address is shifted right now bit position (noticed this in
+          newer PVR USB2 hardware) */
+       if (addr & 0x80) addr >>= 1;
+
+       /* FX2 documentation states that a 16bit-addressed eeprom is
+          expected if the I2C address is an odd number (yeah, this is
+          strange but it's what they do) */
+       mode16 = (addr & 1);
+       eepromSize = (mode16 ? 4096 : 256);
+       trace_eeprom("Examining %d byte eeprom at location 0x%x"
+                    " using %d bit addressing",eepromSize,addr,
+                    mode16 ? 16 : 8);
+
+       msg[0].addr = addr;
+       msg[0].flags = 0;
+       msg[0].len = mode16 ? 2 : 1;
+       msg[0].buf = iadd;
+       msg[1].addr = addr;
+       msg[1].flags = I2C_M_RD;
+
+       /* We have to do the actual eeprom data fetch ourselves, because
+          (1) we're only fetching part of the eeprom, and (2) if we were
+          getting the whole thing our I2C driver can't grab it in one
+          pass - which is what tveeprom is otherwise going to attempt */
+       memset(eeprom,0,EEPROM_SIZE);
+       for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
+               pcnt = 16;
+               if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
+               offs = tcnt + (eepromSize - EEPROM_SIZE);
+               if (mode16) {
+                       iadd[0] = offs >> 8;
+                       iadd[1] = offs;
+               } else {
+                       iadd[0] = offs;
+               }
+               msg[1].len = pcnt;
+               msg[1].buf = eeprom+tcnt;
+               if ((ret = i2c_transfer(
+                            &hdw->i2c_adap,
+                            msg,sizeof(msg)/sizeof(msg[0]))) != 2) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "eeprom fetch set offs err=%d",ret);
+                       kfree(eeprom);
+                       return NULL;
+               }
+       }
+       return eeprom;
+}
+
+
+/* Directly call eeprom analysis function within tveeprom. */
+int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
+{
+       u8 *eeprom;
+       struct tveeprom tvdata;
+
+       memset(&tvdata,0,sizeof(tvdata));
+
+       eeprom = pvr2_eeprom_fetch(hdw);
+       if (!eeprom) return -EINVAL;
+
+       {
+               struct i2c_client fake_client;
+               /* Newer version expects a useless client interface */
+               fake_client.addr = hdw->eeprom_addr;
+               fake_client.adapter = &hdw->i2c_adap;
+               tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
+       }
+
+       trace_eeprom("eeprom assumed v4l tveeprom module");
+       trace_eeprom("eeprom direct call results:");
+       trace_eeprom("has_radio=%d",tvdata.has_radio);
+       trace_eeprom("tuner_type=%d",tvdata.tuner_type);
+       trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats);
+       trace_eeprom("audio_processor=%d",tvdata.audio_processor);
+       trace_eeprom("model=%d",tvdata.model);
+       trace_eeprom("revision=%d",tvdata.revision);
+       trace_eeprom("serial_number=%d",tvdata.serial_number);
+       trace_eeprom("rev_str=%s",tvdata.rev_str);
+       hdw->tuner_type = tvdata.tuner_type;
+       hdw->serial_number = tvdata.serial_number;
+       hdw->std_mask_eeprom = tvdata.tuner_formats;
+
+       kfree(eeprom);
+
+       return 0;
+}
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
new file mode 100644 (file)
index 0000000..8424297
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_EEPROM_H
+#define __PVRUSB2_EEPROM_H
+
+struct pvr2_hdw;
+
+int pvr2_eeprom_analyze(struct pvr2_hdw *);
+
+#endif /* __PVRUSB2_EEPROM_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
new file mode 100644 (file)
index 0000000..18a7073
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/device.h>   // for linux/firmware.h
+#include <linux/firmware.h>
+#include "pvrusb2-util.h"
+#include "pvrusb2-encoder.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+
+
+/* Firmware mailbox flags - definitions found from ivtv */
+#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
+#define IVTV_MBOX_DRIVER_DONE 0x00000002
+#define IVTV_MBOX_DRIVER_BUSY 0x00000001
+
+
+static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
+                                   const u32 *data, unsigned int dlen)
+{
+       unsigned int idx;
+       int ret;
+       unsigned int offs = 0;
+       unsigned int chunkCnt;
+
+       /*
+
+       Format: First byte must be 0x01.  Remaining 32 bit words are
+       spread out into chunks of 7 bytes each, little-endian ordered,
+       offset at zero within each 2 blank bytes following and a
+       single byte that is 0x44 plus the offset of the word.  Repeat
+       request for additional words, with offset adjusted
+       accordingly.
+
+       */
+       while (dlen) {
+               chunkCnt = 8;
+               if (chunkCnt > dlen) chunkCnt = dlen;
+               memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
+               hdw->cmd_buffer[0] = 0x01;
+               for (idx = 0; idx < chunkCnt; idx++) {
+                       hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs;
+                       PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7),
+                                         data[idx]);
+               }
+               ret = pvr2_send_request(hdw,
+                                       hdw->cmd_buffer,1+(chunkCnt*7),
+                                       NULL,0);
+               if (ret) return ret;
+               data += chunkCnt;
+               dlen -= chunkCnt;
+               offs += chunkCnt;
+       }
+
+       return 0;
+}
+
+
+static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
+                                  u32 *data, unsigned int dlen)
+{
+       unsigned int idx;
+       int ret;
+       unsigned int offs = 0;
+       unsigned int chunkCnt;
+
+       /*
+
+       Format: First byte must be 0x02 (status check) or 0x28 (read
+       back block of 32 bit words).  Next 6 bytes must be zero,
+       followed by a single byte of 0x44+offset for portion to be
+       read.  Returned data is packed set of 32 bits words that were
+       read.
+
+       */
+
+       while (dlen) {
+               chunkCnt = 16;
+               if (chunkCnt > dlen) chunkCnt = dlen;
+               memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
+               hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28;
+               hdw->cmd_buffer[7] = 0x44 + offs;
+               ret = pvr2_send_request(hdw,
+                                       hdw->cmd_buffer,8,
+                                       hdw->cmd_buffer,chunkCnt * 4);
+               if (ret) return ret;
+
+               for (idx = 0; idx < chunkCnt; idx++) {
+                       data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
+               }
+               data += chunkCnt;
+               dlen -= chunkCnt;
+               offs += chunkCnt;
+       }
+
+       return 0;
+}
+
+
+/* This prototype is set up to be compatible with the
+   cx2341x_mbox_func prototype in cx2341x.h, which should be in
+   kernels 2.6.18 or later.  We do this so that we can enable
+   cx2341x.ko to write to our encoder (by handing it a pointer to this
+   function).  For earlier kernels this doesn't really matter. */
+static int pvr2_encoder_cmd(void *ctxt,
+                           int cmd,
+                           int arg_cnt_send,
+                           int arg_cnt_recv,
+                           u32 *argp)
+{
+       unsigned int poll_count;
+       int ret = 0;
+       unsigned int idx;
+       /* These sizes look to be limited by the FX2 firmware implementation */
+       u32 wrData[16];
+       u32 rdData[16];
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
+
+
+       /*
+
+       The encoder seems to speak entirely using blocks 32 bit words.
+       In ivtv driver terms, this is a mailbox which we populate with
+       data and watch what the hardware does with it.  The first word
+       is a set of flags used to control the transaction, the second
+       word is the command to execute, the third byte is zero (ivtv
+       driver suggests that this is some kind of return value), and
+       the fourth byte is a specified timeout (windows driver always
+       uses 0x00060000 except for one case when it is zero).  All
+       successive words are the argument words for the command.
+
+       First, write out the entire set of words, with the first word
+       being zero.
+
+       Next, write out just the first word again, but set it to
+       IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
+       probably means "go").
+
+       Next, read back 16 words as status.  Check the first word,
+       which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
+       that bit is not set, then the command isn't done so repeat the
+       read.
+
+       Next, read back 32 words and compare with the original
+       arugments.  Hopefully they will match.
+
+       Finally, write out just the first word again, but set it to
+       0x0 this time (which probably means "idle").
+
+       */
+
+       if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Failed to write cx23416 command"
+                       " - too many input arguments"
+                       " (was given %u limit %u)",
+                       arg_cnt_send,
+                       (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4);
+               return -EINVAL;
+       }
+
+       if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Failed to write cx23416 command"
+                       " - too many return arguments"
+                       " (was given %u limit %u)",
+                       arg_cnt_recv,
+                       (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4);
+               return -EINVAL;
+       }
+
+
+       LOCK_TAKE(hdw->ctl_lock); do {
+
+               wrData[0] = 0;
+               wrData[1] = cmd;
+               wrData[2] = 0;
+               wrData[3] = 0x00060000;
+               for (idx = 0; idx < arg_cnt_send; idx++) {
+                       wrData[idx+4] = argp[idx];
+               }
+               for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
+                       wrData[idx+4] = 0;
+               }
+
+               ret = pvr2_encoder_write_words(hdw,wrData,idx);
+               if (ret) break;
+               wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
+               ret = pvr2_encoder_write_words(hdw,wrData,1);
+               if (ret) break;
+               poll_count = 0;
+               while (1) {
+                       if (poll_count < 10000000) poll_count++;
+                       ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
+                       if (ret) break;
+                       if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
+                               break;
+                       }
+                       if (poll_count == 100) {
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "***WARNING*** device's encoder"
+                                       " appears to be stuck"
+                                       " (status=0%08x)",rdData[0]);
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "Encoder command: 0x%02x",cmd);
+                               for (idx = 4; idx < arg_cnt_send; idx++) {
+                                       pvr2_trace(
+                                               PVR2_TRACE_ERROR_LEGS,
+                                               "Encoder arg%d: 0x%08x",
+                                               idx-3,wrData[idx]);
+                               }
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "Giving up waiting."
+                                       "  It is likely that"
+                                       " this is a bad idea...");
+                               ret = -EBUSY;
+                               break;
+                       }
+               }
+               if (ret) break;
+               wrData[0] = 0x7;
+               ret = pvr2_encoder_read_words(
+                       hdw,0,rdData,
+                       sizeof(rdData)/sizeof(rdData[0]));
+               if (ret) break;
+               for (idx = 0; idx < arg_cnt_recv; idx++) {
+                       argp[idx] = rdData[idx+4];
+               }
+
+               wrData[0] = 0x0;
+               ret = pvr2_encoder_write_words(hdw,wrData,1);
+               if (ret) break;
+
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
+                            int args, ...)
+{
+       va_list vl;
+       unsigned int idx;
+       u32 data[12];
+
+       if (args > sizeof(data)/sizeof(data[0])) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Failed to write cx23416 command"
+                       " - too many arguments"
+                       " (was given %u limit %u)",
+                       args,(unsigned int)(sizeof(data)/sizeof(data[0])));
+               return -EINVAL;
+       }
+
+       va_start(vl, args);
+       for (idx = 0; idx < args; idx++) {
+               data[idx] = va_arg(vl, u32);
+       }
+       va_end(vl);
+
+       return pvr2_encoder_cmd(hdw,cmd,args,0,data);
+}
+
+int pvr2_encoder_configure(struct pvr2_hdw *hdw)
+{
+       int ret;
+       pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
+                  " (cx2341x module)");
+       hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
+       hdw->enc_ctl_state.width = hdw->res_hor_val;
+       hdw->enc_ctl_state.height = hdw->res_ver_val;
+       hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur &
+                                      (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ?
+                                     0 : 1);
+
+       ret = 0;
+
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
+               0xf0, 0xf0);
+
+       /* setup firmware to notify us about some events (don't know why...) */
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
+               0, 0, 0x10000000, 0xffffffff);
+
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw,CX2341X_ENC_SET_VBI_LINE, 5,
+               0xffffffff,0,0,0,0);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to configure cx32416");
+               return ret;
+       }
+
+       ret = cx2341x_update(hdw,pvr2_encoder_cmd,
+                            (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
+                            &hdw->enc_ctl_state);
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Error from cx2341x module code=%d",ret);
+               return ret;
+       }
+
+       ret = 0;
+
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to initialize cx32416 video input");
+               return ret;
+       }
+
+       hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+       memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
+              sizeof(struct cx2341x_mpeg_params));
+       hdw->enc_cur_valid = !0;
+       return 0;
+}
+
+
+int pvr2_encoder_start(struct pvr2_hdw *hdw)
+{
+       int status;
+
+       /* unmask some interrupts */
+       pvr2_write_register(hdw, 0x0048, 0xbfffffff);
+
+       /* change some GPIO data */
+       pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
+       pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+
+       if (hdw->config == pvr2_config_vbi) {
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+                                          0x01,0x14);
+       } else if (hdw->config == pvr2_config_mpeg) {
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+                                          0,0x13);
+       } else {
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+                                          0,0x13);
+       }
+       if (!status) {
+               hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
+       }
+       return status;
+}
+
+int pvr2_encoder_stop(struct pvr2_hdw *hdw)
+{
+       int status;
+
+       /* mask all interrupts */
+       pvr2_write_register(hdw, 0x0048, 0xffffffff);
+
+       if (hdw->config == pvr2_config_vbi) {
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+                                          0x01,0x01,0x14);
+       } else if (hdw->config == pvr2_config_mpeg) {
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+                                          0x01,0,0x13);
+       } else {
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+                                          0x01,0,0x13);
+       }
+
+       /* change some GPIO data */
+       /* Note: Bit d7 of dir appears to control the LED.  So we shut it
+          off here. */
+       pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
+       pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+
+       if (!status) {
+               hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
+       }
+       return status;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/video/pvrusb2/pvrusb2-encoder.h
new file mode 100644 (file)
index 0000000..01b5a0b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_ENCODER_H
+#define __PVRUSB2_ENCODER_H
+
+struct pvr2_hdw;
+
+int pvr2_encoder_configure(struct pvr2_hdw *);
+int pvr2_encoder_start(struct pvr2_hdw *);
+int pvr2_encoder_stop(struct pvr2_hdw *);
+
+#endif /* __PVRUSB2_ENCODER_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
new file mode 100644 (file)
index 0000000..7dd6c3d
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_HDW_INTERNAL_H
+#define __PVRUSB2_HDW_INTERNAL_H
+
+/*
+
+  This header sets up all the internal structures and definitions needed to
+  track and coordinate the driver's interaction with the hardware.  ONLY
+  source files which actually implement part of that whole circus should be
+  including this header.  Higher levels, like the external layers to the
+  various public APIs (V4L, sysfs, etc) should NOT ever include this
+  private, internal header.  This means that pvrusb2-hdw, pvrusb2-encoder,
+  etc will include this, but pvrusb2-v4l should not.
+
+*/
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include <media/cx2341x.h>
+
+/* Legal values for the SRATE state variable */
+#define PVR2_CVAL_SRATE_48 0
+#define PVR2_CVAL_SRATE_44_1 1
+
+/* Legal values for the AUDIOBITRATE state variable */
+#define PVR2_CVAL_AUDIOBITRATE_384 0
+#define PVR2_CVAL_AUDIOBITRATE_320 1
+#define PVR2_CVAL_AUDIOBITRATE_256 2
+#define PVR2_CVAL_AUDIOBITRATE_224 3
+#define PVR2_CVAL_AUDIOBITRATE_192 4
+#define PVR2_CVAL_AUDIOBITRATE_160 5
+#define PVR2_CVAL_AUDIOBITRATE_128 6
+#define PVR2_CVAL_AUDIOBITRATE_112 7
+#define PVR2_CVAL_AUDIOBITRATE_96 8
+#define PVR2_CVAL_AUDIOBITRATE_80 9
+#define PVR2_CVAL_AUDIOBITRATE_64 10
+#define PVR2_CVAL_AUDIOBITRATE_56 11
+#define PVR2_CVAL_AUDIOBITRATE_48 12
+#define PVR2_CVAL_AUDIOBITRATE_32 13
+#define PVR2_CVAL_AUDIOBITRATE_VBR 14
+
+/* Legal values for the AUDIOEMPHASIS state variable */
+#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0
+#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1
+#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2
+
+/* Legal values for PVR2_CID_HSM */
+#define PVR2_CVAL_HSM_FAIL 0
+#define PVR2_CVAL_HSM_FULL 1
+#define PVR2_CVAL_HSM_HIGH 2
+
+#define PVR2_VID_ENDPOINT        0x84
+#define PVR2_UNK_ENDPOINT        0x86    /* maybe raw yuv ? */
+#define PVR2_VBI_ENDPOINT        0x88
+
+#define PVR2_CTL_BUFFSIZE        64
+
+#define FREQTABLE_SIZE 500
+
+#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0)
+#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0)
+
+struct pvr2_decoder;
+
+typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
+typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
+typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
+typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
+typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
+                                   char *,unsigned int,unsigned int *);
+typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *,
+                                   const char *,unsigned int,
+                                   int *mskp,int *valp);
+typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *);
+
+/* This structure describes a specific control.  A table of these is set up
+   in pvrusb2-hdw.c. */
+struct pvr2_ctl_info {
+       /* Control's name suitable for use as an identifier */
+       const char *name;
+
+       /* Short description of control */
+       const char *desc;
+
+       /* Control's implementation */
+       pvr2_ctlf_get_value get_value;      /* Get its 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 */
+       pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
+       pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
+       pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
+       pvr2_ctlf_clear_dirty clear_dirty;  /* Clear dirty state */
+       pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */
+
+       /* Control's type (int, enum, bitmask) */
+       enum pvr2_ctl_type type;
+
+       /* Associated V4L control ID, if any */
+       int v4l_id;
+
+       /* Associated driver internal ID, if any */
+       int internal_id;
+
+       /* Don't implicitly initialize this control's value */
+       int skip_init;
+
+       /* Starting value for this control */
+       int default_value;
+
+       /* Type-specific control information */
+       union {
+               struct { /* Integer control */
+                       long min_value; /* lower limit */
+                       long max_value; /* upper limit */
+               } type_int;
+               struct { /* enumerated control */
+                       unsigned int count;       /* enum value count */
+                       const char **value_names; /* symbol names */
+               } type_enum;
+               struct { /* bitmask control */
+                       unsigned int valid_bits; /* bits in use */
+                       const char **bit_names;  /* symbol name/bit */
+               } type_bitmask;
+       } def;
+};
+
+
+/* Same as pvr2_ctl_info, but includes storage for the control description */
+#define PVR2_CTLD_INFO_DESC_SIZE 32
+struct pvr2_ctld_info {
+       struct pvr2_ctl_info info;
+       char desc[PVR2_CTLD_INFO_DESC_SIZE];
+};
+
+struct pvr2_ctrl {
+       const struct pvr2_ctl_info *info;
+       struct pvr2_hdw *hdw;
+};
+
+
+struct pvr2_audio_stat {
+       void *ctxt;
+       void (*detach)(void *);
+       int (*status)(void *);
+};
+
+struct pvr2_decoder_ctrl {
+       void *ctxt;
+       void (*detach)(void *);
+       void (*enable)(void *,int);
+       int (*tuned)(void *);
+       void (*force_reset)(void *);
+};
+
+#define PVR2_I2C_PEND_DETECT  0x01  /* Need to detect a client type */
+#define PVR2_I2C_PEND_CLIENT  0x02  /* Client needs a specific update */
+#define PVR2_I2C_PEND_REFRESH 0x04  /* Client has specific pending bits */
+#define PVR2_I2C_PEND_STALE   0x08  /* Broadcast pending bits */
+
+#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\
+                          PVR2_I2C_PEND_CLIENT |\
+                          PVR2_I2C_PEND_REFRESH |\
+                          PVR2_I2C_PEND_STALE)
+
+/* Disposition of firmware1 loading situation */
+#define FW1_STATE_UNKNOWN 0
+#define FW1_STATE_MISSING 1
+#define FW1_STATE_FAILED 2
+#define FW1_STATE_RELOAD 3
+#define FW1_STATE_OK 4
+
+/* Known major hardware variants, keyed from device ID */
+#define PVR2_HDW_TYPE_29XXX 0
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+#define PVR2_HDW_TYPE_24XXX 1
+#endif
+
+typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+#define PVR2_I2C_FUNC_CNT 128
+
+/* This structure contains all state data directly needed to
+   manipulate the hardware (as opposed to complying with a kernel
+   interface) */
+struct pvr2_hdw {
+       /* Underlying USB device handle */
+       struct usb_device *usb_dev;
+       struct usb_interface *usb_intf;
+
+       /* Device type, one of PVR2_HDW_TYPE_xxxxx */
+       unsigned int hdw_type;
+
+       /* Video spigot */
+       struct pvr2_stream *vid_stream;
+
+       /* Mutex for all hardware state control */
+       struct mutex big_lock_mutex;
+       int big_lock_held;  /* For debugging */
+
+       void (*poll_trigger_func)(void *);
+       void *poll_trigger_data;
+
+       char name[32];
+
+       /* I2C stuff */
+       struct i2c_adapter i2c_adap;
+       struct i2c_algorithm i2c_algo;
+       pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
+       int i2c_cx25840_hack_state;
+       int i2c_linked;
+       unsigned int i2c_pend_types;    /* Which types of update are needed */
+       unsigned long i2c_pend_mask;    /* Change bits we need to scan */
+       unsigned long i2c_stale_mask;   /* Pending broadcast change bits */
+       unsigned long i2c_active_mask;  /* All change bits currently in use */
+       struct list_head i2c_clients;
+       struct mutex i2c_list_lock;
+
+       /* Frequency table */
+       unsigned int freqTable[FREQTABLE_SIZE];
+       unsigned int freqProgSlot;
+       unsigned int freqSlot;
+
+       /* Stuff for handling low level control interaction with device */
+       struct mutex ctl_lock_mutex;
+       int ctl_lock_held;  /* For debugging */
+       struct urb *ctl_write_urb;
+       struct urb *ctl_read_urb;
+       unsigned char *ctl_write_buffer;
+       unsigned char *ctl_read_buffer;
+       volatile int ctl_write_pend_flag;
+       volatile int ctl_read_pend_flag;
+       volatile int ctl_timeout_flag;
+       struct completion ctl_done;
+       unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE];
+       int cmd_debug_state;               // Low level command debugging info
+       unsigned char cmd_debug_code;      //
+       unsigned int cmd_debug_write_len;  //
+       unsigned int cmd_debug_read_len;   //
+
+       int flag_ok;            // device in known good state
+       int flag_disconnected;  // flag_ok == 0 due to disconnect
+       int flag_init_ok;       // true if structure is fully initialized
+       int flag_streaming_enabled; // true if streaming should be on
+       int fw1_state;          // current situation with fw1
+
+       int flag_decoder_is_tuned;
+
+       struct pvr2_decoder_ctrl *decoder_ctrl;
+
+       // CPU firmware info (used to help find / save firmware data)
+       char *fw_buffer;
+       unsigned int fw_size;
+
+       // Which subsystem pieces have been enabled / configured
+       unsigned long subsys_enabled_mask;
+
+       // Which subsystems are manipulated to enable streaming
+       unsigned long subsys_stream_mask;
+
+       // True if there is a request to trigger logging of state in each
+       // module.
+       int log_requested;
+
+       /* Tuner / frequency control stuff */
+       unsigned int tuner_type;
+       int tuner_updated;
+       unsigned int freqVal;
+       int freqDirty;
+
+       /* Video standard handling */
+       v4l2_std_id std_mask_eeprom; // Hardware supported selections
+       v4l2_std_id std_mask_avail;  // Which standards we may select from
+       v4l2_std_id std_mask_cur;    // Currently selected standard(s)
+       unsigned int std_enum_cnt;   // # of enumerated standards
+       int std_enum_cur;            // selected standard enumeration value
+       int std_dirty;               // True if std_mask_cur has changed
+       struct pvr2_ctl_info std_info_enum;
+       struct pvr2_ctl_info std_info_avail;
+       struct pvr2_ctl_info std_info_cur;
+       struct v4l2_standard *std_defs;
+       const char **std_enum_names;
+
+       // Generated string names, one per actual V4L2 standard
+       const char *std_mask_ptrs[32];
+       char std_mask_names[32][10];
+
+       int unit_number;             /* ID for driver instance */
+       unsigned long serial_number; /* ID for hardware itself */
+
+       /* Minor number used by v4l logic (yes, this is a hack, as there should
+          be no v4l junk here).  Probably a better way to do this. */
+       int v4l_minor_number;
+
+       /* Location of eeprom or a negative number if none */
+       int eeprom_addr;
+
+       enum pvr2_config config;
+
+       /* Information about what audio signal we're hearing */
+       int flag_stereo;
+       int flag_bilingual;
+       struct pvr2_audio_stat *audio_stat;
+
+       /* Control state needed for cx2341x module */
+       struct cx2341x_mpeg_params enc_cur_state;
+       struct cx2341x_mpeg_params enc_ctl_state;
+       /* True if an encoder attribute has changed */
+       int enc_stale;
+       /* True if enc_cur_state is valid */
+       int enc_cur_valid;
+
+       /* Control state */
+#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty
+       VCREATE_DATA(brightness);
+       VCREATE_DATA(contrast);
+       VCREATE_DATA(saturation);
+       VCREATE_DATA(hue);
+       VCREATE_DATA(volume);
+       VCREATE_DATA(balance);
+       VCREATE_DATA(bass);
+       VCREATE_DATA(treble);
+       VCREATE_DATA(mute);
+       VCREATE_DATA(input);
+       VCREATE_DATA(audiomode);
+       VCREATE_DATA(res_hor);
+       VCREATE_DATA(res_ver);
+       VCREATE_DATA(srate);
+#undef VCREATE_DATA
+
+       struct pvr2_ctld_info *mpeg_ctrl_info;
+
+       struct pvr2_ctrl *controls;
+       unsigned int control_cnt;
+};
+
+#endif /* __PVRUSB2_HDW_INTERNAL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
new file mode 100644 (file)
index 0000000..a36a69d
--- /dev/null
@@ -0,0 +1,3128 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/videodev2.h>
+#include <asm/semaphore.h>
+#include "pvrusb2.h"
+#include "pvrusb2-std.h"
+#include "pvrusb2-util.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-tuner.h"
+#include "pvrusb2-eeprom.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-encoder.h"
+#include "pvrusb2-debug.h"
+
+struct usb_device_id pvr2_device_table[] = {
+       [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+       [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
+#endif
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, pvr2_device_table);
+
+static const char *pvr2_device_names[] = {
+       [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+       [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",
+#endif
+};
+
+struct pvr2_string_table {
+       const char **lst;
+       unsigned int cnt;
+};
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+// Names of other client modules to request for 24xxx model hardware
+static const char *pvr2_client_24xxx[] = {
+       "cx25840",
+       "tuner",
+       "wm8775",
+};
+#endif
+
+// Names of other client modules to request for 29xxx model hardware
+static const char *pvr2_client_29xxx[] = {
+       "msp3400",
+       "saa7115",
+       "tuner",
+};
+
+static struct pvr2_string_table pvr2_client_lists[] = {
+       [PVR2_HDW_TYPE_29XXX] = {
+               pvr2_client_29xxx,
+               sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
+       },
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+       [PVR2_HDW_TYPE_24XXX] = {
+               pvr2_client_24xxx,
+               sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
+       },
+#endif
+};
+
+static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
+static DECLARE_MUTEX(pvr2_unit_sem);
+
+static int ctlchg = 0;
+static int initusbreset = 1;
+static int procreload = 0;
+static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
+static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int init_pause_msec = 0;
+
+module_param(ctlchg, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
+module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
+module_param(initusbreset, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");
+module_param(procreload, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(procreload,
+                "Attempt init failure recovery with firmware reload");
+module_param_array(tuner,    int, NULL, 0444);
+MODULE_PARM_DESC(tuner,"specify installed tuner type");
+module_param_array(video_std,    int, NULL, 0444);
+MODULE_PARM_DESC(video_std,"specify initial video standard");
+module_param_array(tolerance,    int, NULL, 0444);
+MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
+
+#define PVR2_CTL_WRITE_ENDPOINT  0x01
+#define PVR2_CTL_READ_ENDPOINT   0x81
+
+#define PVR2_GPIO_IN 0x9008
+#define PVR2_GPIO_OUT 0x900c
+#define PVR2_GPIO_DIR 0x9020
+
+#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__)
+
+#define PVR2_FIRMWARE_ENDPOINT   0x02
+
+/* size of a firmware chunk */
+#define FIRMWARE_CHUNK_SIZE 0x2000
+
+/* Define the list of additional controls we'll dynamically construct based
+   on query of the cx2341x module. */
+struct pvr2_mpeg_ids {
+       const char *strid;
+       int id;
+};
+static const struct pvr2_mpeg_ids mpeg_ids[] = {
+       {
+               .strid = "audio_layer",
+               .id = V4L2_CID_MPEG_AUDIO_ENCODING,
+       },{
+               .strid = "audio_bitrate",
+               .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+       },{
+               /* Already using audio_mode elsewhere :-( */
+               .strid = "mpeg_audio_mode",
+               .id = V4L2_CID_MPEG_AUDIO_MODE,
+       },{
+               .strid = "mpeg_audio_mode_extension",
+               .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+       },{
+               .strid = "audio_emphasis",
+               .id = V4L2_CID_MPEG_AUDIO_EMPHASIS,
+       },{
+               .strid = "audio_crc",
+               .id = V4L2_CID_MPEG_AUDIO_CRC,
+       },{
+               .strid = "video_aspect",
+               .id = V4L2_CID_MPEG_VIDEO_ASPECT,
+       },{
+               .strid = "video_b_frames",
+               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+       },{
+               .strid = "video_gop_size",
+               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+       },{
+               .strid = "video_gop_closure",
+               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+       },{
+               .strid = "video_pulldown",
+               .id = V4L2_CID_MPEG_VIDEO_PULLDOWN,
+       },{
+               .strid = "video_bitrate_mode",
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+       },{
+               .strid = "video_bitrate",
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+       },{
+               .strid = "video_bitrate_peak",
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+       },{
+               .strid = "video_temporal_decimation",
+               .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+       },{
+               .strid = "stream_type",
+               .id = V4L2_CID_MPEG_STREAM_TYPE,
+       },{
+               .strid = "video_spatial_filter_mode",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+       },{
+               .strid = "video_spatial_filter",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+       },{
+               .strid = "video_luma_spatial_filter_type",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+       },{
+               .strid = "video_chroma_spatial_filter_type",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+       },{
+               .strid = "video_temporal_filter_mode",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+       },{
+               .strid = "video_temporal_filter",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+       },{
+               .strid = "video_median_filter_type",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+       },{
+               .strid = "video_luma_median_filter_top",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+       },{
+               .strid = "video_luma_median_filter_bottom",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+       },{
+               .strid = "video_chroma_median_filter_top",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+       },{
+               .strid = "video_chroma_median_filter_bottom",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+       }
+};
+#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
+
+static const char *control_values_srate[] = {
+       [PVR2_CVAL_SRATE_48]   = "48KHz",
+       [PVR2_CVAL_SRATE_44_1] = "44.1KHz",
+};
+
+
+
+
+static const char *control_values_input[] = {
+       [PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
+       [PVR2_CVAL_INPUT_RADIO]     = "radio",
+       [PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
+       [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
+};
+
+
+static const char *control_values_audiomode[] = {
+       [V4L2_TUNER_MODE_MONO]   = "Mono",
+       [V4L2_TUNER_MODE_STEREO] = "Stereo",
+       [V4L2_TUNER_MODE_LANG1]  = "Lang1",
+       [V4L2_TUNER_MODE_LANG2]  = "Lang2",
+       [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2",
+};
+
+
+static const char *control_values_hsm[] = {
+       [PVR2_CVAL_HSM_FAIL] = "Fail",
+       [PVR2_CVAL_HSM_HIGH] = "High",
+       [PVR2_CVAL_HSM_FULL] = "Full",
+};
+
+
+static const char *control_values_subsystem[] = {
+       [PVR2_SUBSYS_B_ENC_FIRMWARE]  = "enc_firmware",
+       [PVR2_SUBSYS_B_ENC_CFG] = "enc_config",
+       [PVR2_SUBSYS_B_DIGITIZER_RUN] = "digitizer_run",
+       [PVR2_SUBSYS_B_USBSTREAM_RUN] = "usbstream_run",
+       [PVR2_SUBSYS_B_ENC_RUN] = "enc_run",
+};
+
+static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
+static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
+static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
+static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw);
+static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
+static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
+static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw);
+static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+                                           unsigned long msk,
+                                           unsigned long val);
+static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+                                                  unsigned long msk,
+                                                  unsigned long val);
+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_write_u16(struct pvr2_hdw *hdw, u16 data, int res);
+static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res);
+
+static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+               *vp = hdw->freqTable[hdw->freqProgSlot-1];
+       } else {
+               *vp = 0;
+       }
+       return 0;
+}
+
+static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+               hdw->freqTable[hdw->freqProgSlot-1] = v;
+       }
+       return 0;
+}
+
+static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->freqProgSlot;
+       return 0;
+}
+
+static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if ((v >= 0) && (v <= FREQTABLE_SIZE)) {
+               hdw->freqProgSlot = v;
+       }
+       return 0;
+}
+
+static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->freqSlot;
+       return 0;
+}
+
+static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       unsigned freq = 0;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       hdw->freqSlot = v;
+       if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) {
+               freq = hdw->freqTable[hdw->freqSlot-1];
+       }
+       if (freq && (freq != hdw->freqVal)) {
+               hdw->freqVal = freq;
+               hdw->freqDirty = !0;
+       }
+       return 0;
+}
+
+static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->freqVal;
+       return 0;
+}
+
+static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->freqDirty != 0;
+}
+
+static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->freqDirty = 0;
+}
+
+static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       hdw->freqVal = v;
+       hdw->freqDirty = !0;
+       hdw->freqSlot = 0;
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* If we're dealing with a 24xxx device, force the horizontal
+          maximum to be 720 no matter what, since we can't get the device
+          to work properly with any other value.  Otherwise just return
+          the normal value. */
+       *vp = cptr->info->def.type_int.max_value;
+       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
+       return 0;
+}
+
+static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* If we're dealing with a 24xxx device, force the horizontal
+          minimum to be 720 no matter what, since we can't get the device
+          to work properly with any other value.  Otherwise just return
+          the normal value. */
+       *vp = cptr->info->def.type_int.min_value;
+       if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
+       return 0;
+}
+#endif
+
+static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->enc_stale != 0;
+}
+
+static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->enc_stale = 0;
+}
+
+static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int ret;
+       struct v4l2_ext_controls cs;
+       struct v4l2_ext_control c1;
+       memset(&cs,0,sizeof(cs));
+       memset(&c1,0,sizeof(c1));
+       cs.controls = &c1;
+       cs.count = 1;
+       c1.id = cptr->info->v4l_id;
+       ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+                               VIDIOC_G_EXT_CTRLS);
+       if (ret) return ret;
+       *vp = c1.value;
+       return 0;
+}
+
+static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       int ret;
+       struct v4l2_ext_controls cs;
+       struct v4l2_ext_control c1;
+       memset(&cs,0,sizeof(cs));
+       memset(&c1,0,sizeof(c1));
+       cs.controls = &c1;
+       cs.count = 1;
+       c1.id = cptr->info->v4l_id;
+       c1.value = v;
+       ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+                               VIDIOC_S_EXT_CTRLS);
+       if (ret) return ret;
+       cptr->hdw->enc_stale = !0;
+       return 0;
+}
+
+static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
+{
+       struct v4l2_queryctrl qctrl;
+       struct pvr2_ctl_info *info;
+       qctrl.id = cptr->info->v4l_id;
+       cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);
+       /* Strip out the const so we can adjust a function pointer.  It's
+          OK to do this here because we know this is a dynamically created
+          control, so the underlying storage for the info pointer is (a)
+          private to us, and (b) not in read-only storage.  Either we do
+          this or we significantly complicate the underlying control
+          implementation. */
+       info = (struct pvr2_ctl_info *)(cptr->info);
+       if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
+               if (info->set_value) {
+                       info->set_value = NULL;
+               }
+       } else {
+               if (!(info->set_value)) {
+                       info->set_value = ctrl_cx2341x_set;
+               }
+       }
+       return qctrl.flags;
+}
+
+static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->flag_streaming_enabled;
+       return 0;
+}
+
+static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int result = pvr2_hdw_is_hsm(cptr->hdw);
+       *vp = PVR2_CVAL_HSM_FULL;
+       if (result < 0) *vp = PVR2_CVAL_HSM_FAIL;
+       if (result) *vp = PVR2_CVAL_HSM_HIGH;
+       return 0;
+}
+
+static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->std_mask_avail;
+       return 0;
+}
+
+static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       v4l2_std_id ns;
+       ns = hdw->std_mask_avail;
+       ns = (ns & ~m) | (v & m);
+       if (ns == hdw->std_mask_avail) return 0;
+       hdw->std_mask_avail = ns;
+       pvr2_hdw_internal_set_std_avail(hdw);
+       pvr2_hdw_internal_find_stdenum(hdw);
+       return 0;
+}
+
+static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val,
+                              char *bufPtr,unsigned int bufSize,
+                              unsigned int *len)
+{
+       *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val);
+       return 0;
+}
+
+static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr,
+                              const char *bufPtr,unsigned int bufSize,
+                              int *mskp,int *valp)
+{
+       int ret;
+       v4l2_std_id id;
+       ret = pvr2_std_str_to_id(&id,bufPtr,bufSize);
+       if (ret < 0) return ret;
+       if (mskp) *mskp = id;
+       if (valp) *valp = id;
+       return 0;
+}
+
+static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->std_mask_cur;
+       return 0;
+}
+
+static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       v4l2_std_id ns;
+       ns = hdw->std_mask_cur;
+       ns = (ns & ~m) | (v & m);
+       if (ns == hdw->std_mask_cur) return 0;
+       hdw->std_mask_cur = ns;
+       hdw->std_dirty = !0;
+       pvr2_hdw_internal_find_stdenum(hdw);
+       return 0;
+}
+
+static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->std_dirty != 0;
+}
+
+static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->std_dirty = 0;
+}
+
+static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
+               PVR2_SIGNAL_OK) ? 1 : 0);
+       return 0;
+}
+
+static int ctrl_subsys_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->subsys_enabled_mask;
+       return 0;
+}
+
+static int ctrl_subsys_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,m,v);
+       return 0;
+}
+
+static int ctrl_subsys_stream_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->subsys_stream_mask;
+       return 0;
+}
+
+static int ctrl_subsys_stream_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,m,v);
+       return 0;
+}
+
+static int ctrl_stdenumcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (v < 0) return -EINVAL;
+       if (v > hdw->std_enum_cnt) return -EINVAL;
+       hdw->std_enum_cur = v;
+       if (!v) return 0;
+       v--;
+       if (hdw->std_mask_cur == hdw->std_defs[v].id) return 0;
+       hdw->std_mask_cur = hdw->std_defs[v].id;
+       hdw->std_dirty = !0;
+       return 0;
+}
+
+
+static int ctrl_stdenumcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->std_enum_cur;
+       return 0;
+}
+
+
+static int ctrl_stdenumcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->std_dirty != 0;
+}
+
+
+static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->std_dirty = 0;
+}
+
+
+#define DEFINT(vmin,vmax) \
+       .type = pvr2_ctl_int, \
+       .def.type_int.min_value = vmin, \
+       .def.type_int.max_value = vmax
+
+#define DEFENUM(tab) \
+       .type = pvr2_ctl_enum, \
+       .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
+       .def.type_enum.value_names = tab
+
+#define DEFBOOL \
+       .type = pvr2_ctl_bool
+
+#define DEFMASK(msk,tab) \
+       .type = pvr2_ctl_bitmask, \
+       .def.type_bitmask.valid_bits = msk, \
+       .def.type_bitmask.bit_names = tab
+
+#define DEFREF(vname) \
+       .set_value = ctrl_set_##vname, \
+       .get_value = ctrl_get_##vname, \
+       .is_dirty = ctrl_isdirty_##vname, \
+       .clear_dirty = ctrl_cleardirty_##vname
+
+
+#define VCREATE_FUNCS(vname) \
+static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \
+{*vp = cptr->hdw->vname##_val; return 0;} \
+static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \
+{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \
+static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \
+{return cptr->hdw->vname##_dirty != 0;} \
+static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \
+{cptr->hdw->vname##_dirty = 0;}
+
+VCREATE_FUNCS(brightness)
+VCREATE_FUNCS(contrast)
+VCREATE_FUNCS(saturation)
+VCREATE_FUNCS(hue)
+VCREATE_FUNCS(volume)
+VCREATE_FUNCS(balance)
+VCREATE_FUNCS(bass)
+VCREATE_FUNCS(treble)
+VCREATE_FUNCS(mute)
+VCREATE_FUNCS(input)
+VCREATE_FUNCS(audiomode)
+VCREATE_FUNCS(res_hor)
+VCREATE_FUNCS(res_ver)
+VCREATE_FUNCS(srate)
+
+#define MIN_FREQ 55250000L
+#define MAX_FREQ 850000000L
+
+/* Table definition of all controls which can be manipulated */
+static const struct pvr2_ctl_info control_defs[] = {
+       {
+               .v4l_id = V4L2_CID_BRIGHTNESS,
+               .desc = "Brightness",
+               .name = "brightness",
+               .default_value = 128,
+               DEFREF(brightness),
+               DEFINT(0,255),
+       },{
+               .v4l_id = V4L2_CID_CONTRAST,
+               .desc = "Contrast",
+               .name = "contrast",
+               .default_value = 68,
+               DEFREF(contrast),
+               DEFINT(0,127),
+       },{
+               .v4l_id = V4L2_CID_SATURATION,
+               .desc = "Saturation",
+               .name = "saturation",
+               .default_value = 64,
+               DEFREF(saturation),
+               DEFINT(0,127),
+       },{
+               .v4l_id = V4L2_CID_HUE,
+               .desc = "Hue",
+               .name = "hue",
+               .default_value = 0,
+               DEFREF(hue),
+               DEFINT(-128,127),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_VOLUME,
+               .desc = "Volume",
+               .name = "volume",
+               .default_value = 65535,
+               DEFREF(volume),
+               DEFINT(0,65535),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_BALANCE,
+               .desc = "Balance",
+               .name = "balance",
+               .default_value = 0,
+               DEFREF(balance),
+               DEFINT(-32768,32767),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_BASS,
+               .desc = "Bass",
+               .name = "bass",
+               .default_value = 0,
+               DEFREF(bass),
+               DEFINT(-32768,32767),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_TREBLE,
+               .desc = "Treble",
+               .name = "treble",
+               .default_value = 0,
+               DEFREF(treble),
+               DEFINT(-32768,32767),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_MUTE,
+               .desc = "Mute",
+               .name = "mute",
+               .default_value = 0,
+               DEFREF(mute),
+               DEFBOOL,
+       },{
+               .desc = "Video Source",
+               .name = "input",
+               .internal_id = PVR2_CID_INPUT,
+               .default_value = PVR2_CVAL_INPUT_TV,
+               DEFREF(input),
+               DEFENUM(control_values_input),
+       },{
+               .desc = "Audio Mode",
+               .name = "audio_mode",
+               .internal_id = PVR2_CID_AUDIOMODE,
+               .default_value = V4L2_TUNER_MODE_STEREO,
+               DEFREF(audiomode),
+               DEFENUM(control_values_audiomode),
+       },{
+               .desc = "Horizontal capture resolution",
+               .name = "resolution_hor",
+               .internal_id = PVR2_CID_HRES,
+               .default_value = 720,
+               DEFREF(res_hor),
+               DEFINT(320,720),
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+               /* Hook in check for clamp on horizontal resolution in
+                  order to avoid unsolved problem involving cx25840. */
+               .get_max_value = ctrl_hres_max_get,
+               .get_min_value = ctrl_hres_min_get,
+#endif
+       },{
+               .desc = "Vertical capture resolution",
+               .name = "resolution_ver",
+               .internal_id = PVR2_CID_VRES,
+               .default_value = 480,
+               DEFREF(res_ver),
+               DEFINT(200,625),
+       },{
+               .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+               .desc = "Sample rate",
+               .name = "srate",
+               .default_value = PVR2_CVAL_SRATE_48,
+               DEFREF(srate),
+               DEFENUM(control_values_srate),
+       },{
+               .desc = "Tuner Frequency (Hz)",
+               .name = "frequency",
+               .internal_id = PVR2_CID_FREQUENCY,
+               .default_value = 175250000L,
+               .set_value = ctrl_freq_set,
+               .get_value = ctrl_freq_get,
+               .is_dirty = ctrl_freq_is_dirty,
+               .clear_dirty = ctrl_freq_clear_dirty,
+               DEFINT(MIN_FREQ,MAX_FREQ),
+       },{
+               .desc = "Channel",
+               .name = "channel",
+               .set_value = ctrl_channel_set,
+               .get_value = ctrl_channel_get,
+               DEFINT(0,FREQTABLE_SIZE),
+       },{
+               .desc = "Channel Program Frequency",
+               .name = "freq_table_value",
+               .set_value = ctrl_channelfreq_set,
+               .get_value = ctrl_channelfreq_get,
+               DEFINT(MIN_FREQ,MAX_FREQ),
+       },{
+               .desc = "Channel Program ID",
+               .name = "freq_table_channel",
+               .set_value = ctrl_channelprog_set,
+               .get_value = ctrl_channelprog_get,
+               DEFINT(0,FREQTABLE_SIZE),
+       },{
+               .desc = "Streaming Enabled",
+               .name = "streaming_enabled",
+               .get_value = ctrl_streamingenabled_get,
+               DEFBOOL,
+       },{
+               .desc = "USB Speed",
+               .name = "usb_speed",
+               .get_value = ctrl_hsm_get,
+               DEFENUM(control_values_hsm),
+       },{
+               .desc = "Signal Present",
+               .name = "signal_present",
+               .get_value = ctrl_signal_get,
+               DEFBOOL,
+       },{
+               .desc = "Video Standards Available Mask",
+               .name = "video_standard_mask_available",
+               .internal_id = PVR2_CID_STDAVAIL,
+               .skip_init = !0,
+               .get_value = ctrl_stdavail_get,
+               .set_value = ctrl_stdavail_set,
+               .val_to_sym = ctrl_std_val_to_sym,
+               .sym_to_val = ctrl_std_sym_to_val,
+               .type = pvr2_ctl_bitmask,
+       },{
+               .desc = "Video Standards In Use Mask",
+               .name = "video_standard_mask_active",
+               .internal_id = PVR2_CID_STDCUR,
+               .skip_init = !0,
+               .get_value = ctrl_stdcur_get,
+               .set_value = ctrl_stdcur_set,
+               .is_dirty = ctrl_stdcur_is_dirty,
+               .clear_dirty = ctrl_stdcur_clear_dirty,
+               .val_to_sym = ctrl_std_val_to_sym,
+               .sym_to_val = ctrl_std_sym_to_val,
+               .type = pvr2_ctl_bitmask,
+       },{
+               .desc = "Subsystem enabled mask",
+               .name = "debug_subsys_mask",
+               .skip_init = !0,
+               .get_value = ctrl_subsys_get,
+               .set_value = ctrl_subsys_set,
+               DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
+       },{
+               .desc = "Subsystem stream mask",
+               .name = "debug_subsys_stream_mask",
+               .skip_init = !0,
+               .get_value = ctrl_subsys_stream_get,
+               .set_value = ctrl_subsys_stream_set,
+               DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
+       },{
+               .desc = "Video Standard Name",
+               .name = "video_standard",
+               .internal_id = PVR2_CID_STDENUM,
+               .skip_init = !0,
+               .get_value = ctrl_stdenumcur_get,
+               .set_value = ctrl_stdenumcur_set,
+               .is_dirty = ctrl_stdenumcur_is_dirty,
+               .clear_dirty = ctrl_stdenumcur_clear_dirty,
+               .type = pvr2_ctl_enum,
+       }
+};
+
+#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
+
+
+const char *pvr2_config_get_name(enum pvr2_config cfg)
+{
+       switch (cfg) {
+       case pvr2_config_empty: return "empty";
+       case pvr2_config_mpeg: return "mpeg";
+       case pvr2_config_vbi: return "vbi";
+       case pvr2_config_radio: return "radio";
+       }
+       return "<unknown>";
+}
+
+
+struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw)
+{
+       return hdw->usb_dev;
+}
+
+
+unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
+{
+       return hdw->serial_number;
+}
+
+int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
+{
+       return hdw->unit_number;
+}
+
+
+/* Attempt to locate one of the given set of files.  Messages are logged
+   appropriate to what has been found.  The return value will be 0 or
+   greater on success (it will be the index of the file name found) and
+   fw_entry will be filled in.  Otherwise a negative error is returned on
+   failure.  If the return value is -ENOENT then no viable firmware file
+   could be located. */
+static int pvr2_locate_firmware(struct pvr2_hdw *hdw,
+                               const struct firmware **fw_entry,
+                               const char *fwtypename,
+                               unsigned int fwcount,
+                               const char *fwnames[])
+{
+       unsigned int idx;
+       int ret = -EINVAL;
+       for (idx = 0; idx < fwcount; idx++) {
+               ret = request_firmware(fw_entry,
+                                      fwnames[idx],
+                                      &hdw->usb_dev->dev);
+               if (!ret) {
+                       trace_firmware("Located %s firmware: %s;"
+                                      " uploading...",
+                                      fwtypename,
+                                      fwnames[idx]);
+                       return idx;
+               }
+               if (ret == -ENOENT) continue;
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "request_firmware fatal error with code=%d",ret);
+               return ret;
+       }
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "***WARNING***"
+                  " Device %s firmware"
+                  " seems to be missing.",
+                  fwtypename);
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "Did you install the pvrusb2 firmware files"
+                  " in their proper location?");
+       if (fwcount == 1) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "request_firmware unable to locate %s file %s",
+                          fwtypename,fwnames[0]);
+       } else {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "request_firmware unable to locate"
+                          " one of the following %s files:",
+                          fwtypename);
+               for (idx = 0; idx < fwcount; idx++) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "request_firmware: Failed to find %s",
+                                  fwnames[idx]);
+               }
+       }
+       return ret;
+}
+
+
+/*
+ * pvr2_upload_firmware1().
+ *
+ * Send the 8051 firmware to the device.  After the upload, arrange for
+ * device to re-enumerate.
+ *
+ * NOTE : the pointer to the firmware data given by request_firmware()
+ * is not suitable for an usb transaction.
+ *
+ */
+static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
+{
+       const struct firmware *fw_entry = NULL;
+       void  *fw_ptr;
+       unsigned int pipe;
+       int ret;
+       u16 address;
+       static const char *fw_files_29xxx[] = {
+               "v4l-pvrusb2-29xxx-01.fw",
+       };
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+       static const char *fw_files_24xxx[] = {
+               "v4l-pvrusb2-24xxx-01.fw",
+       };
+#endif
+       static const struct pvr2_string_table fw_file_defs[] = {
+               [PVR2_HDW_TYPE_29XXX] = {
+                       fw_files_29xxx,
+                       sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
+               },
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+               [PVR2_HDW_TYPE_24XXX] = {
+                       fw_files_24xxx,
+                       sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
+               },
+#endif
+       };
+       hdw->fw1_state = FW1_STATE_FAILED; // default result
+
+       trace_firmware("pvr2_upload_firmware1");
+
+       ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
+                                  fw_file_defs[hdw->hdw_type].cnt,
+                                  fw_file_defs[hdw->hdw_type].lst);
+       if (ret < 0) {
+               if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
+               return ret;
+       }
+
+       usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0);
+       usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
+
+       pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
+
+       if (fw_entry->size != 0x2000){
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,"wrong fx2 firmware size");
+               release_firmware(fw_entry);
+               return -ENOMEM;
+       }
+
+       fw_ptr = kmalloc(0x800, GFP_KERNEL);
+       if (fw_ptr == NULL){
+               release_firmware(fw_entry);
+               return -ENOMEM;
+       }
+
+       /* We have to hold the CPU during firmware upload. */
+       pvr2_hdw_cpureset_assert(hdw,1);
+
+       /* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes
+          chunk. */
+
+       ret = 0;
+       for(address = 0; address < fw_entry->size; address += 0x800) {
+               memcpy(fw_ptr, fw_entry->data + address, 0x800);
+               ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address,
+                                      0, fw_ptr, 0x800, HZ);
+       }
+
+       trace_firmware("Upload done, releasing device's CPU");
+
+       /* Now release the CPU.  It will disconnect and reconnect later. */
+       pvr2_hdw_cpureset_assert(hdw,0);
+
+       kfree(fw_ptr);
+       release_firmware(fw_entry);
+
+       trace_firmware("Upload done (%d bytes sent)",ret);
+
+       /* We should have written 8192 bytes */
+       if (ret == 8192) {
+               hdw->fw1_state = FW1_STATE_RELOAD;
+               return 0;
+       }
+
+       return -EIO;
+}
+
+
+/*
+ * pvr2_upload_firmware2()
+ *
+ * This uploads encoder firmware on endpoint 2.
+ *
+ */
+
+int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+{
+       const struct firmware *fw_entry = NULL;
+       void  *fw_ptr;
+       unsigned int pipe, fw_len, fw_done;
+       int actual_length;
+       int ret = 0;
+       int fwidx;
+       static const char *fw_files[] = {
+               CX2341X_FIRM_ENC_FILENAME,
+       };
+
+       trace_firmware("pvr2_upload_firmware2");
+
+       ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
+                                  sizeof(fw_files)/sizeof(fw_files[0]),
+                                  fw_files);
+       if (ret < 0) return ret;
+       fwidx = ret;
+       ret = 0;
+       /* Since we're about to completely reinitialize the encoder,
+          invalidate our cached copy of its configuration state.  Next
+          time we configure the encoder, then we'll fully configure it. */
+       hdw->enc_cur_valid = 0;
+
+       /* First prepare firmware loading */
+       ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
+       ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
+       ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
+       ret |= pvr2_hdw_cmd_deep_reset(hdw);
+       ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/
+       ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/
+       ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
+       ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/
+       ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/
+       ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/
+       ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/
+       ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/
+       ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/
+       ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
+       ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
+       ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
+       ret |= pvr2_write_u8(hdw, 0x52, 0);
+       ret |= pvr2_write_u16(hdw, 0x0600, 0);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "firmware2 upload prep failed, ret=%d",ret);
+               release_firmware(fw_entry);
+               return ret;
+       }
+
+       /* Now send firmware */
+
+       fw_len = fw_entry->size;
+
+       if (fw_len % FIRMWARE_CHUNK_SIZE) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "size of %s firmware"
+                          " must be a multiple of 8192B",
+                          fw_files[fwidx]);
+               release_firmware(fw_entry);
+               return -1;
+       }
+
+       fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
+       if (fw_ptr == NULL){
+               release_firmware(fw_entry);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "failed to allocate memory for firmware2 upload");
+               return -ENOMEM;
+       }
+
+       pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
+
+       for (fw_done = 0 ; (fw_done < fw_len) && !ret ;
+            fw_done += FIRMWARE_CHUNK_SIZE ) {
+               int i;
+               memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE);
+               /* Usbsnoop log  shows that we must swap bytes... */
+               for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++)
+                       ((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]);
+
+               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,
+                                   FIRMWARE_CHUNK_SIZE,
+                                   &actual_length, HZ);
+               ret |= (actual_length != FIRMWARE_CHUNK_SIZE);
+       }
+
+       trace_firmware("upload of %s : %i / %i ",
+                      fw_files[fwidx],fw_done,fw_len);
+
+       kfree(fw_ptr);
+       release_firmware(fw_entry);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "firmware2 upload transfer failure");
+               return ret;
+       }
+
+       /* Finish upload */
+
+       ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
+       ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
+       ret |= pvr2_write_u16(hdw, 0x0600, 0);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "firmware2 upload post-proc failure");
+       } else {
+               hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_FIRMWARE);
+       }
+       return ret;
+}
+
+
+#define FIRMWARE_RECOVERY_BITS \
+       ((1<<PVR2_SUBSYS_B_ENC_CFG) | \
+        (1<<PVR2_SUBSYS_B_ENC_RUN) | \
+        (1<<PVR2_SUBSYS_B_ENC_FIRMWARE) | \
+        (1<<PVR2_SUBSYS_B_USBSTREAM_RUN))
+
+/*
+
+  This single function is key to pretty much everything.  The pvrusb2
+  device can logically be viewed as a series of subsystems which can be
+  stopped / started or unconfigured / configured.  To get things streaming,
+  one must configure everything and start everything, but there may be
+  various reasons over time to deconfigure something or stop something.
+  This function handles all of this activity.  Everything EVERYWHERE that
+  must affect a subsystem eventually comes here to do the work.
+
+  The current state of all subsystems is represented by a single bit mask,
+  known as subsys_enabled_mask.  The bit positions are defined by the
+  PVR2_SUBSYS_xxxx macros, with one subsystem per bit position.  At any
+  time the set of configured or active subsystems can be queried just by
+  looking at that mask.  To change bits in that mask, this function here
+  must be called.  The "msk" argument indicates which bit positions to
+  change, and the "val" argument defines the new values for the positions
+  defined by "msk".
+
+  There is a priority ordering of starting / stopping things, and for
+  multiple requested changes, this function implements that ordering.
+  (Thus we will act on a request to load encoder firmware before we
+  configure the encoder.)  In addition to priority ordering, there is a
+  recovery strategy implemented here.  If a particular step fails and we
+  detect that failure, this function will clear the affected subsystem bits
+  and restart.  Thus we have a means for recovering from a dead encoder:
+  Clear all bits that correspond to subsystems that we need to restart /
+  reconfigure and start over.
+
+*/
+static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+                                           unsigned long msk,
+                                           unsigned long val)
+{
+       unsigned long nmsk;
+       unsigned long vmsk;
+       int ret;
+       unsigned int tryCount = 0;
+
+       if (!hdw->flag_ok) return;
+
+       msk &= PVR2_SUBSYS_ALL;
+       nmsk = (hdw->subsys_enabled_mask & ~msk) | (val & msk);
+       nmsk &= PVR2_SUBSYS_ALL;
+
+       for (;;) {
+               tryCount++;
+               if (!((nmsk ^ hdw->subsys_enabled_mask) &
+                     PVR2_SUBSYS_ALL)) break;
+               if (tryCount > 4) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Too many retries when configuring device;"
+                                  " giving up");
+                       pvr2_hdw_render_useless(hdw);
+                       break;
+               }
+               if (tryCount > 1) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Retrying device reconfiguration");
+               }
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "subsys mask changing 0x%lx:0x%lx"
+                          " from 0x%lx to 0x%lx",
+                          msk,val,hdw->subsys_enabled_mask,nmsk);
+
+               vmsk = (nmsk ^ hdw->subsys_enabled_mask) &
+                       hdw->subsys_enabled_mask;
+               if (vmsk) {
+                       if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " pvr2_encoder_stop");
+                               ret = pvr2_encoder_stop(hdw);
+                               if (ret) {
+                                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                                  "Error recovery initiated");
+                                       hdw->subsys_enabled_mask &=
+                                               ~FIRMWARE_RECOVERY_BITS;
+                                       continue;
+                               }
+                       }
+                       if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " pvr2_hdw_cmd_usbstream(0)");
+                               pvr2_hdw_cmd_usbstream(hdw,0);
+                       }
+                       if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " decoder disable");
+                               if (hdw->decoder_ctrl) {
+                                       hdw->decoder_ctrl->enable(
+                                               hdw->decoder_ctrl->ctxt,0);
+                               } else {
+                                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                                  "WARNING:"
+                                                  " No decoder present");
+                               }
+                               hdw->subsys_enabled_mask &=
+                                       ~(1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
+                       }
+                       if (vmsk & PVR2_SUBSYS_CFG_ALL) {
+                               hdw->subsys_enabled_mask &=
+                                       ~(vmsk & PVR2_SUBSYS_CFG_ALL);
+                       }
+               }
+               vmsk = (nmsk ^ hdw->subsys_enabled_mask) & nmsk;
+               if (vmsk) {
+                       if (vmsk & (1<<PVR2_SUBSYS_B_ENC_FIRMWARE)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " pvr2_upload_firmware2");
+                               ret = pvr2_upload_firmware2(hdw);
+                               if (ret) {
+                                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                                  "Failure uploading encoder"
+                                                  " firmware");
+                                       pvr2_hdw_render_useless(hdw);
+                                       break;
+                               }
+                       }
+                       if (vmsk & (1<<PVR2_SUBSYS_B_ENC_CFG)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " pvr2_encoder_configure");
+                               ret = pvr2_encoder_configure(hdw);
+                               if (ret) {
+                                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                                  "Error recovery initiated");
+                                       hdw->subsys_enabled_mask &=
+                                               ~FIRMWARE_RECOVERY_BITS;
+                                       continue;
+                               }
+                       }
+                       if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " decoder enable");
+                               if (hdw->decoder_ctrl) {
+                                       hdw->decoder_ctrl->enable(
+                                               hdw->decoder_ctrl->ctxt,!0);
+                               } else {
+                                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                                  "WARNING:"
+                                                  " No decoder present");
+                               }
+                               hdw->subsys_enabled_mask |=
+                                       (1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
+                       }
+                       if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " pvr2_hdw_cmd_usbstream(1)");
+                               pvr2_hdw_cmd_usbstream(hdw,!0);
+                       }
+                       if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
+                               pvr2_trace(PVR2_TRACE_CTL,
+                                          "/*---TRACE_CTL----*/"
+                                          " pvr2_encoder_start");
+                               ret = pvr2_encoder_start(hdw);
+                               if (ret) {
+                                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                                  "Error recovery initiated");
+                                       hdw->subsys_enabled_mask &=
+                                               ~FIRMWARE_RECOVERY_BITS;
+                                       continue;
+                               }
+                       }
+               }
+       }
+}
+
+
+void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
+                            unsigned long msk,unsigned long val)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_hdw_subsys_bit_chg_no_lock(hdw,msk,val);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw)
+{
+       return hdw->subsys_enabled_mask;
+}
+
+
+unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw)
+{
+       return hdw->subsys_stream_mask;
+}
+
+
+static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+                                                  unsigned long msk,
+                                                  unsigned long val)
+{
+       unsigned long val2;
+       msk &= PVR2_SUBSYS_ALL;
+       val2 = ((hdw->subsys_stream_mask & ~msk) | (val & msk));
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "stream mask changing 0x%lx:0x%lx from 0x%lx to 0x%lx",
+                  msk,val,hdw->subsys_stream_mask,val2);
+       hdw->subsys_stream_mask = val2;
+}
+
+
+void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
+                                   unsigned long msk,
+                                   unsigned long val)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,msk,val);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+static int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl)
+{
+       if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0;
+       if (enableFl) {
+               pvr2_trace(PVR2_TRACE_START_STOP,
+                          "/*--TRACE_STREAM--*/ enable");
+               pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,~0);
+       } else {
+               pvr2_trace(PVR2_TRACE_START_STOP,
+                          "/*--TRACE_STREAM--*/ disable");
+               pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0);
+       }
+       if (!hdw->flag_ok) return -EIO;
+       hdw->flag_streaming_enabled = enableFl != 0;
+       return 0;
+}
+
+
+int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
+{
+       return hdw->flag_streaming_enabled != 0;
+}
+
+
+int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
+{
+       int ret;
+       LOCK_TAKE(hdw->big_lock); do {
+               ret = pvr2_hdw_set_streaming_no_lock(hdw,enable_flag);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return ret;
+}
+
+
+static int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw,
+                                           enum pvr2_config config)
+{
+       unsigned long sm = hdw->subsys_enabled_mask;
+       if (!hdw->flag_ok) return -EIO;
+       pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0);
+       hdw->config = config;
+       pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,sm);
+       return 0;
+}
+
+
+int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config)
+{
+       int ret;
+       if (!hdw->flag_ok) return -EIO;
+       LOCK_TAKE(hdw->big_lock);
+       ret = pvr2_hdw_set_stream_type_no_lock(hdw,config);
+       LOCK_GIVE(hdw->big_lock);
+       return ret;
+}
+
+
+static int get_default_tuner_type(struct pvr2_hdw *hdw)
+{
+       int unit_number = hdw->unit_number;
+       int tp = -1;
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               tp = tuner[unit_number];
+       }
+       if (tp < 0) return -EINVAL;
+       hdw->tuner_type = tp;
+       return 0;
+}
+
+
+static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw)
+{
+       int unit_number = hdw->unit_number;
+       int tp = 0;
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               tp = video_std[unit_number];
+       }
+       return tp;
+}
+
+
+static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
+{
+       int unit_number = hdw->unit_number;
+       int tp = 0;
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               tp = tolerance[unit_number];
+       }
+       return tp;
+}
+
+
+static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
+{
+       /* Try a harmless request to fetch the eeprom's address over
+          endpoint 1.  See what happens.  Only the full FX2 image can
+          respond to this.  If this probe fails then likely the FX2
+          firmware needs be loaded. */
+       int result;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = 0xeb;
+               result = pvr2_send_request_ex(hdw,HZ*1,!0,
+                                          hdw->cmd_buffer,1,
+                                          hdw->cmd_buffer,1);
+               if (result < 0) break;
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+       if (result) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Probe of device endpoint 1 result status %d",
+                          result);
+       } else {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Probe of device endpoint 1 succeeded");
+       }
+       return result == 0;
+}
+
+static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
+{
+       char buf[40];
+       unsigned int bcnt;
+       v4l2_std_id std1,std2;
+
+       std1 = get_default_standard(hdw);
+
+       bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "Supported video standard(s) reported by eeprom: %.*s",
+                  bcnt,buf);
+
+       hdw->std_mask_avail = hdw->std_mask_eeprom;
+
+       std2 = std1 & ~hdw->std_mask_avail;
+       if (std2) {
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Expanding supported video standards"
+                          " to include: %.*s",
+                          bcnt,buf);
+               hdw->std_mask_avail |= std2;
+       }
+
+       pvr2_hdw_internal_set_std_avail(hdw);
+
+       if (std1) {
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Initial video standard forced to %.*s",
+                          bcnt,buf);
+               hdw->std_mask_cur = std1;
+               hdw->std_dirty = !0;
+               pvr2_hdw_internal_find_stdenum(hdw);
+               return;
+       }
+
+       if (hdw->std_enum_cnt > 1) {
+               // Autoselect the first listed standard
+               hdw->std_enum_cur = 1;
+               hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id;
+               hdw->std_dirty = !0;
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Initial video standard auto-selected to %s",
+                          hdw->std_defs[hdw->std_enum_cur-1].name);
+               return;
+       }
+
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "Unable to select a viable initial video standard");
+}
+
+
+static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
+{
+       int ret;
+       unsigned int idx;
+       struct pvr2_ctrl *cptr;
+       int reloadFl = 0;
+       if (!reloadFl) {
+               reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
+                           == 0);
+               if (reloadFl) {
+                       pvr2_trace(PVR2_TRACE_INIT,
+                                  "USB endpoint config looks strange"
+                                  "; possibly firmware needs to be loaded");
+               }
+       }
+       if (!reloadFl) {
+               reloadFl = !pvr2_hdw_check_firmware(hdw);
+               if (reloadFl) {
+                       pvr2_trace(PVR2_TRACE_INIT,
+                                  "Check for FX2 firmware failed"
+                                  "; possibly firmware needs to be loaded");
+               }
+       }
+       if (reloadFl) {
+               if (pvr2_upload_firmware1(hdw) != 0) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Failure uploading firmware1");
+               }
+               return;
+       }
+       hdw->fw1_state = FW1_STATE_OK;
+
+       if (initusbreset) {
+               pvr2_hdw_device_reset(hdw);
+       }
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) {
+               request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]);
+       }
+
+       pvr2_hdw_cmd_powerup(hdw);
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       if (pvr2_upload_firmware2(hdw)){
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!");
+               pvr2_hdw_render_useless(hdw);
+               return;
+       }
+
+       // This step MUST happen after the earlier powerup step.
+       pvr2_i2c_core_init(hdw);
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+               cptr = hdw->controls + idx;
+               if (cptr->info->skip_init) continue;
+               if (!cptr->info->set_value) continue;
+               cptr->info->set_value(cptr,~0,cptr->info->default_value);
+       }
+
+       // Do not use pvr2_reset_ctl_endpoints() here.  It is not
+       // thread-safe against the normal pvr2_send_request() mechanism.
+       // (We should make it thread safe).
+
+       ret = pvr2_hdw_get_eeprom_addr(hdw);
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Unable to determine location of eeprom, skipping");
+       } else {
+               hdw->eeprom_addr = ret;
+               pvr2_eeprom_analyze(hdw);
+               if (!pvr2_hdw_dev_ok(hdw)) return;
+       }
+
+       pvr2_hdw_setup_std(hdw);
+
+       if (!get_default_tuner_type(hdw)) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "pvr2_hdw_setup: Tuner type overridden to %d",
+                          hdw->tuner_type);
+       }
+
+       hdw->tuner_updated = !0;
+       pvr2_i2c_core_check_stale(hdw);
+       hdw->tuner_updated = 0;
+
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       pvr2_hdw_commit_ctl_internal(hdw);
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       hdw->vid_stream = pvr2_stream_create();
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "pvr2_hdw_setup: video stream is %p",hdw->vid_stream);
+       if (hdw->vid_stream) {
+               idx = get_default_error_tolerance(hdw);
+               if (idx) {
+                       pvr2_trace(PVR2_TRACE_INIT,
+                                  "pvr2_hdw_setup: video stream %p"
+                                  " setting tolerance %u",
+                                  hdw->vid_stream,idx);
+               }
+               pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
+                                 PVR2_VID_ENDPOINT,idx);
+       }
+
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       /* Make sure everything is up to date */
+       pvr2_i2c_core_sync(hdw);
+
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       hdw->flag_init_ok = !0;
+}
+
+
+int pvr2_hdw_setup(struct pvr2_hdw *hdw)
+{
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw);
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_hdw_setup_low(hdw);
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",
+                          hdw,hdw->flag_ok,hdw->flag_init_ok);
+               if (pvr2_hdw_dev_ok(hdw)) {
+                       if (pvr2_hdw_init_ok(hdw)) {
+                               pvr2_trace(
+                                       PVR2_TRACE_INFO,
+                                       "Device initialization"
+                                       " completed successfully.");
+                               break;
+                       }
+                       if (hdw->fw1_state == FW1_STATE_RELOAD) {
+                               pvr2_trace(
+                                       PVR2_TRACE_INFO,
+                                       "Device microcontroller firmware"
+                                       " (re)loaded; it should now reset"
+                                       " and reconnect.");
+                               break;
+                       }
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Device initialization was not successful.");
+                       if (hdw->fw1_state == FW1_STATE_MISSING) {
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "Giving up since device"
+                                       " microcontroller firmware"
+                                       " appears to be missing.");
+                               break;
+                       }
+               }
+               if (procreload) {
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Attempting pvrusb2 recovery by reloading"
+                               " primary firmware.");
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "If this works, device should disconnect"
+                               " and reconnect in a sane state.");
+                       hdw->fw1_state = FW1_STATE_UNKNOWN;
+                       pvr2_upload_firmware1(hdw);
+               } else {
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "***WARNING*** pvrusb2 device hardware"
+                               " appears to be jammed"
+                               " and I can't clear it.");
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "You might need to power cycle"
+                               " the pvrusb2 device"
+                               " in order to recover.");
+               }
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
+       return hdw->flag_init_ok;
+}
+
+
+/* Create and return a structure for interacting with the underlying
+   hardware */
+struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+                                const struct usb_device_id *devid)
+{
+       unsigned int idx,cnt1,cnt2;
+       struct pvr2_hdw *hdw;
+       unsigned int hdw_type;
+       int valid_std_mask;
+       struct pvr2_ctrl *cptr;
+       __u8 ifnum;
+       struct v4l2_queryctrl qctrl;
+       struct pvr2_ctl_info *ciptr;
+
+       hdw_type = devid - pvr2_device_table;
+       if (hdw_type >=
+           sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Bogus device type of %u reported",hdw_type);
+               return NULL;
+       }
+
+       hdw = kmalloc(sizeof(*hdw),GFP_KERNEL);
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
+                  hdw,pvr2_device_names[hdw_type]);
+       if (!hdw) goto fail;
+       memset(hdw,0,sizeof(*hdw));
+       cx2341x_fill_defaults(&hdw->enc_ctl_state);
+
+       hdw->control_cnt = CTRLDEF_COUNT;
+       hdw->control_cnt += MPEGDEF_COUNT;
+       hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+                               GFP_KERNEL);
+       if (!hdw->controls) goto fail;
+       memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt);
+       hdw->hdw_type = hdw_type;
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               cptr->hdw = hdw;
+       }
+       for (idx = 0; idx < 32; idx++) {
+               hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
+       }
+       for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+               cptr = hdw->controls + idx;
+               cptr->info = control_defs+idx;
+       }
+       /* Define and configure additional controls from cx2341x module. */
+       hdw->mpeg_ctrl_info = kmalloc(
+               sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+       if (!hdw->mpeg_ctrl_info) goto fail;
+       memset(hdw->mpeg_ctrl_info,0,
+              sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT);
+       for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
+               cptr = hdw->controls + idx + CTRLDEF_COUNT;
+               ciptr = &(hdw->mpeg_ctrl_info[idx].info);
+               ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
+               ciptr->name = mpeg_ids[idx].strid;
+               ciptr->v4l_id = mpeg_ids[idx].id;
+               ciptr->skip_init = !0;
+               ciptr->get_value = ctrl_cx2341x_get;
+               ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
+               ciptr->is_dirty = ctrl_cx2341x_is_dirty;
+               if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
+               qctrl.id = ciptr->v4l_id;
+               cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
+               if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
+                       ciptr->set_value = ctrl_cx2341x_set;
+               }
+               strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,
+                       PVR2_CTLD_INFO_DESC_SIZE);
+               hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;
+               ciptr->default_value = qctrl.default_value;
+               switch (qctrl.type) {
+               default:
+               case V4L2_CTRL_TYPE_INTEGER:
+                       ciptr->type = pvr2_ctl_int;
+                       ciptr->def.type_int.min_value = qctrl.minimum;
+                       ciptr->def.type_int.max_value = qctrl.maximum;
+                       break;
+               case V4L2_CTRL_TYPE_BOOLEAN:
+                       ciptr->type = pvr2_ctl_bool;
+                       break;
+               case V4L2_CTRL_TYPE_MENU:
+                       ciptr->type = pvr2_ctl_enum;
+                       ciptr->def.type_enum.value_names =
+                               cx2341x_ctrl_get_menu(ciptr->v4l_id);
+                       for (cnt1 = 0;
+                            ciptr->def.type_enum.value_names[cnt1] != NULL;
+                            cnt1++) { }
+                       ciptr->def.type_enum.count = cnt1;
+                       break;
+               }
+               cptr->info = ciptr;
+       }
+
+       // Initialize video standard enum dynamic control
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM);
+       if (cptr) {
+               memcpy(&hdw->std_info_enum,cptr->info,
+                      sizeof(hdw->std_info_enum));
+               cptr->info = &hdw->std_info_enum;
+
+       }
+       // Initialize control data regarding video standard masks
+       valid_std_mask = pvr2_std_get_usable();
+       for (idx = 0; idx < 32; idx++) {
+               if (!(valid_std_mask & (1 << idx))) continue;
+               cnt1 = pvr2_std_id_to_str(
+                       hdw->std_mask_names[idx],
+                       sizeof(hdw->std_mask_names[idx])-1,
+                       1 << idx);
+               hdw->std_mask_names[idx][cnt1] = 0;
+       }
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
+       if (cptr) {
+               memcpy(&hdw->std_info_avail,cptr->info,
+                      sizeof(hdw->std_info_avail));
+               cptr->info = &hdw->std_info_avail;
+               hdw->std_info_avail.def.type_bitmask.bit_names =
+                       hdw->std_mask_ptrs;
+               hdw->std_info_avail.def.type_bitmask.valid_bits =
+                       valid_std_mask;
+       }
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
+       if (cptr) {
+               memcpy(&hdw->std_info_cur,cptr->info,
+                      sizeof(hdw->std_info_cur));
+               cptr->info = &hdw->std_info_cur;
+               hdw->std_info_cur.def.type_bitmask.bit_names =
+                       hdw->std_mask_ptrs;
+               hdw->std_info_avail.def.type_bitmask.valid_bits =
+                       valid_std_mask;
+       }
+
+       hdw->eeprom_addr = -1;
+       hdw->unit_number = -1;
+       hdw->v4l_minor_number = -1;
+       hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
+       if (!hdw->ctl_write_buffer) goto fail;
+       hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
+       if (!hdw->ctl_read_buffer) goto fail;
+       hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);
+       if (!hdw->ctl_write_urb) goto fail;
+       hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
+       if (!hdw->ctl_read_urb) goto fail;
+
+       down(&pvr2_unit_sem); do {
+               for (idx = 0; idx < PVR_NUM; idx++) {
+                       if (unit_pointers[idx]) continue;
+                       hdw->unit_number = idx;
+                       unit_pointers[idx] = hdw;
+                       break;
+               }
+       } while (0); up(&pvr2_unit_sem);
+
+       cnt1 = 0;
+       cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
+       cnt1 += cnt2;
+       if (hdw->unit_number >= 0) {
+               cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",
+                                ('a' + hdw->unit_number));
+               cnt1 += cnt2;
+       }
+       if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
+       hdw->name[cnt1] = 0;
+
+       pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
+                  hdw->unit_number,hdw->name);
+
+       hdw->tuner_type = -1;
+       hdw->flag_ok = !0;
+       /* Initialize the mask of subsystems that we will shut down when we
+          stop streaming. */
+       hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL;
+       hdw->subsys_stream_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+
+       pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx",
+                  hdw->subsys_stream_mask);
+
+       hdw->usb_intf = intf;
+       hdw->usb_dev = interface_to_usbdev(intf);
+
+       ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
+       usb_set_interface(hdw->usb_dev,ifnum,0);
+
+       mutex_init(&hdw->ctl_lock_mutex);
+       mutex_init(&hdw->big_lock_mutex);
+
+       return hdw;
+ fail:
+       if (hdw) {
+               if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb);
+               if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb);
+               if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
+               if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
+               if (hdw->controls) kfree(hdw->controls);
+               if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
+               kfree(hdw);
+       }
+       return NULL;
+}
+
+
+/* Remove _all_ associations between this driver and the underlying USB
+   layer. */
+static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
+{
+       if (hdw->flag_disconnected) return;
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);
+       if (hdw->ctl_read_urb) {
+               usb_kill_urb(hdw->ctl_read_urb);
+               usb_free_urb(hdw->ctl_read_urb);
+               hdw->ctl_read_urb = NULL;
+       }
+       if (hdw->ctl_write_urb) {
+               usb_kill_urb(hdw->ctl_write_urb);
+               usb_free_urb(hdw->ctl_write_urb);
+               hdw->ctl_write_urb = NULL;
+       }
+       if (hdw->ctl_read_buffer) {
+               kfree(hdw->ctl_read_buffer);
+               hdw->ctl_read_buffer = NULL;
+       }
+       if (hdw->ctl_write_buffer) {
+               kfree(hdw->ctl_write_buffer);
+               hdw->ctl_write_buffer = NULL;
+       }
+       pvr2_hdw_render_useless_unlocked(hdw);
+       hdw->flag_disconnected = !0;
+       hdw->usb_dev = NULL;
+       hdw->usb_intf = NULL;
+}
+
+
+/* Destroy hardware interaction structure */
+void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
+{
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
+       if (hdw->fw_buffer) {
+               kfree(hdw->fw_buffer);
+               hdw->fw_buffer = NULL;
+       }
+       if (hdw->vid_stream) {
+               pvr2_stream_destroy(hdw->vid_stream);
+               hdw->vid_stream = NULL;
+       }
+       if (hdw->audio_stat) {
+               hdw->audio_stat->detach(hdw->audio_stat->ctxt);
+       }
+       if (hdw->decoder_ctrl) {
+               hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
+       }
+       pvr2_i2c_core_done(hdw);
+       pvr2_hdw_remove_usb_stuff(hdw);
+       down(&pvr2_unit_sem); do {
+               if ((hdw->unit_number >= 0) &&
+                   (hdw->unit_number < PVR_NUM) &&
+                   (unit_pointers[hdw->unit_number] == hdw)) {
+                       unit_pointers[hdw->unit_number] = NULL;
+               }
+       } while (0); up(&pvr2_unit_sem);
+       if (hdw->controls) kfree(hdw->controls);
+       if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
+       if (hdw->std_defs) kfree(hdw->std_defs);
+       if (hdw->std_enum_names) kfree(hdw->std_enum_names);
+       kfree(hdw);
+}
+
+
+int pvr2_hdw_init_ok(struct pvr2_hdw *hdw)
+{
+       return hdw->flag_init_ok;
+}
+
+
+int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw)
+{
+       return (hdw && hdw->flag_ok);
+}
+
+
+/* Called when hardware has been unplugged */
+void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
+{
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
+       LOCK_TAKE(hdw->big_lock);
+       LOCK_TAKE(hdw->ctl_lock);
+       pvr2_hdw_remove_usb_stuff(hdw);
+       LOCK_GIVE(hdw->ctl_lock);
+       LOCK_GIVE(hdw->big_lock);
+}
+
+
+// Attempt to autoselect an appropriate value for std_enum_cur given
+// whatever is currently in std_mask_cur
+static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw)
+{
+       unsigned int idx;
+       for (idx = 1; idx < hdw->std_enum_cnt; idx++) {
+               if (hdw->std_defs[idx-1].id == hdw->std_mask_cur) {
+                       hdw->std_enum_cur = idx;
+                       return;
+               }
+       }
+       hdw->std_enum_cur = 0;
+}
+
+
+// Calculate correct set of enumerated standards based on currently known
+// set of available standards bits.
+static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw)
+{
+       struct v4l2_standard *newstd;
+       unsigned int std_cnt;
+       unsigned int idx;
+
+       newstd = pvr2_std_create_enum(&std_cnt,hdw->std_mask_avail);
+
+       if (hdw->std_defs) {
+               kfree(hdw->std_defs);
+               hdw->std_defs = NULL;
+       }
+       hdw->std_enum_cnt = 0;
+       if (hdw->std_enum_names) {
+               kfree(hdw->std_enum_names);
+               hdw->std_enum_names = NULL;
+       }
+
+       if (!std_cnt) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "WARNING: Failed to identify any viable standards");
+       }
+       hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL);
+       hdw->std_enum_names[0] = "none";
+       for (idx = 0; idx < std_cnt; idx++) {
+               hdw->std_enum_names[idx+1] =
+                       newstd[idx].name;
+       }
+       // Set up the dynamic control for this standard
+       hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names;
+       hdw->std_info_enum.def.type_enum.count = std_cnt+1;
+       hdw->std_defs = newstd;
+       hdw->std_enum_cnt = std_cnt+1;
+       hdw->std_enum_cur = 0;
+       hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
+}
+
+
+int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,
+                              struct v4l2_standard *std,
+                              unsigned int idx)
+{
+       int ret = -EINVAL;
+       if (!idx) return ret;
+       LOCK_TAKE(hdw->big_lock); do {
+               if (idx >= hdw->std_enum_cnt) break;
+               idx--;
+               memcpy(std,hdw->std_defs+idx,sizeof(*std));
+               ret = 0;
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return ret;
+}
+
+
+/* Get the number of defined controls */
+unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
+{
+       return hdw->control_cnt;
+}
+
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,
+                                            unsigned int idx)
+{
+       if (idx >= hdw->control_cnt) return NULL;
+       return hdw->controls + idx;
+}
+
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw,
+                                         unsigned int ctl_id)
+{
+       struct pvr2_ctrl *cptr;
+       unsigned int idx;
+       int i;
+
+       /* This could be made a lot more efficient, but for now... */
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               i = cptr->info->internal_id;
+               if (i && (i == ctl_id)) return cptr;
+       }
+       return NULL;
+}
+
+
+/* Given a V4L ID, retrieve the control structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id)
+{
+       struct pvr2_ctrl *cptr;
+       unsigned int idx;
+       int i;
+
+       /* This could be made a lot more efficient, but for now... */
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               i = cptr->info->v4l_id;
+               if (i && (i == ctl_id)) return cptr;
+       }
+       return NULL;
+}
+
+
+/* Given a V4L ID for its immediate predecessor, retrieve the control
+   structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw,
+                                           unsigned int ctl_id)
+{
+       struct pvr2_ctrl *cptr,*cp2;
+       unsigned int idx;
+       int i;
+
+       /* This could be made a lot more efficient, but for now... */
+       cp2 = NULL;
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               i = cptr->info->v4l_id;
+               if (!i) continue;
+               if (i <= ctl_id) continue;
+               if (cp2 && (cp2->info->v4l_id < i)) continue;
+               cp2 = cptr;
+       }
+       return cp2;
+       return NULL;
+}
+
+
+static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
+{
+       switch (tp) {
+       case pvr2_ctl_int: return "integer";
+       case pvr2_ctl_enum: return "enum";
+       case pvr2_ctl_bool: return "boolean";
+       case pvr2_ctl_bitmask: return "bitmask";
+       }
+       return "";
+}
+
+
+/* Commit all control changes made up to this point.  Subsystems can be
+   indirectly affected by these changes.  For a given set of things being
+   committed, we'll clear the affected subsystem bits and then once we're
+   done committing everything we'll make a request to restore the subsystem
+   state(s) back to their previous value before this function was called.
+   Thus we can automatically reconfigure affected pieces of the driver as
+   controls are changed. */
+static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
+{
+       unsigned long saved_subsys_mask = hdw->subsys_enabled_mask;
+       unsigned long stale_subsys_mask = 0;
+       unsigned int idx;
+       struct pvr2_ctrl *cptr;
+       int value;
+       int commit_flag = 0;
+       char buf[100];
+       unsigned int bcnt,ccnt;
+
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               if (cptr->info->is_dirty == 0) continue;
+               if (!cptr->info->is_dirty(cptr)) continue;
+               if (!commit_flag) {
+                       commit_flag = !0;
+               }
+
+               bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
+                                cptr->info->name);
+               value = 0;
+               cptr->info->get_value(cptr,&value);
+               pvr2_ctrl_value_to_sym_internal(cptr,~0,value,
+                                               buf+bcnt,
+                                               sizeof(buf)-bcnt,&ccnt);
+               bcnt += ccnt;
+               bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>",
+                                 get_ctrl_typename(cptr->info->type));
+               pvr2_trace(PVR2_TRACE_CTL,
+                          "/*--TRACE_COMMIT--*/ %.*s",
+                          bcnt,buf);
+       }
+
+       if (!commit_flag) {
+               /* Nothing has changed */
+               return 0;
+       }
+
+       /* When video standard changes, reset the hres and vres values -
+          but if the user has pending changes there, then let the changes
+          take priority. */
+       if (hdw->std_dirty) {
+               /* Rewrite the vertical resolution to be appropriate to the
+                  video standard that has been selected. */
+               int nvres;
+               if (hdw->std_mask_cur & V4L2_STD_525_60) {
+                       nvres = 480;
+               } else {
+                       nvres = 576;
+               }
+               if (nvres != hdw->res_ver_val) {
+                       hdw->res_ver_val = nvres;
+                       hdw->res_ver_dirty = !0;
+               }
+       }
+
+       if (hdw->std_dirty ||
+           0) {
+               /* If any of this changes, then the encoder needs to be
+                  reconfigured, and we need to reset the stream. */
+               stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+               stale_subsys_mask |= hdw->subsys_stream_mask;
+       }
+
+       if (hdw->srate_dirty) {
+               /* Write new sample rate into control structure since
+                * the master copy is stale.  We must track srate
+                * separate from the mpeg control structure because
+                * other logic also uses this value. */
+               struct v4l2_ext_controls cs;
+               struct v4l2_ext_control c1;
+               memset(&cs,0,sizeof(cs));
+               memset(&c1,0,sizeof(c1));
+               cs.controls = &c1;
+               cs.count = 1;
+               c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
+               c1.value = hdw->srate_val;
+               cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS);
+       }
+
+       /* Scan i2c core at this point - before we clear all the dirty
+          bits.  Various parts of the i2c core will notice dirty bits as
+          appropriate and arrange to broadcast or directly send updates to
+          the client drivers in order to keep everything in sync */
+       pvr2_i2c_core_check_stale(hdw);
+
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               if (!cptr->info->clear_dirty) continue;
+               cptr->info->clear_dirty(cptr);
+       }
+
+       /* Now execute i2c core update */
+       pvr2_i2c_core_sync(hdw);
+
+       pvr2_hdw_subsys_bit_chg_no_lock(hdw,stale_subsys_mask,0);
+       pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,saved_subsys_mask);
+
+       return 0;
+}
+
+
+int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_hdw_commit_ctl_internal(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return 0;
+}
+
+
+void pvr2_hdw_poll(struct pvr2_hdw *hdw)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_i2c_core_sync(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *hdw,
+                                void (*func)(void *),
+                                void *data)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               hdw->poll_trigger_func = func;
+               hdw->poll_trigger_data = data;
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw)
+{
+       if (hdw->poll_trigger_func) {
+               hdw->poll_trigger_func(hdw->poll_trigger_data);
+       }
+}
+
+/* Return name for this driver instance */
+const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
+{
+       return hdw->name;
+}
+
+
+/* Return bit mask indicating signal status */
+static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
+{
+       unsigned int msk = 0;
+       switch (hdw->input_val) {
+       case PVR2_CVAL_INPUT_TV:
+       case PVR2_CVAL_INPUT_RADIO:
+               if (hdw->decoder_ctrl &&
+                   hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) {
+                       msk |= PVR2_SIGNAL_OK;
+                       if (hdw->audio_stat &&
+                           hdw->audio_stat->status(hdw->audio_stat->ctxt)) {
+                               if (hdw->flag_stereo) {
+                                       msk |= PVR2_SIGNAL_STEREO;
+                               }
+                               if (hdw->flag_bilingual) {
+                                       msk |= PVR2_SIGNAL_SAP;
+                               }
+                       }
+               }
+               break;
+       default:
+               msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO;
+       }
+       return msk;
+}
+
+
+int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
+{
+       int result;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = 0x0b;
+               result = pvr2_send_request(hdw,
+                                          hdw->cmd_buffer,1,
+                                          hdw->cmd_buffer,1);
+               if (result < 0) break;
+               result = (hdw->cmd_buffer[0] != 0);
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+       return result;
+}
+
+
+/* Return bit mask indicating signal status */
+unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
+{
+       unsigned int msk = 0;
+       LOCK_TAKE(hdw->big_lock); do {
+               msk = pvr2_hdw_get_signal_status_internal(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return msk;
+}
+
+
+/* Get handle to video output stream */
+struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
+{
+       return hp->vid_stream;
+}
+
+
+void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
+{
+       int nr = pvr2_hdw_get_unit_number(hdw);
+       LOCK_TAKE(hdw->big_lock); do {
+               hdw->log_requested = !0;
+               printk(KERN_INFO "pvrusb2: =================  START STATUS CARD #%d  =================\n", nr);
+               pvr2_i2c_core_check_stale(hdw);
+               hdw->log_requested = 0;
+               pvr2_i2c_core_sync(hdw);
+               pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
+               cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
+               printk(KERN_INFO "pvrusb2: ==================  END STATUS CARD #%d  ==================\n", nr);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
+{
+       int ret;
+       u16 address;
+       unsigned int pipe;
+       LOCK_TAKE(hdw->big_lock); do {
+               if ((hdw->fw_buffer == 0) == !enable_flag) break;
+
+               if (!enable_flag) {
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Cleaning up after CPU firmware fetch");
+                       kfree(hdw->fw_buffer);
+                       hdw->fw_buffer = NULL;
+                       hdw->fw_size = 0;
+                       /* Now release the CPU.  It will disconnect and
+                          reconnect later. */
+                       pvr2_hdw_cpureset_assert(hdw,0);
+                       break;
+               }
+
+               pvr2_trace(PVR2_TRACE_FIRMWARE,
+                          "Preparing to suck out CPU firmware");
+               hdw->fw_size = 0x2000;
+               hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL);
+               if (!hdw->fw_buffer) {
+                       hdw->fw_size = 0;
+                       break;
+               }
+
+               memset(hdw->fw_buffer,0,hdw->fw_size);
+
+               /* We have to hold the CPU during firmware upload. */
+               pvr2_hdw_cpureset_assert(hdw,1);
+
+               /* download the firmware from address 0000-1fff in 2048
+                  (=0x800) bytes chunk. */
+
+               pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware");
+               pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
+               for(address = 0; address < hdw->fw_size; address += 0x800) {
+                       ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0,
+                                             address,0,
+                                             hdw->fw_buffer+address,0x800,HZ);
+                       if (ret < 0) break;
+               }
+
+               pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware");
+
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+/* Return true if we're in a mode for retrieval CPU firmware */
+int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
+{
+       return hdw->fw_buffer != 0;
+}
+
+
+int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs,
+                      char *buf,unsigned int cnt)
+{
+       int ret = -EINVAL;
+       LOCK_TAKE(hdw->big_lock); do {
+               if (!buf) break;
+               if (!cnt) break;
+
+               if (!hdw->fw_buffer) {
+                       ret = -EIO;
+                       break;
+               }
+
+               if (offs >= hdw->fw_size) {
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Read firmware data offs=%d EOF",
+                                  offs);
+                       ret = 0;
+                       break;
+               }
+
+               if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs;
+
+               memcpy(buf,hdw->fw_buffer+offs,cnt);
+
+               pvr2_trace(PVR2_TRACE_FIRMWARE,
+                          "Read firmware data offs=%d cnt=%d",
+                          offs,cnt);
+               ret = cnt;
+       } while (0); LOCK_GIVE(hdw->big_lock);
+
+       return ret;
+}
+
+
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw)
+{
+       return hdw->v4l_minor_number;
+}
+
+
+/* Store the v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
+{
+       hdw->v4l_minor_number = v;
+}
+
+
+static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
+{
+       struct pvr2_hdw *hdw = urb->context;
+       hdw->ctl_write_pend_flag = 0;
+       if (hdw->ctl_read_pend_flag) return;
+       complete(&hdw->ctl_done);
+}
+
+
+static void pvr2_ctl_read_complete(struct urb *urb, struct pt_regs *regs)
+{
+       struct pvr2_hdw *hdw = urb->context;
+       hdw->ctl_read_pend_flag = 0;
+       if (hdw->ctl_write_pend_flag) return;
+       complete(&hdw->ctl_done);
+}
+
+
+static void pvr2_ctl_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
+               hdw->ctl_timeout_flag = !0;
+               if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) {
+                       usb_unlink_urb(hdw->ctl_write_urb);
+               }
+               if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
+                       usb_unlink_urb(hdw->ctl_read_urb);
+               }
+       }
+}
+
+
+/* Issue a command and get a response from the device.  This extended
+   version includes a probe flag (which if set means that device errors
+   should not be logged or treated as fatal) and a timeout in jiffies.
+   This can be used to non-lethally probe the health of endpoint 1. */
+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)
+{
+       unsigned int idx;
+       int status = 0;
+       struct timer_list timer;
+       if (!hdw->ctl_lock_held) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Attempted to execute control transfer"
+                          " without lock!!");
+               return -EDEADLK;
+       }
+       if ((!hdw->flag_ok) && !probe_fl) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Attempted to execute control transfer"
+                          " when device not ok");
+               return -EIO;
+       }
+       if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
+               if (!probe_fl) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Attempted to execute control transfer"
+                                  " when USB is disconnected");
+               }
+               return -ENOTTY;
+       }
+
+       /* Ensure that we have sane parameters */
+       if (!write_data) write_len = 0;
+       if (!read_data) read_len = 0;
+       if (write_len > PVR2_CTL_BUFFSIZE) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Attempted to execute %d byte"
+                       " control-write transfer (limit=%d)",
+                       write_len,PVR2_CTL_BUFFSIZE);
+               return -EINVAL;
+       }
+       if (read_len > PVR2_CTL_BUFFSIZE) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Attempted to execute %d byte"
+                       " control-read transfer (limit=%d)",
+                       write_len,PVR2_CTL_BUFFSIZE);
+               return -EINVAL;
+       }
+       if ((!write_len) && (!read_len)) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Attempted to execute null control transfer?");
+               return -EINVAL;
+       }
+
+
+       hdw->cmd_debug_state = 1;
+       if (write_len) {
+               hdw->cmd_debug_code = ((unsigned char *)write_data)[0];
+       } else {
+               hdw->cmd_debug_code = 0;
+       }
+       hdw->cmd_debug_write_len = write_len;
+       hdw->cmd_debug_read_len = read_len;
+
+       /* Initialize common stuff */
+       init_completion(&hdw->ctl_done);
+       hdw->ctl_timeout_flag = 0;
+       hdw->ctl_write_pend_flag = 0;
+       hdw->ctl_read_pend_flag = 0;
+       init_timer(&timer);
+       timer.expires = jiffies + timeout;
+       timer.data = (unsigned long)hdw;
+       timer.function = pvr2_ctl_timeout;
+
+       if (write_len) {
+               hdw->cmd_debug_state = 2;
+               /* Transfer write data to internal buffer */
+               for (idx = 0; idx < write_len; idx++) {
+                       hdw->ctl_write_buffer[idx] =
+                               ((unsigned char *)write_data)[idx];
+               }
+               /* Initiate a write request */
+               usb_fill_bulk_urb(hdw->ctl_write_urb,
+                                 hdw->usb_dev,
+                                 usb_sndbulkpipe(hdw->usb_dev,
+                                                 PVR2_CTL_WRITE_ENDPOINT),
+                                 hdw->ctl_write_buffer,
+                                 write_len,
+                                 pvr2_ctl_write_complete,
+                                 hdw);
+               hdw->ctl_write_urb->actual_length = 0;
+               hdw->ctl_write_pend_flag = !0;
+               status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL);
+               if (status < 0) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Failed to submit write-control"
+                                  " URB status=%d",status);
+                       hdw->ctl_write_pend_flag = 0;
+                       goto done;
+               }
+       }
+
+       if (read_len) {
+               hdw->cmd_debug_state = 3;
+               memset(hdw->ctl_read_buffer,0x43,read_len);
+               /* Initiate a read request */
+               usb_fill_bulk_urb(hdw->ctl_read_urb,
+                                 hdw->usb_dev,
+                                 usb_rcvbulkpipe(hdw->usb_dev,
+                                                 PVR2_CTL_READ_ENDPOINT),
+                                 hdw->ctl_read_buffer,
+                                 read_len,
+                                 pvr2_ctl_read_complete,
+                                 hdw);
+               hdw->ctl_read_urb->actual_length = 0;
+               hdw->ctl_read_pend_flag = !0;
+               status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL);
+               if (status < 0) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Failed to submit read-control"
+                                  " URB status=%d",status);
+                       hdw->ctl_read_pend_flag = 0;
+                       goto done;
+               }
+       }
+
+       /* Start timer */
+       add_timer(&timer);
+
+       /* Now wait for all I/O to complete */
+       hdw->cmd_debug_state = 4;
+       while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
+               wait_for_completion(&hdw->ctl_done);
+       }
+       hdw->cmd_debug_state = 5;
+
+       /* Stop timer */
+       del_timer_sync(&timer);
+
+       hdw->cmd_debug_state = 6;
+       status = 0;
+
+       if (hdw->ctl_timeout_flag) {
+               status = -ETIMEDOUT;
+               if (!probe_fl) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Timed out control-write");
+               }
+               goto done;
+       }
+
+       if (write_len) {
+               /* Validate results of write request */
+               if ((hdw->ctl_write_urb->status != 0) &&
+                   (hdw->ctl_write_urb->status != -ENOENT) &&
+                   (hdw->ctl_write_urb->status != -ESHUTDOWN) &&
+                   (hdw->ctl_write_urb->status != -ECONNRESET)) {
+                       /* USB subsystem is reporting some kind of failure
+                          on the write */
+                       status = hdw->ctl_write_urb->status;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-write URB failure,"
+                                          " status=%d",
+                                          status);
+                       }
+                       goto done;
+               }
+               if (hdw->ctl_write_urb->actual_length < write_len) {
+                       /* Failed to write enough data */
+                       status = -EIO;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-write URB short,"
+                                          " expected=%d got=%d",
+                                          write_len,
+                                          hdw->ctl_write_urb->actual_length);
+                       }
+                       goto done;
+               }
+       }
+       if (read_len) {
+               /* Validate results of read request */
+               if ((hdw->ctl_read_urb->status != 0) &&
+                   (hdw->ctl_read_urb->status != -ENOENT) &&
+                   (hdw->ctl_read_urb->status != -ESHUTDOWN) &&
+                   (hdw->ctl_read_urb->status != -ECONNRESET)) {
+                       /* USB subsystem is reporting some kind of failure
+                          on the read */
+                       status = hdw->ctl_read_urb->status;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-read URB failure,"
+                                          " status=%d",
+                                          status);
+                       }
+                       goto done;
+               }
+               if (hdw->ctl_read_urb->actual_length < read_len) {
+                       /* Failed to read enough data */
+                       status = -EIO;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-read URB short,"
+                                          " expected=%d got=%d",
+                                          read_len,
+                                          hdw->ctl_read_urb->actual_length);
+                       }
+                       goto done;
+               }
+               /* Transfer retrieved data out from internal buffer */
+               for (idx = 0; idx < read_len; idx++) {
+                       ((unsigned char *)read_data)[idx] =
+                               hdw->ctl_read_buffer[idx];
+               }
+       }
+
+ done:
+
+       hdw->cmd_debug_state = 0;
+       if ((status < 0) && (!probe_fl)) {
+               pvr2_hdw_render_useless_unlocked(hdw);
+       }
+       return status;
+}
+
+
+int pvr2_send_request(struct pvr2_hdw *hdw,
+                     void *write_data,unsigned int write_len,
+                     void *read_data,unsigned int read_len)
+{
+       return pvr2_send_request_ex(hdw,HZ*4,0,
+                                   write_data,write_len,
+                                   read_data,read_len);
+}
+
+int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
+{
+       int ret;
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       hdw->cmd_buffer[0] = 0x04;  /* write register prefix */
+       PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
+       hdw->cmd_buffer[5] = 0;
+       hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
+       hdw->cmd_buffer[7] = reg & 0xff;
+
+
+       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0);
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
+{
+       int ret = 0;
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       hdw->cmd_buffer[0] = 0x05;  /* read register prefix */
+       hdw->cmd_buffer[1] = 0;
+       hdw->cmd_buffer[2] = 0;
+       hdw->cmd_buffer[3] = 0;
+       hdw->cmd_buffer[4] = 0;
+       hdw->cmd_buffer[5] = 0;
+       hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
+       hdw->cmd_buffer[7] = reg & 0xff;
+
+       ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4);
+       *data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0);
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
+{
+       int ret;
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       hdw->cmd_buffer[0] = (data >> 8) & 0xff;
+       hdw->cmd_buffer[1] = data & 0xff;
+
+       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res);
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
+{
+       int ret;
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       hdw->cmd_buffer[0] = data;
+
+       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res);
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
+{
+       if (!hdw->flag_ok) return;
+       pvr2_trace(PVR2_TRACE_INIT,"render_useless");
+       hdw->flag_ok = 0;
+       if (hdw->vid_stream) {
+               pvr2_stream_setup(hdw->vid_stream,NULL,0,0);
+       }
+       hdw->flag_streaming_enabled = 0;
+       hdw->subsys_enabled_mask = 0;
+}
+
+
+void pvr2_hdw_render_useless(struct pvr2_hdw *hdw)
+{
+       LOCK_TAKE(hdw->ctl_lock);
+       pvr2_hdw_render_useless_unlocked(hdw);
+       LOCK_GIVE(hdw->ctl_lock);
+}
+
+
+void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
+{
+       int ret;
+       pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
+       ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
+       if (ret == 1) {
+               ret = usb_reset_device(hdw->usb_dev);
+               usb_unlock_device(hdw->usb_dev);
+       } else {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to lock USB device ret=%d",ret);
+       }
+       if (init_pause_msec) {
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Waiting %u msec for hardware to settle",
+                          init_pause_msec);
+               msleep(init_pause_msec);
+       }
+
+}
+
+
+void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
+{
+       char da[1];
+       unsigned int pipe;
+       int ret;
+
+       if (!hdw->usb_dev) return;
+
+       pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
+
+       da[0] = val ? 0x01 : 0x00;
+
+       /* Write the CPUCS register on the 8051.  The lsb of the register
+          is the reset bit; a 1 asserts reset while a 0 clears it. */
+       pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
+       ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "cpureset_assert(%d) error=%d",val,ret);
+               pvr2_hdw_render_useless(hdw);
+       }
+}
+
+
+int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
+{
+       int status;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
+               hdw->flag_ok = !0;
+               hdw->cmd_buffer[0] = 0xdd;
+               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       return status;
+}
+
+
+int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
+{
+       int status;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
+               hdw->cmd_buffer[0] = 0xde;
+               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       return status;
+}
+
+
+int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
+{
+       if (!hdw->decoder_ctrl) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Unable to reset decoder: nothing attached");
+               return -ENOTTY;
+       }
+
+       if (!hdw->decoder_ctrl->force_reset) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Unable to reset decoder: not implemented");
+               return -ENOTTY;
+       }
+
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "Requesting decoder reset");
+       hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt);
+       return 0;
+}
+
+
+/* Stop / start video stream transport */
+static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
+{
+       int status;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37);
+               status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
+       if (!status) {
+               hdw->subsys_enabled_mask =
+                       ((hdw->subsys_enabled_mask &
+                         ~(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) |
+                        (runFl ? (1<<PVR2_SUBSYS_B_USBSTREAM_RUN) : 0));
+       }
+       return status;
+}
+
+
+void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw,
+                            struct pvr2_hdw_debug_info *ptr)
+{
+       ptr->big_lock_held = hdw->big_lock_held;
+       ptr->ctl_lock_held = hdw->ctl_lock_held;
+       ptr->flag_ok = hdw->flag_ok;
+       ptr->flag_disconnected = hdw->flag_disconnected;
+       ptr->flag_init_ok = hdw->flag_init_ok;
+       ptr->flag_streaming_enabled = hdw->flag_streaming_enabled;
+       ptr->subsys_flags = hdw->subsys_enabled_mask;
+       ptr->cmd_debug_state = hdw->cmd_debug_state;
+       ptr->cmd_code = hdw->cmd_debug_code;
+       ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
+       ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
+       ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
+       ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
+       ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
+       ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
+       ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
+}
+
+
+int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
+{
+       return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
+}
+
+
+int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp)
+{
+       return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp);
+}
+
+
+int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp)
+{
+       return pvr2_read_register(hdw,PVR2_GPIO_IN,dp);
+}
+
+
+int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val)
+{
+       u32 cval,nval;
+       int ret;
+       if (~msk) {
+               ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval);
+               if (ret) return ret;
+               nval = (cval & ~msk) | (val & msk);
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO direction changing 0x%x:0x%x"
+                          " from 0x%x to 0x%x",
+                          msk,val,cval,nval);
+       } else {
+               nval = val;
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO direction changing to 0x%x",nval);
+       }
+       return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval);
+}
+
+
+int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
+{
+       u32 cval,nval;
+       int ret;
+       if (~msk) {
+               ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval);
+               if (ret) return ret;
+               nval = (cval & ~msk) | (val & msk);
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x",
+                          msk,val,cval,nval);
+       } else {
+               nval = val;
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO output changing to 0x%x",nval);
+       }
+       return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval);
+}
+
+
+/* Find I2C address of eeprom */
+static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
+{
+       int result;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = 0xeb;
+               result = pvr2_send_request(hdw,
+                                          hdw->cmd_buffer,1,
+                                          hdw->cmd_buffer,1);
+               if (result < 0) break;
+               result = hdw->cmd_buffer[0];
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+       return result;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
new file mode 100644 (file)
index 0000000..fd931b5
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_HDW_H
+#define __PVRUSB2_HDW_H
+
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include "pvrusb2-io.h"
+#include "pvrusb2-ctrl.h"
+
+
+/* Private internal control ids, look these up with
+   pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */
+#define PVR2_CID_STDENUM 1
+#define PVR2_CID_STDCUR 2
+#define PVR2_CID_STDAVAIL 3
+#define PVR2_CID_INPUT 4
+#define PVR2_CID_AUDIOMODE 5
+#define PVR2_CID_FREQUENCY 6
+#define PVR2_CID_HRES 7
+#define PVR2_CID_VRES 8
+
+/* Legal values for the INPUT state variable */
+#define PVR2_CVAL_INPUT_TV 0
+#define PVR2_CVAL_INPUT_SVIDEO 1
+#define PVR2_CVAL_INPUT_COMPOSITE 2
+#define PVR2_CVAL_INPUT_RADIO 3
+
+/* Values that pvr2_hdw_get_signal_status() returns */
+#define PVR2_SIGNAL_OK     0x0001
+#define PVR2_SIGNAL_STEREO 0x0002
+#define PVR2_SIGNAL_SAP    0x0004
+
+
+/* Subsystem definitions - these are various pieces that can be
+   independently stopped / started.  Usually you don't want to mess with
+   this directly (let the driver handle things itself), but it is useful
+   for debugging. */
+#define PVR2_SUBSYS_B_ENC_FIRMWARE        0
+#define PVR2_SUBSYS_B_ENC_CFG             1
+#define PVR2_SUBSYS_B_DIGITIZER_RUN       2
+#define PVR2_SUBSYS_B_USBSTREAM_RUN       3
+#define PVR2_SUBSYS_B_ENC_RUN             4
+
+#define PVR2_SUBSYS_CFG_ALL ( \
+       (1 << PVR2_SUBSYS_B_ENC_FIRMWARE) | \
+       (1 << PVR2_SUBSYS_B_ENC_CFG) )
+#define PVR2_SUBSYS_RUN_ALL ( \
+       (1 << PVR2_SUBSYS_B_DIGITIZER_RUN) | \
+       (1 << PVR2_SUBSYS_B_USBSTREAM_RUN) | \
+       (1 << PVR2_SUBSYS_B_ENC_RUN) )
+#define PVR2_SUBSYS_ALL ( \
+       PVR2_SUBSYS_CFG_ALL | \
+       PVR2_SUBSYS_RUN_ALL )
+
+enum pvr2_config {
+       pvr2_config_empty,
+       pvr2_config_mpeg,
+       pvr2_config_vbi,
+       pvr2_config_radio,
+};
+
+const char *pvr2_config_get_name(enum pvr2_config);
+
+struct pvr2_hdw;
+
+/* Create and return a structure for interacting with the underlying
+   hardware */
+struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+                                const struct usb_device_id *devid);
+
+/* Poll for background activity (if any) */
+void pvr2_hdw_poll(struct pvr2_hdw *);
+
+/* Trigger a poll to take place later at a convenient time */
+void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *);
+
+/* Register a callback used to trigger a future poll */
+void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *,
+                                void (*func)(void *),
+                                void *data);
+
+/* Destroy hardware interaction structure */
+void pvr2_hdw_destroy(struct pvr2_hdw *);
+
+/* Set up the structure and attempt to put the device into a usable state.
+   This can be a time-consuming operation, which is why it is not done
+   internally as part of the create() step.  Return value is exactly the
+   same as pvr2_hdw_init_ok(). */
+int pvr2_hdw_setup(struct pvr2_hdw *);
+
+/* Initialization succeeded */
+int pvr2_hdw_init_ok(struct pvr2_hdw *);
+
+/* Return true if in the ready (normal) state */
+int pvr2_hdw_dev_ok(struct pvr2_hdw *);
+
+/* Return small integer number [1..N] for logical instance number of this
+   device.  This is useful for indexing array-valued module parameters. */
+int pvr2_hdw_get_unit_number(struct pvr2_hdw *);
+
+/* Get pointer to underlying USB device */
+struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *);
+
+/* Retrieve serial number of device */
+unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *);
+
+/* Called when hardware has been unplugged */
+void pvr2_hdw_disconnect(struct pvr2_hdw *);
+
+/* Get the number of defined controls */
+unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *);
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int);
+
+/* Retrieve a control handle given its internal ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int);
+
+/* Retrieve a control handle given its V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id);
+
+/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
+                                           unsigned int ctl_id);
+
+/* Commit all control changes made up to this point */
+int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
+
+/* Return name for this driver instance */
+const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
+
+/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */
+unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *);
+
+/* Query device and see if it thinks it is on a high-speed USB link */
+int pvr2_hdw_is_hsm(struct pvr2_hdw *);
+
+/* Turn streaming on/off */
+int pvr2_hdw_set_streaming(struct pvr2_hdw *,int);
+
+/* Find out if streaming is on */
+int pvr2_hdw_get_streaming(struct pvr2_hdw *);
+
+/* Configure the type of stream to generate */
+int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config);
+
+/* Get handle to video output stream */
+struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
+
+/* Emit a video standard struct */
+int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std,
+                              unsigned int idx);
+
+/* Enable / disable various pieces of hardware.  Items to change are
+   identified by bit positions within msk, and new state for each item is
+   identified by corresponding bit positions within val. */
+void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
+                            unsigned long msk,unsigned long val);
+
+/* Retrieve mask indicating which pieces of hardware are currently enabled
+   / configured. */
+unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *);
+
+/* Adjust mask of what get shut down when streaming is stopped.  This is a
+   debugging aid. */
+void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
+                                   unsigned long msk,unsigned long val);
+
+/* Retrieve mask indicating which pieces of hardware are disabled when
+   streaming is turned off. */
+unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *);
+
+
+/* Enable / disable retrieval of CPU firmware.  This must be enabled before
+   pvr2_hdw_cpufw_get() will function.  Note that doing this may prevent
+   the device from running (and leaving this mode may imply a device
+   reset). */
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, int enable_flag);
+
+/* Return true if we're in a mode for retrieval CPU firmware */
+int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *);
+
+/* Retrieve a piece of the CPU's firmware at the given offset.  Return
+   value is the number of bytes retrieved or zero if we're past the end or
+   an error otherwise (e.g. if firmware retrieval is not enabled). */
+int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs,
+                      char *buf,unsigned int cnt);
+
+/* Retrieve previously stored v4l minor device number */
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *);
+
+/* Store the v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
+
+
+/* The following entry points are all lower level things you normally don't
+   want to worry about. */
+
+/* Issue a command and get a response from the device.  LOTS of higher
+   level stuff is built on this. */
+int pvr2_send_request(struct pvr2_hdw *,
+                     void *write_ptr,unsigned int write_len,
+                     void *read_ptr,unsigned int read_len);
+
+/* Slightly higher level device communication functions. */
+int pvr2_write_register(struct pvr2_hdw *, u16, u32);
+
+/* Call if for any reason we can't talk to the hardware anymore - this will
+   cause the driver to stop flailing on the device. */
+void pvr2_hdw_render_useless(struct pvr2_hdw *);
+
+/* Set / clear 8051's reset bit */
+void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int);
+
+/* Execute a USB-commanded device reset */
+void pvr2_hdw_device_reset(struct pvr2_hdw *);
+
+/* Execute hard reset command (after this point it's likely that the
+   encoder will have to be reconfigured).  This also clears the "useless"
+   state. */
+int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
+
+/* Execute simple reset command */
+int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
+
+/* Order decoder to reset */
+int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
+
+/* Direct manipulation of GPIO bits */
+int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val);
+int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val);
+
+/* This data structure is specifically for the next function... */
+struct pvr2_hdw_debug_info {
+       int big_lock_held;
+       int ctl_lock_held;
+       int flag_ok;
+       int flag_disconnected;
+       int flag_init_ok;
+       int flag_streaming_enabled;
+       unsigned long subsys_flags;
+       int cmd_debug_state;
+       int cmd_debug_write_len;
+       int cmd_debug_read_len;
+       int cmd_debug_write_pend;
+       int cmd_debug_read_pend;
+       int cmd_debug_timeout;
+       int cmd_debug_rstatus;
+       int cmd_debug_wstatus;
+       unsigned char cmd_code;
+};
+
+/* Non-intrusively retrieve internal state info - this is useful for
+   diagnosing lockups.  Note that this operation is completed without any
+   kind of locking and so it is not atomic and may yield inconsistent
+   results.  This is *purely* a debugging aid. */
+void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw,
+                            struct pvr2_hdw_debug_info *);
+
+/* Cause modules to log their state once */
+void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
+
+/* Cause encoder firmware to be uploaded into the device.  This is normally
+   done autonomously, but the interface is exported here because it is also
+   a debugging aid. */
+int pvr2_upload_firmware2(struct pvr2_hdw *hdw);
+
+/* List of device types that we can match */
+extern struct usb_device_id pvr2_device_table[];
+
+#endif /* __PVRUSB2_HDW_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
new file mode 100644 (file)
index 0000000..fbe6039
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+#include "pvrusb2-audio.h"
+#include "pvrusb2-tuner.h"
+#include "pvrusb2-video-v4l.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-wm8775.h"
+#endif
+
+#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
+
+#define OP_STANDARD 0
+#define OP_BCSH 1
+#define OP_VOLUME 2
+#define OP_FREQ 3
+#define OP_AUDIORATE 4
+#define OP_SIZE 5
+#define OP_LOG 6
+
+static const struct pvr2_i2c_op * const ops[] = {
+       [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
+       [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
+       [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
+       [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
+       [OP_SIZE] = &pvr2_i2c_op_v4l2_size,
+       [OP_LOG] = &pvr2_i2c_op_v4l2_log,
+};
+
+void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+       int id;
+       id = cp->client->driver->id;
+       cp->ctl_mask = ((1 << OP_STANDARD) |
+                       (1 << OP_BCSH) |
+                       (1 << OP_VOLUME) |
+                       (1 << OP_FREQ) |
+                       (1 << OP_SIZE) |
+                       (1 << OP_LOG));
+
+       if (id == I2C_DRIVERID_MSP3400) {
+               if (pvr2_i2c_msp3400_setup(hdw,cp)) {
+                       return;
+               }
+       }
+       if (id == I2C_DRIVERID_TUNER) {
+               if (pvr2_i2c_tuner_setup(hdw,cp)) {
+                       return;
+               }
+       }
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+       if (id == I2C_DRIVERID_CX25840) {
+               if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
+                       return;
+               }
+       }
+       if (id == I2C_DRIVERID_WM8775) {
+               if (pvr2_i2c_wm8775_setup(hdw,cp)) {
+                       return;
+               }
+       }
+#endif
+       if (id == I2C_DRIVERID_SAA711X) {
+               if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
+                       return;
+               }
+       }
+}
+
+
+const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
+{
+       if (idx >= sizeof(ops)/sizeof(ops[0])) return 0;
+       return ops[idx];
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
new file mode 100644 (file)
index 0000000..8a9933d
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-i2c-cmd-v4l2.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+
+
+static void set_standard(struct pvr2_hdw *hdw)
+{
+       v4l2_std_id vs;
+       vs = hdw->std_mask_cur;
+       pvr2_trace(PVR2_TRACE_CHIPS,
+                  "i2c v4l2 set_standard(0x%llx)",(__u64)vs);
+
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
+}
+
+
+static int check_standard(struct pvr2_hdw *hdw)
+{
+       return hdw->std_dirty != 0;
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = {
+       .check = check_standard,
+       .update = set_standard,
+       .name = "v4l2_standard",
+};
+
+
+static void set_bcsh(struct pvr2_hdw *hdw)
+{
+       struct v4l2_control ctrl;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh"
+                  " b=%d c=%d s=%d h=%d",
+                  hdw->brightness_val,hdw->contrast_val,
+                  hdw->saturation_val,hdw->hue_val);
+       memset(&ctrl,0,sizeof(ctrl));
+       ctrl.id = V4L2_CID_BRIGHTNESS;
+       ctrl.value = hdw->brightness_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_CONTRAST;
+       ctrl.value = hdw->contrast_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_SATURATION;
+       ctrl.value = hdw->saturation_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_HUE;
+       ctrl.value = hdw->hue_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+}
+
+
+static int check_bcsh(struct pvr2_hdw *hdw)
+{
+       return (hdw->brightness_dirty ||
+               hdw->contrast_dirty ||
+               hdw->saturation_dirty ||
+               hdw->hue_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = {
+       .check = check_bcsh,
+       .update = set_bcsh,
+       .name = "v4l2_bcsh",
+};
+
+
+static void set_volume(struct pvr2_hdw *hdw)
+{
+       struct v4l2_control ctrl;
+       pvr2_trace(PVR2_TRACE_CHIPS,
+                  "i2c v4l2 set_volume"
+                  "(vol=%d bal=%d bas=%d treb=%d mute=%d)",
+                  hdw->volume_val,
+                  hdw->balance_val,
+                  hdw->bass_val,
+                  hdw->treble_val,
+                  hdw->mute_val);
+       memset(&ctrl,0,sizeof(ctrl));
+       ctrl.id = V4L2_CID_AUDIO_MUTE;
+       ctrl.value = hdw->mute_val ? 1 : 0;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_AUDIO_VOLUME;
+       ctrl.value = hdw->volume_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_AUDIO_BALANCE;
+       ctrl.value = hdw->balance_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_AUDIO_BASS;
+       ctrl.value = hdw->bass_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+       ctrl.id = V4L2_CID_AUDIO_TREBLE;
+       ctrl.value = hdw->treble_val;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+}
+
+
+static int check_volume(struct pvr2_hdw *hdw)
+{
+       return (hdw->volume_dirty ||
+               hdw->balance_dirty ||
+               hdw->bass_dirty ||
+               hdw->treble_dirty ||
+               hdw->mute_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = {
+       .check = check_volume,
+       .update = set_volume,
+       .name = "v4l2_volume",
+};
+
+
+static void set_frequency(struct pvr2_hdw *hdw)
+{
+       unsigned long fv;
+       struct v4l2_frequency freq;
+       fv = hdw->freqVal;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
+       memset(&freq,0,sizeof(freq));
+       freq.frequency = fv / 62500;
+       freq.tuner = 0;
+       freq.type = V4L2_TUNER_ANALOG_TV;
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
+}
+
+
+static int check_frequency(struct pvr2_hdw *hdw)
+{
+       return hdw->freqDirty != 0;
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = {
+       .check = check_frequency,
+       .update = set_frequency,
+       .name = "v4l2_freq",
+};
+
+
+static void set_size(struct pvr2_hdw *hdw)
+{
+       struct v4l2_format fmt;
+
+       memset(&fmt,0,sizeof(fmt));
+
+       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       fmt.fmt.pix.width = hdw->res_hor_val;
+       fmt.fmt.pix.height = hdw->res_ver_val;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)",
+                          fmt.fmt.pix.width,fmt.fmt.pix.height);
+
+       pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt);
+}
+
+
+static int check_size(struct pvr2_hdw *hdw)
+{
+       return (hdw->res_hor_dirty || hdw->res_ver_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
+       .check = check_size,
+       .update = set_size,
+       .name = "v4l2_size",
+};
+
+
+static void do_log(struct pvr2_hdw *hdw)
+{
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
+       pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL);
+
+}
+
+
+static int check_log(struct pvr2_hdw *hdw)
+{
+       return hdw->log_requested != 0;
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = {
+       .check = check_log,
+       .update = do_log,
+       .name = "v4l2_log",
+};
+
+
+void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
+{
+       pvr2_i2c_client_cmd(cp,
+                           (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL);
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
new file mode 100644 (file)
index 0000000..ecabddb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_CMD_V4L2_H
+#define __PVRUSB2_CMD_V4L2_H
+
+#include "pvrusb2-i2c-core.h"
+
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
+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_size;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
+
+void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
+
+#endif /* __PVRUSB2_CMD_V4L2_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
new file mode 100644 (file)
index 0000000..7fca479
--- /dev/null
@@ -0,0 +1,941 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
+
+/*
+
+  This module attempts to implement a compliant I2C adapter for the pvrusb2
+  device.  By doing this we can then make use of existing functionality in
+  V4L (e.g. tuner.c) rather than rolling our own.
+
+*/
+
+static unsigned int i2c_scan = 0;
+module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
+                                            unsigned int detail,
+                                            char *buf,unsigned int maxlen);
+
+static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
+                         u8 i2c_addr,      /* I2C address we're talking to */
+                         u8 *data,         /* Data to write */
+                         u16 length)       /* Size of data to write */
+{
+       /* Return value - default 0 means success */
+       int ret;
+
+
+       if (!data) length = 0;
+       if (length > (sizeof(hdw->cmd_buffer) - 3)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Killing an I2C write to %u that is too large"
+                          " (desired=%u limit=%u)",
+                          i2c_addr,
+                          length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3));
+               return -ENOTSUPP;
+       }
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       /* Clear the command buffer (likely to be paranoia) */
+       memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
+
+       /* Set up command buffer for an I2C write */
+       hdw->cmd_buffer[0] = 0x08;      /* write prefix */
+       hdw->cmd_buffer[1] = i2c_addr;  /* i2c addr of chip */
+       hdw->cmd_buffer[2] = length;    /* length of what follows */
+       if (length) memcpy(hdw->cmd_buffer + 3, data, length);
+
+       /* Do the operation */
+       ret = pvr2_send_request(hdw,
+                               hdw->cmd_buffer,
+                               length + 3,
+                               hdw->cmd_buffer,
+                               1);
+       if (!ret) {
+               if (hdw->cmd_buffer[0] != 8) {
+                       ret = -EIO;
+                       if (hdw->cmd_buffer[0] != 7) {
+                               trace_i2c("unexpected status"
+                                         " from i2_write[%d]: %d",
+                                         i2c_addr,hdw->cmd_buffer[0]);
+                       }
+               }
+       }
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
+                        u8 i2c_addr,       /* I2C address we're talking to */
+                        u8 *data,          /* Data to write */
+                        u16 dlen,          /* Size of data to write */
+                        u8 *res,           /* Where to put data we read */
+                        u16 rlen)          /* Amount of data to read */
+{
+       /* Return value - default 0 means success */
+       int ret;
+
+
+       if (!data) dlen = 0;
+       if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Killing an I2C read to %u that has wlen too large"
+                          " (desired=%u limit=%u)",
+                          i2c_addr,
+                          dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
+               return -ENOTSUPP;
+       }
+       if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Killing an I2C read to %u that has rlen too large"
+                          " (desired=%u limit=%u)",
+                          i2c_addr,
+                          rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
+               return -ENOTSUPP;
+       }
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       /* Clear the command buffer (likely to be paranoia) */
+       memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
+
+       /* Set up command buffer for an I2C write followed by a read */
+       hdw->cmd_buffer[0] = 0x09;  /* read prefix */
+       hdw->cmd_buffer[1] = dlen;  /* arg length */
+       hdw->cmd_buffer[2] = rlen;  /* answer length. Device will send one
+                                      more byte (status). */
+       hdw->cmd_buffer[3] = i2c_addr;  /* i2c addr of chip */
+       if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen);
+
+       /* Do the operation */
+       ret = pvr2_send_request(hdw,
+                               hdw->cmd_buffer,
+                               4 + dlen,
+                               hdw->cmd_buffer,
+                               rlen + 1);
+       if (!ret) {
+               if (hdw->cmd_buffer[0] != 8) {
+                       ret = -EIO;
+                       if (hdw->cmd_buffer[0] != 7) {
+                               trace_i2c("unexpected status"
+                                         " from i2_read[%d]: %d",
+                                         i2c_addr,hdw->cmd_buffer[0]);
+                       }
+               }
+       }
+
+       /* Copy back the result */
+       if (res && rlen) {
+               if (ret) {
+                       /* Error, just blank out the return buffer */
+                       memset(res, 0, rlen);
+               } else {
+                       memcpy(res, hdw->cmd_buffer + 1, rlen);
+               }
+       }
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+/* This is the common low level entry point for doing I2C operations to the
+   hardware. */
+static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
+                            u8 i2c_addr,
+                            u8 *wdata,
+                            u16 wlen,
+                            u8 *rdata,
+                            u16 rlen)
+{
+       if (!rdata) rlen = 0;
+       if (!wdata) wlen = 0;
+       if (rlen || !wlen) {
+               return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+       } else {
+               return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen);
+       }
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+
+/* This is a special entry point that is entered if an I2C operation is
+   attempted to a wm8775 chip on model 24xxx hardware.  Autodetect of this
+   part doesn't work, but we know it is really there.  So let's look for
+   the autodetect attempt and just return success if we see that. */
+static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
+                          u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       if (!(rlen || wlen)) {
+               // This is a probe attempt.  Just let it succeed.
+               return 0;
+       }
+       return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+}
+
+/* This is a special entry point that is entered if an I2C operation is
+   attempted to a cx25840 chip on model 24xxx hardware.  This chip can
+   sometimes wedge itself.  Worse still, when this happens msp3400 can
+   falsely detect this part and then the system gets hosed up after msp3400
+   gets confused and dies.  What we want to do here is try to keep msp3400
+   away and also try to notice if the chip is wedged and send a warning to
+   the system log. */
+static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
+                           u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       int ret;
+       unsigned int subaddr;
+       u8 wbuf[2];
+       int state = hdw->i2c_cx25840_hack_state;
+
+       if (!(rlen || wlen)) {
+               // Probe attempt - always just succeed and don't bother the
+               // hardware (this helps to make the state machine further
+               // down somewhat easier).
+               return 0;
+       }
+
+       if (state == 3) {
+               return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+       }
+
+       /* We're looking for the exact pattern where the revision register
+          is being read.  The cx25840 module will always look at the
+          revision register first.  Any other pattern of access therefore
+          has to be a probe attempt from somebody else so we'll reject it.
+          Normally we could just let each client just probe the part
+          anyway, but when the cx25840 is wedged, msp3400 will get a false
+          positive and that just screws things up... */
+
+       if (wlen == 0) {
+               switch (state) {
+               case 1: subaddr = 0x0100; break;
+               case 2: subaddr = 0x0101; break;
+               default: goto fail;
+               }
+       } else if (wlen == 2) {
+               subaddr = (wdata[0] << 8) | wdata[1];
+               switch (subaddr) {
+               case 0x0100: state = 1; break;
+               case 0x0101: state = 2; break;
+               default: goto fail;
+               }
+       } else {
+               goto fail;
+       }
+       if (!rlen) goto success;
+       state = 0;
+       if (rlen != 1) goto fail;
+
+       /* If we get to here then we have a legitimate read for one of the
+          two revision bytes, so pass it through. */
+       wbuf[0] = subaddr >> 8;
+       wbuf[1] = subaddr;
+       ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen);
+
+       if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: Detected a wedged cx25840 chip;"
+                          " the device will not work.");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: Try power cycling the pvrusb2 device.");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: Disabling further access to the device"
+                          " to prevent other foul-ups.");
+               // This blocks all further communication with the part.
+               hdw->i2c_func[0x44] = NULL;
+               pvr2_hdw_render_useless(hdw);
+               goto fail;
+       }
+
+       /* Success! */
+       pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK.");
+       state = 3;
+
+ success:
+       hdw->i2c_cx25840_hack_state = state;
+       return 0;
+
+ fail:
+       hdw->i2c_cx25840_hack_state = state;
+       return -EIO;
+}
+
+#endif /* CONFIG_VIDEO_PVRUSB2_24XXX */
+
+/* This is a very, very limited I2C adapter implementation.  We can only
+   support what we actually know will work on the device... */
+static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
+                        struct i2c_msg msgs[],
+                        int num)
+{
+       int ret = -ENOTSUPP;
+       pvr2_i2c_func funcp = NULL;
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data);
+
+       if (!num) {
+               ret = -EINVAL;
+               goto done;
+       }
+       if ((msgs[0].flags & I2C_M_NOSTART)) {
+               trace_i2c("i2c refusing I2C_M_NOSTART");
+               goto done;
+       }
+       if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
+               funcp = hdw->i2c_func[msgs[0].addr];
+       }
+       if (!funcp) {
+               ret = -EIO;
+               goto done;
+       }
+
+       if (num == 1) {
+               if (msgs[0].flags & I2C_M_RD) {
+                       /* Simple read */
+                       u16 tcnt,bcnt,offs;
+                       if (!msgs[0].len) {
+                               /* Length == 0 read.  This is a probe. */
+                               if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) {
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               ret = 1;
+                               goto done;
+                       }
+                       /* If the read is short enough we'll do the whole
+                          thing atomically.  Otherwise we have no choice
+                          but to break apart the reads. */
+                       tcnt = msgs[0].len;
+                       offs = 0;
+                       while (tcnt) {
+                               bcnt = tcnt;
+                               if (bcnt > sizeof(hdw->cmd_buffer)-1) {
+                                       bcnt = sizeof(hdw->cmd_buffer)-1;
+                               }
+                               if (funcp(hdw,msgs[0].addr,NULL,0,
+                                         msgs[0].buf+offs,bcnt)) {
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               offs += bcnt;
+                               tcnt -= bcnt;
+                       }
+                       ret = 1;
+                       goto done;
+               } else {
+                       /* Simple write */
+                       ret = 1;
+                       if (funcp(hdw,msgs[0].addr,
+                                 msgs[0].buf,msgs[0].len,NULL,0)) {
+                               ret = -EIO;
+                       }
+                       goto done;
+               }
+       } else if (num == 2) {
+               if (msgs[0].addr != msgs[1].addr) {
+                       trace_i2c("i2c refusing 2 phase transfer with"
+                                 " conflicting target addresses");
+                       ret = -ENOTSUPP;
+                       goto done;
+               }
+               if ((!((msgs[0].flags & I2C_M_RD))) &&
+                   (msgs[1].flags & I2C_M_RD)) {
+                       u16 tcnt,bcnt,wcnt,offs;
+                       /* Write followed by atomic read.  If the read
+                          portion is short enough we'll do the whole thing
+                          atomically.  Otherwise we have no choice but to
+                          break apart the reads. */
+                       tcnt = msgs[1].len;
+                       wcnt = msgs[0].len;
+                       offs = 0;
+                       while (tcnt || wcnt) {
+                               bcnt = tcnt;
+                               if (bcnt > sizeof(hdw->cmd_buffer)-1) {
+                                       bcnt = sizeof(hdw->cmd_buffer)-1;
+                               }
+                               if (funcp(hdw,msgs[0].addr,
+                                         msgs[0].buf,wcnt,
+                                         msgs[1].buf+offs,bcnt)) {
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               offs += bcnt;
+                               tcnt -= bcnt;
+                               wcnt = 0;
+                       }
+                       ret = 2;
+                       goto done;
+               } else {
+                       trace_i2c("i2c refusing complex transfer"
+                                 " read0=%d read1=%d",
+                                 (msgs[0].flags & I2C_M_RD),
+                                 (msgs[1].flags & I2C_M_RD));
+               }
+       } else {
+               trace_i2c("i2c refusing %d phase transfer",num);
+       }
+
+ done:
+       if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) {
+               unsigned int idx,offs,cnt;
+               for (idx = 0; idx < num; idx++) {
+                       cnt = msgs[idx].len;
+                       printk(KERN_INFO
+                              "pvrusb2 i2c xfer %u/%u:"
+                              " addr=0x%x len=%d %s%s",
+                              idx+1,num,
+                              msgs[idx].addr,
+                              cnt,
+                              (msgs[idx].flags & I2C_M_RD ?
+                               "read" : "write"),
+                              (msgs[idx].flags & I2C_M_NOSTART ?
+                               " nostart" : ""));
+                       if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
+                               if (cnt > 8) cnt = 8;
+                               printk(" [");
+                               for (offs = 0; offs < (cnt>8?8:cnt); offs++) {
+                                       if (offs) printk(" ");
+                                       printk("%02x",msgs[idx].buf[offs]);
+                               }
+                               if (offs < cnt) printk(" ...");
+                               printk("]");
+                       }
+                       if (idx+1 == num) {
+                               printk(" result=%d",ret);
+                       }
+                       printk("\n");
+               }
+               if (!num) {
+                       printk(KERN_INFO
+                              "pvrusb2 i2c xfer null transfer result=%d\n",
+                              ret);
+               }
+       }
+       return ret;
+}
+
+static int pvr2_i2c_control(struct i2c_adapter *adapter,
+                           unsigned int cmd, unsigned long arg)
+{
+       return 0;
+}
+
+static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static int pvr2_i2c_core_singleton(struct i2c_client *cp,
+                                  unsigned int cmd,void *arg)
+{
+       int stat;
+       if (!cp) return -EINVAL;
+       if (!(cp->driver)) return -EINVAL;
+       if (!(cp->driver->command)) return -EINVAL;
+       if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN;
+       stat = cp->driver->command(cp,cmd,arg);
+       module_put(cp->driver->driver.owner);
+       return stat;
+}
+
+int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg)
+{
+       int stat;
+       if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
+               char buf[100];
+               unsigned int cnt;
+               cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
+                                              buf,sizeof(buf));
+               pvr2_trace(PVR2_TRACE_I2C_CMD,
+                          "i2c COMMAND (code=%u 0x%x) to %.*s",
+                          cmd,cmd,cnt,buf);
+       }
+       stat = pvr2_i2c_core_singleton(cp->client,cmd,arg);
+       if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
+               char buf[100];
+               unsigned int cnt;
+               cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
+                                              buf,sizeof(buf));
+               pvr2_trace(PVR2_TRACE_I2C_CMD,
+                          "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat);
+       }
+       return stat;
+}
+
+int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
+{
+       struct list_head *item,*nc;
+       struct pvr2_i2c_client *cp;
+       int stat = -EINVAL;
+
+       if (!hdw) return stat;
+
+       mutex_lock(&hdw->i2c_list_lock);
+       list_for_each_safe(item,nc,&hdw->i2c_clients) {
+               cp = list_entry(item,struct pvr2_i2c_client,list);
+               if (!cp->recv_enable) continue;
+               mutex_unlock(&hdw->i2c_list_lock);
+               stat = pvr2_i2c_client_cmd(cp,cmd,arg);
+               mutex_lock(&hdw->i2c_list_lock);
+       }
+       mutex_unlock(&hdw->i2c_list_lock);
+       return stat;
+}
+
+
+static int handler_check(struct pvr2_i2c_client *cp)
+{
+       struct pvr2_i2c_handler *hp = cp->handler;
+       if (!hp) return 0;
+       if (!hp->func_table->check) return 0;
+       return hp->func_table->check(hp->func_data) != 0;
+}
+
+#define BUFSIZE 500
+
+void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
+{
+       unsigned long msk;
+       unsigned int idx;
+       struct list_head *item,*nc;
+       struct pvr2_i2c_client *cp;
+
+       if (!hdw->i2c_linked) return;
+       if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) {
+               return;
+       }
+       mutex_lock(&hdw->i2c_list_lock); do {
+               pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN");
+               if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) {
+                       /* One or more I2C clients have attached since we
+                          last synced.  So scan the list and identify the
+                          new clients. */
+                       char *buf;
+                       unsigned int cnt;
+                       unsigned long amask = 0;
+                       buf = kmalloc(BUFSIZE,GFP_KERNEL);
+                       pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT");
+                       hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT;
+                       list_for_each(item,&hdw->i2c_clients) {
+                               cp = list_entry(item,struct pvr2_i2c_client,
+                                               list);
+                               if (!cp->detected_flag) {
+                                       cp->ctl_mask = 0;
+                                       pvr2_i2c_probe(hdw,cp);
+                                       cp->detected_flag = !0;
+                                       msk = cp->ctl_mask;
+                                       cnt = 0;
+                                       if (buf) {
+                                               cnt = pvr2_i2c_client_describe(
+                                                       cp,
+                                                       PVR2_I2C_DETAIL_ALL,
+                                                       buf,BUFSIZE);
+                                       }
+                                       trace_i2c("Probed: %.*s",cnt,buf);
+                                       if (handler_check(cp)) {
+                                               hdw->i2c_pend_types |=
+                                                       PVR2_I2C_PEND_CLIENT;
+                                       }
+                                       cp->pend_mask = msk;
+                                       hdw->i2c_pend_mask |= msk;
+                                       hdw->i2c_pend_types |=
+                                               PVR2_I2C_PEND_REFRESH;
+                               }
+                               amask |= cp->ctl_mask;
+                       }
+                       hdw->i2c_active_mask = amask;
+                       if (buf) kfree(buf);
+               }
+               if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) {
+                       /* Need to do one or more global updates.  Arrange
+                          for this to happen. */
+                       unsigned long m2;
+                       pvr2_trace(PVR2_TRACE_I2C_CORE,
+                                  "i2c: PEND_STALE (0x%lx)",
+                                  hdw->i2c_stale_mask);
+                       hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE;
+                       list_for_each(item,&hdw->i2c_clients) {
+                               cp = list_entry(item,struct pvr2_i2c_client,
+                                               list);
+                               m2 = hdw->i2c_stale_mask;
+                               m2 &= cp->ctl_mask;
+                               m2 &= ~cp->pend_mask;
+                               if (m2) {
+                                       pvr2_trace(PVR2_TRACE_I2C_CORE,
+                                                  "i2c: cp=%p setting 0x%lx",
+                                                  cp,m2);
+                                       cp->pend_mask |= m2;
+                               }
+                       }
+                       hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
+                       hdw->i2c_stale_mask = 0;
+                       hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH;
+               }
+               if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) {
+                       /* One or more client handlers are asking for an
+                          update.  Run through the list of known clients
+                          and update each one. */
+                       pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT");
+                       hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT;
+                       list_for_each_safe(item,nc,&hdw->i2c_clients) {
+                               cp = list_entry(item,struct pvr2_i2c_client,
+                                               list);
+                               if (!cp->handler) continue;
+                               if (!cp->handler->func_table->update) continue;
+                               pvr2_trace(PVR2_TRACE_I2C_CORE,
+                                          "i2c: cp=%p update",cp);
+                               mutex_unlock(&hdw->i2c_list_lock);
+                               cp->handler->func_table->update(
+                                       cp->handler->func_data);
+                               mutex_lock(&hdw->i2c_list_lock);
+                               /* If client's update function set some
+                                  additional pending bits, account for that
+                                  here. */
+                               if (cp->pend_mask & ~hdw->i2c_pend_mask) {
+                                       hdw->i2c_pend_mask |= cp->pend_mask;
+                                       hdw->i2c_pend_types |=
+                                               PVR2_I2C_PEND_REFRESH;
+                               }
+                       }
+               }
+               if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) {
+                       const struct pvr2_i2c_op *opf;
+                       unsigned long pm;
+                       /* Some actual updates are pending.  Walk through
+                          each update type and perform it. */
+                       pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH"
+                                  " (0x%lx)",hdw->i2c_pend_mask);
+                       hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH;
+                       pm = hdw->i2c_pend_mask;
+                       hdw->i2c_pend_mask = 0;
+                       for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
+                               if (!(pm & msk)) continue;
+                               pm &= ~msk;
+                               list_for_each(item,&hdw->i2c_clients) {
+                                       cp = list_entry(item,
+                                                       struct pvr2_i2c_client,
+                                                       list);
+                                       if (cp->pend_mask & msk) {
+                                               cp->pend_mask &= ~msk;
+                                               cp->recv_enable = !0;
+                                       } else {
+                                               cp->recv_enable = 0;
+                                       }
+                               }
+                               opf = pvr2_i2c_get_op(idx);
+                               if (!opf) continue;
+                               mutex_unlock(&hdw->i2c_list_lock);
+                               opf->update(hdw);
+                               mutex_lock(&hdw->i2c_list_lock);
+                       }
+               }
+               pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END");
+       } while (0); mutex_unlock(&hdw->i2c_list_lock);
+}
+
+int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
+{
+       unsigned long msk,sm,pm;
+       unsigned int idx;
+       const struct pvr2_i2c_op *opf;
+       struct list_head *item;
+       struct pvr2_i2c_client *cp;
+       unsigned int pt = 0;
+
+       pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN");
+
+       pm = hdw->i2c_active_mask;
+       sm = 0;
+       for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
+               if (!(msk & pm)) continue;
+               pm &= ~msk;
+               opf = pvr2_i2c_get_op(idx);
+               if (!opf) continue;
+               if (opf->check(hdw)) {
+                       sm |= msk;
+               }
+       }
+       if (sm) pt |= PVR2_I2C_PEND_STALE;
+
+       list_for_each(item,&hdw->i2c_clients) {
+               cp = list_entry(item,struct pvr2_i2c_client,list);
+               if (!handler_check(cp)) continue;
+               pt |= PVR2_I2C_PEND_CLIENT;
+       }
+
+       if (pt) {
+               mutex_lock(&hdw->i2c_list_lock); do {
+                       hdw->i2c_pend_types |= pt;
+                       hdw->i2c_stale_mask |= sm;
+                       hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
+               } while (0); mutex_unlock(&hdw->i2c_list_lock);
+       }
+
+       pvr2_trace(PVR2_TRACE_I2C_CORE,
+                  "i2c: types=0x%x stale=0x%lx pend=0x%lx",
+                  hdw->i2c_pend_types,
+                  hdw->i2c_stale_mask,
+                  hdw->i2c_pend_mask);
+       pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END");
+
+       return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0;
+}
+
+static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
+                                            unsigned int detail,
+                                            char *buf,unsigned int maxlen)
+{
+       unsigned int ccnt,bcnt;
+       int spcfl = 0;
+       const struct pvr2_i2c_op *opf;
+
+       ccnt = 0;
+       if (detail & PVR2_I2C_DETAIL_DEBUG) {
+               bcnt = scnprintf(buf,maxlen,
+                                "ctxt=%p ctl_mask=0x%lx",
+                                cp,cp->ctl_mask);
+               ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+               spcfl = !0;
+       }
+       bcnt = scnprintf(buf,maxlen,
+                        "%s%s @ 0x%x",
+                        (spcfl ? " " : ""),
+                        cp->client->name,
+                        cp->client->addr);
+       ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+       if ((detail & PVR2_I2C_DETAIL_HANDLER) &&
+           cp->handler && cp->handler->func_table->describe) {
+               bcnt = scnprintf(buf,maxlen," (");
+               ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+               bcnt = cp->handler->func_table->describe(
+                       cp->handler->func_data,buf,maxlen);
+               ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+               bcnt = scnprintf(buf,maxlen,")");
+               ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+       }
+       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;
+               spcfl = 0;
+               for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {
+                       if (!(cp->ctl_mask & msk)) continue;
+                       opf = pvr2_i2c_get_op(idx);
+                       if (opf) {
+                               bcnt = scnprintf(buf,maxlen,"%s%s",
+                                                spcfl ? " " : "",
+                                                opf->name);
+                               ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+                               spcfl = !0;
+                       } else {
+                               sm |= msk;
+                       }
+               }
+               if (sm) {
+                       bcnt = scnprintf(buf,maxlen,"%s%lx",
+                                        idx != 0 ? " " : "",sm);
+                       ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+               }
+               bcnt = scnprintf(buf,maxlen,"]");
+               ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+       }
+       return ccnt;
+}
+
+unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw,
+                            char *buf,unsigned int maxlen)
+{
+       unsigned int ccnt,bcnt;
+       struct list_head *item;
+       struct pvr2_i2c_client *cp;
+       ccnt = 0;
+       mutex_lock(&hdw->i2c_list_lock); do {
+               list_for_each(item,&hdw->i2c_clients) {
+                       cp = list_entry(item,struct pvr2_i2c_client,list);
+                       bcnt = pvr2_i2c_client_describe(
+                               cp,
+                               (PVR2_I2C_DETAIL_HANDLER|
+                                PVR2_I2C_DETAIL_CTLMASK),
+                               buf,maxlen);
+                       ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+                       bcnt = scnprintf(buf,maxlen,"\n");
+                       ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+               }
+       } while (0); mutex_unlock(&hdw->i2c_list_lock);
+       return ccnt;
+}
+
+static int pvr2_i2c_attach_inform(struct i2c_client *client)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
+       struct pvr2_i2c_client *cp;
+       int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
+       cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+       trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
+                 client->name,
+                 client->addr,cp);
+       if (!cp) return -ENOMEM;
+       memset(cp,0,sizeof(*cp));
+       INIT_LIST_HEAD(&cp->list);
+       cp->client = client;
+       mutex_lock(&hdw->i2c_list_lock); do {
+               list_add_tail(&cp->list,&hdw->i2c_clients);
+               hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
+       } while (0); mutex_unlock(&hdw->i2c_list_lock);
+       if (fl) pvr2_hdw_poll_trigger_unlocked(hdw);
+       return 0;
+}
+
+static int pvr2_i2c_detach_inform(struct i2c_client *client)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
+       struct pvr2_i2c_client *cp;
+       struct list_head *item,*nc;
+       unsigned long amask = 0;
+       int foundfl = 0;
+       mutex_lock(&hdw->i2c_list_lock); do {
+               list_for_each_safe(item,nc,&hdw->i2c_clients) {
+                       cp = list_entry(item,struct pvr2_i2c_client,list);
+                       if (cp->client == client) {
+                               trace_i2c("pvr2_i2c_detach"
+                                         " [client=%s @ 0x%x ctxt=%p]",
+                                         client->name,
+                                         client->addr,cp);
+                               if (cp->handler &&
+                                   cp->handler->func_table->detach) {
+                                       cp->handler->func_table->detach(
+                                               cp->handler->func_data);
+                               }
+                               list_del(&cp->list);
+                               kfree(cp);
+                               foundfl = !0;
+                               continue;
+                       }
+                       amask |= cp->ctl_mask;
+               }
+               hdw->i2c_active_mask = amask;
+       } while (0); mutex_unlock(&hdw->i2c_list_lock);
+       if (!foundfl) {
+               trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
+                         client->name,
+                         client->addr);
+       }
+       return 0;
+}
+
+static struct i2c_algorithm pvr2_i2c_algo_template = {
+       .master_xfer   = pvr2_i2c_xfer,
+       .algo_control  = pvr2_i2c_control,
+       .functionality = pvr2_i2c_functionality,
+};
+
+static struct i2c_adapter pvr2_i2c_adap_template = {
+       .owner         = THIS_MODULE,
+       .class     = I2C_CLASS_TV_ANALOG,
+       .id            = I2C_HW_B_BT848,
+       .client_register = pvr2_i2c_attach_inform,
+       .client_unregister = pvr2_i2c_detach_inform,
+};
+
+static void do_i2c_scan(struct pvr2_hdw *hdw)
+{
+       struct i2c_msg msg[1];
+       int i,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);
+       for (i = 0; i < 128; i++) {
+               msg[0].addr = i;
+               rc = i2c_transfer(&hdw->i2c_adap,msg,
+                                 sizeof(msg)/sizeof(msg[0]));
+               if (rc != 1) continue;
+               printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i);
+       }
+       printk("%s: i2c scan done.\n",hdw->name);
+}
+
+void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
+{
+       unsigned int idx;
+
+       // The default action for all possible I2C addresses is just to do
+       // the transfer normally.
+       for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
+               hdw->i2c_func[idx] = pvr2_i2c_basic_op;
+       }
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+       // If however we're dealing with new hardware, insert some hacks in
+       // the I2C transfer stack to let things work better.
+       if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+               hdw->i2c_func[0x1b] = i2c_hack_wm8775;
+               hdw->i2c_func[0x44] = i2c_hack_cx25840;
+       }
+#endif
+
+       // Configure the adapter and set up everything else related to it.
+       memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
+       memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
+       strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
+       hdw->i2c_adap.algo = &hdw->i2c_algo;
+       hdw->i2c_adap.algo_data = hdw;
+       hdw->i2c_pend_mask = 0;
+       hdw->i2c_stale_mask = 0;
+       hdw->i2c_active_mask = 0;
+       INIT_LIST_HEAD(&hdw->i2c_clients);
+       mutex_init(&hdw->i2c_list_lock);
+       hdw->i2c_linked = !0;
+       i2c_add_adapter(&hdw->i2c_adap);
+       if (i2c_scan) do_i2c_scan(hdw);
+}
+
+void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
+{
+       if (hdw->i2c_linked) {
+               i2c_del_adapter(&hdw->i2c_adap);
+               hdw->i2c_linked = 0;
+       }
+}
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
new file mode 100644 (file)
index 0000000..6d7e252
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_I2C_CORE_H
+#define __PVRUSB2_I2C_CORE_H
+
+#include <linux/list.h>
+#include <linux/i2c.h>
+
+struct pvr2_hdw;
+struct pvr2_i2c_client;
+struct pvr2_i2c_handler;
+struct pvr2_i2c_handler_functions;
+struct pvr2_i2c_op;
+struct pvr2_i2c_op_functions;
+
+struct pvr2_i2c_client {
+       struct i2c_client *client;
+       struct pvr2_i2c_handler *handler;
+       struct list_head list;
+       int detected_flag;
+       int recv_enable;
+       unsigned long pend_mask;
+       unsigned long ctl_mask;
+};
+
+struct pvr2_i2c_handler {
+       void *func_data;
+       const struct pvr2_i2c_handler_functions *func_table;
+};
+
+struct pvr2_i2c_handler_functions {
+       void (*detach)(void *);
+       int (*check)(void *);
+       void (*update)(void *);
+       unsigned int (*describe)(void *,char *,unsigned int);
+};
+
+struct pvr2_i2c_op {
+       int (*check)(struct pvr2_hdw *);
+       void (*update)(struct pvr2_hdw *);
+       const char *name;
+};
+
+void pvr2_i2c_core_init(struct pvr2_hdw *);
+void pvr2_i2c_core_done(struct pvr2_hdw *);
+
+int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg);
+int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg);
+
+int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
+void pvr2_i2c_core_sync(struct pvr2_hdw *);
+unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
+#define PVR2_I2C_DETAIL_DEBUG   0x0001
+#define PVR2_I2C_DETAIL_HANDLER 0x0002
+#define PVR2_I2C_DETAIL_CTLMASK 0x0004
+#define PVR2_I2C_DETAIL_ALL (\
+       PVR2_I2C_DETAIL_DEBUG |\
+       PVR2_I2C_DETAIL_HANDLER |\
+       PVR2_I2C_DETAIL_CTLMASK)
+
+void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
+const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
+
+#endif /* __PVRUSB2_I2C_CORE_H */
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
new file mode 100644 (file)
index 0000000..1e39376
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-io.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
+
+#define BUFFER_SIG 0x47653271
+
+// #define SANITY_CHECK_BUFFERS
+
+
+#ifdef SANITY_CHECK_BUFFERS
+#define BUFFER_CHECK(bp) do { \
+       if ((bp)->signature != BUFFER_SIG) { \
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
+               "Buffer %p is bad at %s:%d", \
+               (bp),__FILE__,__LINE__); \
+               pvr2_buffer_describe(bp,"BadSig"); \
+               BUG(); \
+       } \
+} while (0)
+#else
+#define BUFFER_CHECK(bp) do {} while(0)
+#endif
+
+struct pvr2_stream {
+       /* Buffers queued for reading */
+       struct list_head queued_list;
+       unsigned int q_count;
+       unsigned int q_bcount;
+       /* Buffers with retrieved data */
+       struct list_head ready_list;
+       unsigned int r_count;
+       unsigned int r_bcount;
+       /* Buffers available for use */
+       struct list_head idle_list;
+       unsigned int i_count;
+       unsigned int i_bcount;
+       /* Pointers to all buffers */
+       struct pvr2_buffer **buffers;
+       /* Array size of buffers */
+       unsigned int buffer_slot_count;
+       /* Total buffers actually in circulation */
+       unsigned int buffer_total_count;
+       /* Designed number of buffers to be in circulation */
+       unsigned int buffer_target_count;
+       /* Executed when ready list become non-empty */
+       pvr2_stream_callback callback_func;
+       void *callback_data;
+       /* Context for transfer endpoint */
+       struct usb_device *dev;
+       int endpoint;
+       /* Overhead for mutex enforcement */
+       spinlock_t list_lock;
+       struct mutex mutex;
+       /* Tracking state for tolerating errors */
+       unsigned int fail_count;
+       unsigned int fail_tolerance;
+};
+
+struct pvr2_buffer {
+       int id;
+       int signature;
+       enum pvr2_buffer_state state;
+       void *ptr;               /* Pointer to storage area */
+       unsigned int max_count;  /* Size of storage area */
+       unsigned int used_count; /* Amount of valid data in storage area */
+       int status;              /* Transfer result status */
+       struct pvr2_stream *stream;
+       struct list_head list_overhead;
+       struct urb *purb;
+};
+
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
+{
+       switch (st) {
+       case pvr2_buffer_state_none: return "none";
+       case pvr2_buffer_state_idle: return "idle";
+       case pvr2_buffer_state_queued: return "queued";
+       case pvr2_buffer_state_ready: return "ready";
+       }
+       return "unknown";
+}
+
+#ifdef SANITY_CHECK_BUFFERS
+static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
+{
+       pvr2_trace(PVR2_TRACE_INFO,
+                  "buffer%s%s %p state=%s id=%d status=%d"
+                  " stream=%p purb=%p sig=0x%x",
+                  (msg ? " " : ""),
+                  (msg ? msg : ""),
+                  bp,
+                  (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
+                  (bp ? bp->id : 0),
+                  (bp ? bp->status : 0),
+                  (bp ? bp->stream : NULL),
+                  (bp ? bp->purb : NULL),
+                  (bp ? bp->signature : 0));
+}
+#endif  /*  SANITY_CHECK_BUFFERS  */
+
+static void pvr2_buffer_remove(struct pvr2_buffer *bp)
+{
+       unsigned int *cnt;
+       unsigned int *bcnt;
+       unsigned int ccnt;
+       struct pvr2_stream *sp = bp->stream;
+       switch (bp->state) {
+       case pvr2_buffer_state_idle:
+               cnt = &sp->i_count;
+               bcnt = &sp->i_bcount;
+               ccnt = bp->max_count;
+               break;
+       case pvr2_buffer_state_queued:
+               cnt = &sp->q_count;
+               bcnt = &sp->q_bcount;
+               ccnt = bp->max_count;
+               break;
+       case pvr2_buffer_state_ready:
+               cnt = &sp->r_count;
+               bcnt = &sp->r_bcount;
+               ccnt = bp->used_count;
+               break;
+       default:
+               return;
+       }
+       list_del_init(&bp->list_overhead);
+       (*cnt)--;
+       (*bcnt) -= ccnt;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s dec cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
+       bp->state = pvr2_buffer_state_none;
+}
+
+static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
+{
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_none));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       pvr2_buffer_remove(bp);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
+{
+       int fl;
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_ready));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       fl = (sp->r_count == 0);
+       pvr2_buffer_remove(bp);
+       list_add_tail(&bp->list_overhead,&sp->ready_list);
+       bp->state = pvr2_buffer_state_ready;
+       (sp->r_count)++;
+       sp->r_bcount += bp->used_count;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s inc cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),
+                  sp->r_bcount,sp->r_count);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       return fl;
+}
+
+static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
+{
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_idle));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       pvr2_buffer_remove(bp);
+       list_add_tail(&bp->list_overhead,&sp->idle_list);
+       bp->state = pvr2_buffer_state_idle;
+       (sp->i_count)++;
+       sp->i_bcount += bp->max_count;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s inc cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),
+                  sp->i_bcount,sp->i_count);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
+{
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_queued));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       pvr2_buffer_remove(bp);
+       list_add_tail(&bp->list_overhead,&sp->queued_list);
+       bp->state = pvr2_buffer_state_queued;
+       (sp->q_count)++;
+       sp->q_bcount += bp->max_count;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s inc cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),
+                  sp->q_bcount,sp->q_count);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
+{
+       if (bp->state == pvr2_buffer_state_queued) {
+               usb_kill_urb(bp->purb);
+       }
+}
+
+static int pvr2_buffer_init(struct pvr2_buffer *bp,
+                           struct pvr2_stream *sp,
+                           unsigned int id)
+{
+       memset(bp,0,sizeof(*bp));
+       bp->signature = BUFFER_SIG;
+       bp->id = id;
+       pvr2_trace(PVR2_TRACE_BUF_POOL,
+                  "/*---TRACE_FLOW---*/ bufferInit     %p stream=%p",bp,sp);
+       bp->stream = sp;
+       bp->state = pvr2_buffer_state_none;
+       INIT_LIST_HEAD(&bp->list_overhead);
+       bp->purb = usb_alloc_urb(0,GFP_KERNEL);
+       if (! bp->purb) return -ENOMEM;
+#ifdef SANITY_CHECK_BUFFERS
+       pvr2_buffer_describe(bp,"create");
+#endif
+       return 0;
+}
+
+static void pvr2_buffer_done(struct pvr2_buffer *bp)
+{
+#ifdef SANITY_CHECK_BUFFERS
+       pvr2_buffer_describe(bp,"delete");
+#endif
+       pvr2_buffer_wipe(bp);
+       pvr2_buffer_set_none(bp);
+       bp->signature = 0;
+       bp->stream = NULL;
+       if (bp->purb) usb_free_urb(bp->purb);
+       pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
+                  " bufferDone     %p",bp);
+}
+
+static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
+{
+       int ret;
+       unsigned int scnt;
+
+       /* Allocate buffers pointer array in multiples of 32 entries */
+       if (cnt == sp->buffer_total_count) return 0;
+
+       pvr2_trace(PVR2_TRACE_BUF_POOL,
+                  "/*---TRACE_FLOW---*/ poolResize    "
+                  " stream=%p cur=%d adj=%+d",
+                  sp,
+                  sp->buffer_total_count,
+                  cnt-sp->buffer_total_count);
+
+       scnt = cnt & ~0x1f;
+       if (cnt > scnt) scnt += 0x20;
+
+       if (cnt > sp->buffer_total_count) {
+               if (scnt > sp->buffer_slot_count) {
+                       struct pvr2_buffer **nb;
+                       nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
+                       if (!nb) return -ENOMEM;
+                       if (sp->buffer_slot_count) {
+                               memcpy(nb,sp->buffers,
+                                      sp->buffer_slot_count * sizeof(*nb));
+                               kfree(sp->buffers);
+                       }
+                       sp->buffers = nb;
+                       sp->buffer_slot_count = scnt;
+               }
+               while (sp->buffer_total_count < cnt) {
+                       struct pvr2_buffer *bp;
+                       bp = kmalloc(sizeof(*bp),GFP_KERNEL);
+                       if (!bp) return -ENOMEM;
+                       ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count);
+                       if (ret) {
+                               kfree(bp);
+                               return -ENOMEM;
+                       }
+                       sp->buffers[sp->buffer_total_count] = bp;
+                       (sp->buffer_total_count)++;
+                       pvr2_buffer_set_idle(bp);
+               }
+       } else {
+               while (sp->buffer_total_count > cnt) {
+                       struct pvr2_buffer *bp;
+                       bp = sp->buffers[sp->buffer_total_count - 1];
+                       /* Paranoia */
+                       sp->buffers[sp->buffer_total_count - 1] = NULL;
+                       (sp->buffer_total_count)--;
+                       pvr2_buffer_done(bp);
+                       kfree(bp);
+               }
+               if (scnt < sp->buffer_slot_count) {
+                       struct pvr2_buffer **nb = NULL;
+                       if (scnt) {
+                               nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
+                               if (!nb) return -ENOMEM;
+                               memcpy(nb,sp->buffers,scnt * sizeof(*nb));
+                       }
+                       kfree(sp->buffers);
+                       sp->buffers = nb;
+                       sp->buffer_slot_count = scnt;
+               }
+       }
+       return 0;
+}
+
+static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
+{
+       struct pvr2_buffer *bp;
+       unsigned int cnt;
+
+       if (sp->buffer_total_count == sp->buffer_target_count) return 0;
+
+       pvr2_trace(PVR2_TRACE_BUF_POOL,
+                  "/*---TRACE_FLOW---*/"
+                  " poolCheck      stream=%p cur=%d tgt=%d",
+                  sp,sp->buffer_total_count,sp->buffer_target_count);
+
+       if (sp->buffer_total_count < sp->buffer_target_count) {
+               return pvr2_stream_buffer_count(sp,sp->buffer_target_count);
+       }
+
+       cnt = 0;
+       while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
+               bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
+               if (bp->state != pvr2_buffer_state_idle) break;
+               cnt++;
+       }
+       if (cnt) {
+               pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);
+       }
+
+       return 0;
+}
+
+static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
+{
+       struct list_head *lp;
+       struct pvr2_buffer *bp1;
+       while ((lp = sp->queued_list.next) != &sp->queued_list) {
+               bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);
+               pvr2_buffer_wipe(bp1);
+               /* At this point, we should be guaranteed that no
+                  completion callback may happen on this buffer.  But it's
+                  possible that it might have completed after we noticed
+                  it but before we wiped it.  So double check its status
+                  here first. */
+               if (bp1->state != pvr2_buffer_state_queued) continue;
+               pvr2_buffer_set_idle(bp1);
+       }
+       if (sp->buffer_total_count != sp->buffer_target_count) {
+               pvr2_stream_achieve_buffer_count(sp);
+       }
+}
+
+static void pvr2_stream_init(struct pvr2_stream *sp)
+{
+       spin_lock_init(&sp->list_lock);
+       mutex_init(&sp->mutex);
+       INIT_LIST_HEAD(&sp->queued_list);
+       INIT_LIST_HEAD(&sp->ready_list);
+       INIT_LIST_HEAD(&sp->idle_list);
+}
+
+static void pvr2_stream_done(struct pvr2_stream *sp)
+{
+       mutex_lock(&sp->mutex); do {
+               pvr2_stream_internal_flush(sp);
+               pvr2_stream_buffer_count(sp,0);
+       } while (0); mutex_unlock(&sp->mutex);
+}
+
+static void buffer_complete(struct urb *urb, struct pt_regs *regs)
+{
+       struct pvr2_buffer *bp = urb->context;
+       struct pvr2_stream *sp;
+       unsigned long irq_flags;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       bp->used_count = 0;
+       bp->status = 0;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
+                  bp,urb->status,urb->actual_length);
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       if ((!(urb->status)) ||
+           (urb->status == -ENOENT) ||
+           (urb->status == -ECONNRESET) ||
+           (urb->status == -ESHUTDOWN)) {
+               bp->used_count = urb->actual_length;
+               if (sp->fail_count) {
+                       pvr2_trace(PVR2_TRACE_TOLERANCE,
+                                  "stream %p transfer ok"
+                                  " - fail count reset",sp);
+                       sp->fail_count = 0;
+               }
+       } else if (sp->fail_count < sp->fail_tolerance) {
+               // We can tolerate this error, because we're below the
+               // threshold...
+               (sp->fail_count)++;
+               pvr2_trace(PVR2_TRACE_TOLERANCE,
+                          "stream %p ignoring error %d"
+                          " - fail count increased to %u",
+                          sp,urb->status,sp->fail_count);
+       } else {
+               bp->status = urb->status;
+       }
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       pvr2_buffer_set_ready(bp);
+       if (sp && sp->callback_func) {
+               sp->callback_func(sp->callback_data);
+       }
+}
+
+struct pvr2_stream *pvr2_stream_create(void)
+{
+       struct pvr2_stream *sp;
+       sp = kmalloc(sizeof(*sp),GFP_KERNEL);
+       if (!sp) return sp;
+       memset(sp,0,sizeof(*sp));
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
+       pvr2_stream_init(sp);
+       return sp;
+}
+
+void pvr2_stream_destroy(struct pvr2_stream *sp)
+{
+       if (!sp) return;
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);
+       pvr2_stream_done(sp);
+       kfree(sp);
+}
+
+void pvr2_stream_setup(struct pvr2_stream *sp,
+                      struct usb_device *dev,
+                      int endpoint,
+                      unsigned int tolerance)
+{
+       mutex_lock(&sp->mutex); do {
+               pvr2_stream_internal_flush(sp);
+               sp->dev = dev;
+               sp->endpoint = endpoint;
+               sp->fail_tolerance = tolerance;
+       } while(0); mutex_unlock(&sp->mutex);
+}
+
+void pvr2_stream_set_callback(struct pvr2_stream *sp,
+                             pvr2_stream_callback func,
+                             void *data)
+{
+       unsigned long irq_flags;
+       mutex_lock(&sp->mutex); do {
+               spin_lock_irqsave(&sp->list_lock,irq_flags);
+               sp->callback_data = data;
+               sp->callback_func = func;
+               spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       } while(0); mutex_unlock(&sp->mutex);
+}
+
+/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+{
+       return sp->buffer_target_count;
+}
+
+int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
+{
+       int ret;
+       if (sp->buffer_target_count == cnt) return 0;
+       mutex_lock(&sp->mutex); do {
+               sp->buffer_target_count = cnt;
+               ret = pvr2_stream_achieve_buffer_count(sp);
+       } while(0); mutex_unlock(&sp->mutex);
+       return ret;
+}
+
+struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
+{
+       struct list_head *lp = sp->idle_list.next;
+       if (lp == &sp->idle_list) return NULL;
+       return list_entry(lp,struct pvr2_buffer,list_overhead);
+}
+
+struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
+{
+       struct list_head *lp = sp->ready_list.next;
+       if (lp == &sp->ready_list) return NULL;
+       return list_entry(lp,struct pvr2_buffer,list_overhead);
+}
+
+struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
+{
+       if (id < 0) return NULL;
+       if (id >= sp->buffer_total_count) return NULL;
+       return sp->buffers[id];
+}
+
+int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
+{
+       return sp->r_count;
+}
+
+void pvr2_stream_kill(struct pvr2_stream *sp)
+{
+       struct pvr2_buffer *bp;
+       mutex_lock(&sp->mutex); do {
+               pvr2_stream_internal_flush(sp);
+               while ((bp = pvr2_stream_get_ready_buffer(sp)) != 0) {
+                       pvr2_buffer_set_idle(bp);
+               }
+               if (sp->buffer_total_count != sp->buffer_target_count) {
+                       pvr2_stream_achieve_buffer_count(sp);
+               }
+       } while(0); mutex_unlock(&sp->mutex);
+}
+
+int pvr2_buffer_queue(struct pvr2_buffer *bp)
+{
+#undef SEED_BUFFER
+#ifdef SEED_BUFFER
+       unsigned int idx;
+       unsigned int val;
+#endif
+       int ret = 0;
+       struct pvr2_stream *sp;
+       if (!bp) return -EINVAL;
+       sp = bp->stream;
+       mutex_lock(&sp->mutex); do {
+               pvr2_buffer_wipe(bp);
+               if (!sp->dev) {
+                       ret = -EIO;
+                       break;
+               }
+               pvr2_buffer_set_queued(bp);
+#ifdef SEED_BUFFER
+               for (idx = 0; idx < (bp->max_count) / 4; idx++) {
+                       val = bp->id << 24;
+                       val |= idx;
+                       ((unsigned int *)(bp->ptr))[idx] = val;
+               }
+#endif
+               bp->status = -EINPROGRESS;
+               usb_fill_bulk_urb(bp->purb,      // struct urb *urb
+                                 sp->dev,       // struct usb_device *dev
+                                 // endpoint (below)
+                                 usb_rcvbulkpipe(sp->dev,sp->endpoint),
+                                 bp->ptr,       // void *transfer_buffer
+                                 bp->max_count, // int buffer_length
+                                 buffer_complete,
+                                 bp);
+               usb_submit_urb(bp->purb,GFP_KERNEL);
+       } while(0); mutex_unlock(&sp->mutex);
+       return ret;
+}
+
+int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
+{
+       int ret = 0;
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       if (!bp) return -EINVAL;
+       sp = bp->stream;
+       mutex_lock(&sp->mutex); do {
+               spin_lock_irqsave(&sp->list_lock,irq_flags);
+               if (bp->state != pvr2_buffer_state_idle) {
+                       ret = -EPERM;
+               } else {
+                       bp->ptr = ptr;
+                       bp->stream->i_bcount -= bp->max_count;
+                       bp->max_count = cnt;
+                       bp->stream->i_bcount += bp->max_count;
+                       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                                  "/*---TRACE_FLOW---*/ bufferPool    "
+                                  " %8s cap cap=%07d cnt=%02d",
+                                  pvr2_buffer_state_decode(
+                                          pvr2_buffer_state_idle),
+                                  bp->stream->i_bcount,bp->stream->i_count);
+               }
+               spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       } while(0); mutex_unlock(&sp->mutex);
+       return ret;
+}
+
+unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
+{
+       return bp->used_count;
+}
+
+int pvr2_buffer_get_status(struct pvr2_buffer *bp)
+{
+       return bp->status;
+}
+
+int pvr2_buffer_get_id(struct pvr2_buffer *bp)
+{
+       return bp->id;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
new file mode 100644 (file)
index 0000000..93279cc
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_IO_H
+#define __PVRUSB2_IO_H
+
+#include <linux/usb.h>
+#include <linux/list.h>
+
+typedef void (*pvr2_stream_callback)(void *);
+
+enum pvr2_buffer_state {
+       pvr2_buffer_state_none = 0,   // Not on any list
+       pvr2_buffer_state_idle = 1,   // Buffer is ready to be used again
+       pvr2_buffer_state_queued = 2, // Buffer has been queued for filling
+       pvr2_buffer_state_ready = 3,  // Buffer has data available
+};
+
+struct pvr2_stream;
+struct pvr2_buffer;
+
+/* Initialize / tear down stream structure */
+struct pvr2_stream *pvr2_stream_create(void);
+void pvr2_stream_destroy(struct pvr2_stream *);
+void pvr2_stream_setup(struct pvr2_stream *,
+                      struct usb_device *dev,int endpoint,
+                      unsigned int tolerance);
+void pvr2_stream_set_callback(struct pvr2_stream *,
+                             pvr2_stream_callback func,
+                             void *data);
+
+/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *);
+int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
+
+/* Get a pointer to a buffer that is either idle, ready, or is specified
+   named. */
+struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *);
+struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *);
+struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
+
+/* Find out how many buffers are idle or ready */
+int pvr2_stream_get_ready_count(struct pvr2_stream *);
+
+
+/* Kill all pending buffers and throw away any ready buffers as well */
+void pvr2_stream_kill(struct pvr2_stream *);
+
+/* Set up the actual storage for a buffer */
+int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt);
+
+/* Find out size of data in the given ready buffer */
+unsigned int pvr2_buffer_get_count(struct pvr2_buffer *);
+
+/* Retrieve completion code for given ready buffer */
+int pvr2_buffer_get_status(struct pvr2_buffer *);
+
+/* Retrieve ID of given buffer */
+int pvr2_buffer_get_id(struct pvr2_buffer *);
+
+/* Start reading into given buffer (kill it if needed) */
+int pvr2_buffer_queue(struct pvr2_buffer *);
+
+#endif /* __PVRUSB2_IO_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
new file mode 100644 (file)
index 0000000..b71f9a9
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-ioread.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+
+#define BUFFER_COUNT 32
+#define BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_ioread {
+       struct pvr2_stream *stream;
+       char *buffer_storage[BUFFER_COUNT];
+       char *sync_key_ptr;
+       unsigned int sync_key_len;
+       unsigned int sync_buf_offs;
+       unsigned int sync_state;
+       unsigned int sync_trashed_count;
+       int enabled;         // Streaming is on
+       int spigot_open;     // OK to pass data to client
+       int stream_running;  // Passing data to client now
+
+       /* State relevant to current buffer being read */
+       struct pvr2_buffer *c_buf;
+       char *c_data_ptr;
+       unsigned int c_data_len;
+       unsigned int c_data_offs;
+       struct mutex mutex;
+};
+
+static int pvr2_ioread_init(struct pvr2_ioread *cp)
+{
+       unsigned int idx;
+
+       cp->stream = NULL;
+       mutex_init(&cp->mutex);
+
+       for (idx = 0; idx < BUFFER_COUNT; idx++) {
+               cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL);
+               if (!(cp->buffer_storage[idx])) break;
+       }
+
+       if (idx < BUFFER_COUNT) {
+               // An allocation appears to have failed
+               for (idx = 0; idx < BUFFER_COUNT; idx++) {
+                       if (!(cp->buffer_storage[idx])) continue;
+                       kfree(cp->buffer_storage[idx]);
+               }
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void pvr2_ioread_done(struct pvr2_ioread *cp)
+{
+       unsigned int idx;
+
+       pvr2_ioread_setup(cp,NULL);
+       for (idx = 0; idx < BUFFER_COUNT; idx++) {
+               if (!(cp->buffer_storage[idx])) continue;
+               kfree(cp->buffer_storage[idx]);
+       }
+}
+
+struct pvr2_ioread *pvr2_ioread_create(void)
+{
+       struct pvr2_ioread *cp;
+       cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+       if (!cp) return NULL;
+       pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
+       memset(cp,0,sizeof(*cp));
+       if (pvr2_ioread_init(cp) < 0) {
+               kfree(cp);
+               return NULL;
+       }
+       return cp;
+}
+
+void pvr2_ioread_destroy(struct pvr2_ioread *cp)
+{
+       if (!cp) return;
+       pvr2_ioread_done(cp);
+       pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
+       if (cp->sync_key_ptr) {
+               kfree(cp->sync_key_ptr);
+               cp->sync_key_ptr = NULL;
+       }
+       kfree(cp);
+}
+
+void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
+                             const char *sync_key_ptr,
+                             unsigned int sync_key_len)
+{
+       if (!cp) return;
+
+       if (!sync_key_ptr) sync_key_len = 0;
+       if ((sync_key_len == cp->sync_key_len) &&
+           ((!sync_key_len) ||
+            (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return;
+
+       if (sync_key_len != cp->sync_key_len) {
+               if (cp->sync_key_ptr) {
+                       kfree(cp->sync_key_ptr);
+                       cp->sync_key_ptr = NULL;
+               }
+               cp->sync_key_len = 0;
+               if (sync_key_len) {
+                       cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL);
+                       if (cp->sync_key_ptr) {
+                               cp->sync_key_len = sync_key_len;
+                       }
+               }
+       }
+       if (!cp->sync_key_len) return;
+       memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len);
+}
+
+static void pvr2_ioread_stop(struct pvr2_ioread *cp)
+{
+       if (!(cp->enabled)) return;
+       pvr2_trace(PVR2_TRACE_START_STOP,
+                  "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
+       pvr2_stream_kill(cp->stream);
+       cp->c_buf = NULL;
+       cp->c_data_ptr = NULL;
+       cp->c_data_len = 0;
+       cp->c_data_offs = 0;
+       cp->enabled = 0;
+       cp->stream_running = 0;
+       cp->spigot_open = 0;
+       if (cp->sync_state) {
+               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                          "/*---TRACE_READ---*/ sync_state <== 0");
+               cp->sync_state = 0;
+       }
+}
+
+static int pvr2_ioread_start(struct pvr2_ioread *cp)
+{
+       int stat;
+       struct pvr2_buffer *bp;
+       if (cp->enabled) return 0;
+       if (!(cp->stream)) return 0;
+       pvr2_trace(PVR2_TRACE_START_STOP,
+                  "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
+       while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != 0) {
+               stat = pvr2_buffer_queue(bp);
+               if (stat < 0) {
+                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                  "/*---TRACE_READ---*/"
+                                  " pvr2_ioread_start id=%p"
+                                  " error=%d",
+                                  cp,stat);
+                       pvr2_ioread_stop(cp);
+                       return stat;
+               }
+       }
+       cp->enabled = !0;
+       cp->c_buf = NULL;
+       cp->c_data_ptr = NULL;
+       cp->c_data_len = 0;
+       cp->c_data_offs = 0;
+       cp->stream_running = 0;
+       if (cp->sync_key_len) {
+               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                          "/*---TRACE_READ---*/ sync_state <== 1");
+               cp->sync_state = 1;
+               cp->sync_trashed_count = 0;
+               cp->sync_buf_offs = 0;
+       }
+       cp->spigot_open = 0;
+       return 0;
+}
+
+struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp)
+{
+       return cp->stream;
+}
+
+int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
+{
+       int ret;
+       unsigned int idx;
+       struct pvr2_buffer *bp;
+
+       mutex_lock(&cp->mutex); do {
+               if (cp->stream) {
+                       pvr2_trace(PVR2_TRACE_START_STOP,
+                                  "/*---TRACE_READ---*/"
+                                  " pvr2_ioread_setup (tear-down) id=%p",cp);
+                       pvr2_ioread_stop(cp);
+                       pvr2_stream_kill(cp->stream);
+                       if (pvr2_stream_get_buffer_count(cp->stream)) {
+                               pvr2_stream_set_buffer_count(cp->stream,0);
+                       }
+                       cp->stream = NULL;
+               }
+               if (sp) {
+                       pvr2_trace(PVR2_TRACE_START_STOP,
+                                  "/*---TRACE_READ---*/"
+                                  " pvr2_ioread_setup (setup) id=%p",cp);
+                       pvr2_stream_kill(sp);
+                       ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
+                       if (ret < 0) return ret;
+                       for (idx = 0; idx < BUFFER_COUNT; idx++) {
+                               bp = pvr2_stream_get_buffer(sp,idx);
+                               pvr2_buffer_set_buffer(bp,
+                                                      cp->buffer_storage[idx],
+                                                      BUFFER_SIZE);
+                       }
+                       cp->stream = sp;
+               }
+       } while (0); mutex_unlock(&cp->mutex);
+
+       return 0;
+}
+
+int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
+{
+       int ret = 0;
+       if ((!fl) == (!(cp->enabled))) return ret;
+
+       mutex_lock(&cp->mutex); do {
+               if (fl) {
+                       ret = pvr2_ioread_start(cp);
+               } else {
+                       pvr2_ioread_stop(cp);
+               }
+       } while (0); mutex_unlock(&cp->mutex);
+       return ret;
+}
+
+static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
+{
+       int stat;
+
+       while (cp->c_data_len <= cp->c_data_offs) {
+               if (cp->c_buf) {
+                       // Flush out current buffer first.
+                       stat = pvr2_buffer_queue(cp->c_buf);
+                       if (stat < 0) {
+                               // Streaming error...
+                               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                          "/*---TRACE_READ---*/"
+                                          " pvr2_ioread_read id=%p"
+                                          " queue_error=%d",
+                                          cp,stat);
+                               pvr2_ioread_stop(cp);
+                               return 0;
+                       }
+                       cp->c_buf = NULL;
+                       cp->c_data_ptr = NULL;
+                       cp->c_data_len = 0;
+                       cp->c_data_offs = 0;
+               }
+               // Now get a freshly filled buffer.
+               cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream);
+               if (!cp->c_buf) break; // Nothing ready; done.
+               cp->c_data_len = pvr2_buffer_get_count(cp->c_buf);
+               if (!cp->c_data_len) {
+                       // Nothing transferred.  Was there an error?
+                       stat = pvr2_buffer_get_status(cp->c_buf);
+                       if (stat < 0) {
+                               // Streaming error...
+                               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                          "/*---TRACE_READ---*/"
+                                          " pvr2_ioread_read id=%p"
+                                          " buffer_error=%d",
+                                          cp,stat);
+                               pvr2_ioread_stop(cp);
+                               // Give up.
+                               return 0;
+                       }
+                       // Start over...
+                       continue;
+               }
+               cp->c_data_offs = 0;
+               cp->c_data_ptr = cp->buffer_storage[
+                       pvr2_buffer_get_id(cp->c_buf)];
+       }
+       return !0;
+}
+
+static void pvr2_ioread_filter(struct pvr2_ioread *cp)
+{
+       unsigned int idx;
+       if (!cp->enabled) return;
+       if (cp->sync_state != 1) return;
+
+       // Search the stream for our synchronization key.  This is made
+       // complicated by the fact that in order to be honest with
+       // ourselves here we must search across buffer boundaries...
+       mutex_lock(&cp->mutex); while (1) {
+               // Ensure we have a buffer
+               if (!pvr2_ioread_get_buffer(cp)) break;
+               if (!cp->c_data_len) break;
+
+               // Now walk the buffer contents until we match the key or
+               // run out of buffer data.
+               for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) {
+                       if (cp->sync_buf_offs >= cp->sync_key_len) break;
+                       if (cp->c_data_ptr[idx] ==
+                           cp->sync_key_ptr[cp->sync_buf_offs]) {
+                               // Found the next key byte
+                               (cp->sync_buf_offs)++;
+                       } else {
+                               // Whoops, mismatched.  Start key over...
+                               cp->sync_buf_offs = 0;
+                       }
+               }
+
+               // Consume what we've walked through
+               cp->c_data_offs += idx;
+               cp->sync_trashed_count += idx;
+
+               // If we've found the key, then update state and get out.
+               if (cp->sync_buf_offs >= cp->sync_key_len) {
+                       cp->sync_trashed_count -= cp->sync_key_len;
+                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                  "/*---TRACE_READ---*/"
+                                  " sync_state <== 2 (skipped %u bytes)",
+                                  cp->sync_trashed_count);
+                       cp->sync_state = 2;
+                       cp->sync_buf_offs = 0;
+                       break;
+               }
+
+               if (cp->c_data_offs < cp->c_data_len) {
+                       // Sanity check - should NEVER get here
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "ERROR: pvr2_ioread filter sync problem"
+                                  " len=%u offs=%u",
+                                  cp->c_data_len,cp->c_data_offs);
+                       // Get out so we don't get stuck in an infinite
+                       // loop.
+                       break;
+               }
+
+               continue; // (for clarity)
+       } mutex_unlock(&cp->mutex);
+}
+
+int pvr2_ioread_avail(struct pvr2_ioread *cp)
+{
+       int ret;
+       if (!(cp->enabled)) {
+               // Stream is not enabled; so this is an I/O error
+               return -EIO;
+       }
+
+       if (cp->sync_state == 1) {
+               pvr2_ioread_filter(cp);
+               if (cp->sync_state == 1) return -EAGAIN;
+       }
+
+       ret = 0;
+       if (cp->stream_running) {
+               if (!pvr2_stream_get_ready_count(cp->stream)) {
+                       // No data available at all right now.
+                       ret = -EAGAIN;
+               }
+       } else {
+               if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) {
+                       // Haven't buffered up enough yet; try again later
+                       ret = -EAGAIN;
+               }
+       }
+
+       if ((!(cp->spigot_open)) != (!(ret == 0))) {
+               cp->spigot_open = (ret == 0);
+               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                          "/*---TRACE_READ---*/ data is %s",
+                          cp->spigot_open ? "available" : "pending");
+       }
+
+       return ret;
+}
+
+int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
+{
+       unsigned int copied_cnt;
+       unsigned int bcnt;
+       const char *src;
+       int stat;
+       int ret = 0;
+       unsigned int req_cnt = cnt;
+
+       if (!cnt) {
+               pvr2_trace(PVR2_TRACE_TRAP,
+                          "/*---TRACE_READ---*/ pvr2_ioread_read id=%p"
+                          " ZERO Request? Returning zero.",cp);
+               return 0;
+       }
+
+       stat = pvr2_ioread_avail(cp);
+       if (stat < 0) return stat;
+
+       cp->stream_running = !0;
+
+       mutex_lock(&cp->mutex); do {
+
+               // Suck data out of the buffers and copy to the user
+               copied_cnt = 0;
+               if (!buf) cnt = 0;
+               while (1) {
+                       if (!pvr2_ioread_get_buffer(cp)) {
+                               ret = -EIO;
+                               break;
+                       }
+
+                       if (!cnt) break;
+
+                       if (cp->sync_state == 2) {
+                               // We're repeating the sync key data into
+                               // the stream.
+                               src = cp->sync_key_ptr + cp->sync_buf_offs;
+                               bcnt = cp->sync_key_len - cp->sync_buf_offs;
+                       } else {
+                               // Normal buffer copy
+                               src = cp->c_data_ptr + cp->c_data_offs;
+                               bcnt = cp->c_data_len - cp->c_data_offs;
+                       }
+
+                       if (!bcnt) break;
+
+                       // Don't run past user's buffer
+                       if (bcnt > cnt) bcnt = cnt;
+
+                       if (copy_to_user(buf,src,bcnt)) {
+                               // User supplied a bad pointer?
+                               // Give up - this *will* cause data
+                               // to be lost.
+                               ret = -EFAULT;
+                               break;
+                       }
+                       cnt -= bcnt;
+                       buf += bcnt;
+                       copied_cnt += bcnt;
+
+                       if (cp->sync_state == 2) {
+                               // Update offset inside sync key that we're
+                               // repeating back out.
+                               cp->sync_buf_offs += bcnt;
+                               if (cp->sync_buf_offs >= cp->sync_key_len) {
+                                       // Consumed entire key; switch mode
+                                       // to normal.
+                                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                                  "/*---TRACE_READ---*/"
+                                                  " sync_state <== 0");
+                                       cp->sync_state = 0;
+                               }
+                       } else {
+                               // Update buffer offset.
+                               cp->c_data_offs += bcnt;
+                       }
+               }
+
+       } while (0); mutex_unlock(&cp->mutex);
+
+       if (!ret) {
+               if (copied_cnt) {
+                       // If anything was copied, return that count
+                       ret = copied_cnt;
+               } else {
+                       // Nothing copied; suggest to caller that another
+                       // attempt should be tried again later
+                       ret = -EAGAIN;
+               }
+       }
+
+       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                  "/*---TRACE_READ---*/ pvr2_ioread_read"
+                  " id=%p request=%d result=%d",
+                  cp,req_cnt,ret);
+       return ret;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/video/pvrusb2/pvrusb2-ioread.h
new file mode 100644 (file)
index 0000000..1d362f8
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_IOREAD_H
+#define __PVRUSB2_IOREAD_H
+
+#include "pvrusb2-io.h"
+
+struct pvr2_ioread;
+
+struct pvr2_ioread *pvr2_ioread_create(void);
+void pvr2_ioread_destroy(struct pvr2_ioread *);
+int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *);
+struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *);
+void pvr2_ioread_set_sync_key(struct pvr2_ioread *,
+                             const char *sync_key_ptr,
+                             unsigned int sync_key_len);
+int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl);
+int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt);
+int pvr2_ioread_avail(struct pvr2_ioread *);
+
+#endif /* __PVRUSB2_IOREAD_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
new file mode 100644 (file)
index 0000000..e976c48
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/smp_lock.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-context.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-v4l2.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+#include "pvrusb2-sysfs.h"
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>"
+#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner"
+#define DRIVER_VERSION "V4L in-tree version"
+
+#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \
+                           PVR2_TRACE_INFO| \
+                           PVR2_TRACE_TOLERANCE| \
+                           PVR2_TRACE_TRAP| \
+                           0)
+
+int pvrusb2_debug = DEFAULT_DEBUG_MASK;
+
+module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug trace mask");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+static struct pvr2_sysfs_class *class_ptr = NULL;
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+static void pvr_setup_attach(struct pvr2_context *pvr)
+{
+       /* Create association with v4l layer */
+       pvr2_v4l2_create(pvr);
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+       pvr2_sysfs_create(pvr,class_ptr);
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+}
+
+static int pvr_probe(struct usb_interface *intf,
+                    const struct usb_device_id *devid)
+{
+       struct pvr2_context *pvr;
+
+       /* Create underlying hardware interface */
+       pvr = pvr2_context_create(intf,devid,pvr_setup_attach);
+       if (!pvr) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to create hdw handler");
+               return -ENOMEM;
+       }
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr);
+
+       usb_set_intfdata(intf, pvr);
+
+       return 0;
+}
+
+/*
+ * pvr_disconnect()
+ *
+ */
+static void pvr_disconnect(struct usb_interface *intf)
+{
+       struct pvr2_context *pvr = usb_get_intfdata(intf);
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr);
+
+       usb_set_intfdata (intf, NULL);
+       pvr2_context_disconnect(pvr);
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr);
+
+}
+
+static struct usb_driver pvr_driver = {
+       .name =         "pvrusb2",
+       .id_table =     pvr2_device_table,
+       .probe =        pvr_probe,
+       .disconnect =   pvr_disconnect
+};
+
+/*
+ * pvr_init() / pvr_exit()
+ *
+ * This code is run to initialize/exit the driver.
+ *
+ */
+static int __init pvr_init(void)
+{
+       int ret;
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+       class_ptr = pvr2_sysfs_class_create();
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+       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);
+
+       return ret;
+}
+
+static void __exit pvr_exit(void)
+{
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+       pvr2_sysfs_class_destroy(class_ptr);
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+       usb_deregister(&pvr_driver);
+}
+
+module_init(pvr_init);
+module_exit(pvr_exit);
+
+/* Mike Isely <mcisely@pobox.com> 11-Mar-2006: See pvrusb2-hdw.c for
+   MODULE_DEVICE_TABLE().  We have to declare that attribute there
+   because that's where the device table actually is now and it seems
+   that certain gcc configurations get angry if MODULE_DEVICE_TABLE()
+   is used on what ends up being an external symbol. */
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
new file mode 100644 (file)
index 0000000..f95c598
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 "pvrusb2-std.h"
+#include "pvrusb2-debug.h"
+#include <asm/string.h>
+#include <linux/slab.h>
+
+struct std_name {
+       const char *name;
+       v4l2_std_id id;
+};
+
+
+#define CSTD_PAL \
+       (V4L2_STD_PAL_B| \
+        V4L2_STD_PAL_B1| \
+        V4L2_STD_PAL_G| \
+        V4L2_STD_PAL_H| \
+        V4L2_STD_PAL_I| \
+        V4L2_STD_PAL_D| \
+        V4L2_STD_PAL_D1| \
+        V4L2_STD_PAL_K| \
+        V4L2_STD_PAL_M| \
+        V4L2_STD_PAL_N| \
+        V4L2_STD_PAL_Nc| \
+        V4L2_STD_PAL_60)
+
+#define CSTD_NTSC \
+       (V4L2_STD_NTSC_M| \
+        V4L2_STD_NTSC_M_JP| \
+        V4L2_STD_NTSC_M_KR| \
+        V4L2_STD_NTSC_443)
+
+#define CSTD_SECAM \
+       (V4L2_STD_SECAM_B| \
+        V4L2_STD_SECAM_D| \
+        V4L2_STD_SECAM_G| \
+        V4L2_STD_SECAM_H| \
+        V4L2_STD_SECAM_K| \
+        V4L2_STD_SECAM_K1| \
+        V4L2_STD_SECAM_L| \
+        V4L2_STD_SECAM_LC)
+
+#define TSTD_B   (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
+#define TSTD_B1  (V4L2_STD_PAL_B1)
+#define TSTD_D   (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
+#define TSTD_D1  (V4L2_STD_PAL_D1)
+#define TSTD_G   (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
+#define TSTD_H   (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
+#define TSTD_I   (V4L2_STD_PAL_I)
+#define TSTD_K   (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
+#define TSTD_K1  (V4L2_STD_SECAM_K1)
+#define TSTD_L   (V4L2_STD_SECAM_L)
+#define TSTD_M   (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
+#define TSTD_N   (V4L2_STD_PAL_N)
+#define TSTD_Nc  (V4L2_STD_PAL_Nc)
+#define TSTD_60  (V4L2_STD_PAL_60)
+
+#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
+
+/* Mapping of standard bits to color system */
+const static struct std_name std_groups[] = {
+       {"PAL",CSTD_PAL},
+       {"NTSC",CSTD_NTSC},
+       {"SECAM",CSTD_SECAM},
+};
+
+/* Mapping of standard bits to modulation system */
+const static struct std_name std_items[] = {
+       {"B",TSTD_B},
+       {"B1",TSTD_B1},
+       {"D",TSTD_D},
+       {"D1",TSTD_D1},
+       {"G",TSTD_G},
+       {"H",TSTD_H},
+       {"I",TSTD_I},
+       {"K",TSTD_K},
+       {"K1",TSTD_K1},
+       {"L",TSTD_L},
+       {"LC",V4L2_STD_SECAM_LC},
+       {"M",TSTD_M},
+       {"Mj",V4L2_STD_NTSC_M_JP},
+       {"443",V4L2_STD_NTSC_443},
+       {"Mk",V4L2_STD_NTSC_M_KR},
+       {"N",TSTD_N},
+       {"Nc",TSTD_Nc},
+       {"60",TSTD_60},
+};
+
+
+// Search an array of std_name structures and return a pointer to the
+// element with the matching name.
+static const struct std_name *find_std_name(const struct std_name *arrPtr,
+                                           unsigned int arrSize,
+                                           const char *bufPtr,
+                                           unsigned int bufSize)
+{
+       unsigned int idx;
+       const struct std_name *p;
+       for (idx = 0; idx < arrSize; idx++) {
+               p = arrPtr + idx;
+               if (strlen(p->name) != bufSize) continue;
+               if (!memcmp(bufPtr,p->name,bufSize)) return p;
+       }
+       return NULL;
+}
+
+
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+                      unsigned int bufSize)
+{
+       v4l2_std_id id = 0;
+       v4l2_std_id cmsk = 0;
+       v4l2_std_id t;
+       int mMode = 0;
+       unsigned int cnt;
+       char ch;
+       const struct std_name *sp;
+
+       while (bufSize) {
+               if (!mMode) {
+                       cnt = 0;
+                       while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
+                       if (cnt >= bufSize) return 0; // No more characters
+                       sp = find_std_name(
+                               std_groups,
+                               sizeof(std_groups)/sizeof(std_groups[0]),
+                               bufPtr,cnt);
+                       if (!sp) return 0; // Illegal color system name
+                       cnt++;
+                       bufPtr += cnt;
+                       bufSize -= cnt;
+                       mMode = !0;
+                       cmsk = sp->id;
+                       continue;
+               }
+               cnt = 0;
+               while (cnt < bufSize) {
+                       ch = bufPtr[cnt];
+                       if (ch == ';') {
+                               mMode = 0;
+                               break;
+                       }
+                       if (ch == '/') break;
+                       cnt++;
+               }
+               sp = find_std_name(std_items,
+                                  sizeof(std_items)/sizeof(std_items[0]),
+                                  bufPtr,cnt);
+               if (!sp) return 0; // Illegal modulation system ID
+               t = sp->id & cmsk;
+               if (!t) return 0; // Specific color + modulation system illegal
+               id |= t;
+               if (cnt < bufSize) cnt++;
+               bufPtr += cnt;
+               bufSize -= cnt;
+       }
+
+       if (idPtr) *idPtr = id;
+       return !0;
+}
+
+
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+                               v4l2_std_id id)
+{
+       unsigned int idx1,idx2;
+       const struct std_name *ip,*gp;
+       int gfl,cfl;
+       unsigned int c1,c2;
+       cfl = 0;
+       c1 = 0;
+       for (idx1 = 0;
+            idx1 < sizeof(std_groups)/sizeof(std_groups[0]);
+            idx1++) {
+               gp = std_groups + idx1;
+               gfl = 0;
+               for (idx2 = 0;
+                    idx2 < sizeof(std_items)/sizeof(std_items[0]);
+                    idx2++) {
+                       ip = std_items + idx2;
+                       if (!(gp->id & ip->id & id)) continue;
+                       if (!gfl) {
+                               if (cfl) {
+                                       c2 = scnprintf(bufPtr,bufSize,";");
+                                       c1 += c2;
+                                       bufSize -= c2;
+                                       bufPtr += c2;
+                               }
+                               cfl = !0;
+                               c2 = scnprintf(bufPtr,bufSize,
+                                              "%s-",gp->name);
+                               gfl = !0;
+                       } else {
+                               c2 = scnprintf(bufPtr,bufSize,"/");
+                       }
+                       c1 += c2;
+                       bufSize -= c2;
+                       bufPtr += c2;
+                       c2 = scnprintf(bufPtr,bufSize,
+                                      ip->name);
+                       c1 += c2;
+                       bufSize -= c2;
+                       bufPtr += c2;
+               }
+       }
+       return c1;
+}
+
+
+// Template data for possible enumerated video standards.  Here we group
+// standards which share common frame rates and resolution.
+static struct v4l2_standard generic_standards[] = {
+       {
+               .id             = (TSTD_B|TSTD_B1|
+                                  TSTD_D|TSTD_D1|
+                                  TSTD_G|
+                                  TSTD_H|
+                                  TSTD_I|
+                                  TSTD_K|TSTD_K1|
+                                  TSTD_L|
+                                  V4L2_STD_SECAM_LC |
+                                  TSTD_N|TSTD_Nc),
+               .frameperiod    =
+               {
+                       .numerator  = 1,
+                       .denominator= 25
+               },
+               .framelines     = 625,
+               .reserved       = {0,0,0,0}
+       }, {
+               .id             = (TSTD_M|
+                                  V4L2_STD_NTSC_M_JP|
+                                  V4L2_STD_NTSC_M_KR),
+               .frameperiod    =
+               {
+                       .numerator  = 1001,
+                       .denominator= 30000
+               },
+               .framelines     = 525,
+               .reserved       = {0,0,0,0}
+       }, { // This is a total wild guess
+               .id             = (TSTD_60),
+               .frameperiod    =
+               {
+                       .numerator  = 1001,
+                       .denominator= 30000
+               },
+               .framelines     = 525,
+               .reserved       = {0,0,0,0}
+       }, { // This is total wild guess
+               .id             = V4L2_STD_NTSC_443,
+               .frameperiod    =
+               {
+                       .numerator  = 1001,
+                       .denominator= 30000
+               },
+               .framelines     = 525,
+               .reserved       = {0,0,0,0}
+       }
+};
+
+#define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0]))
+
+static struct v4l2_standard *match_std(v4l2_std_id id)
+{
+       unsigned int idx;
+       for (idx = 0; idx < generic_standards_cnt; idx++) {
+               if (generic_standards[idx].id & id) {
+                       return generic_standards + idx;
+               }
+       }
+       return NULL;
+}
+
+static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
+{
+       struct v4l2_standard *template;
+       int idx;
+       unsigned int bcnt;
+       template = match_std(id);
+       if (!template) return 0;
+       idx = std->index;
+       memcpy(std,template,sizeof(*template));
+       std->index = idx;
+       std->id = id;
+       bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
+       std->name[bcnt] = 0;
+       pvr2_trace(PVR2_TRACE_INIT,"Set up standard idx=%u name=%s",
+                  std->index,std->name);
+       return !0;
+}
+
+/* These are special cases of combined standards that we should enumerate
+   separately if the component pieces are present. */
+static v4l2_std_id std_mixes[] = {
+       V4L2_STD_PAL_B | V4L2_STD_PAL_G,
+       V4L2_STD_PAL_D | V4L2_STD_PAL_K,
+       V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
+       V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
+};
+
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+                                          v4l2_std_id id)
+{
+       unsigned int std_cnt = 0;
+       unsigned int idx,bcnt,idx2;
+       v4l2_std_id idmsk,cmsk,fmsk;
+       struct v4l2_standard *stddefs;
+
+       if (pvrusb2_debug & PVR2_TRACE_INIT) {
+               char buf[50];
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
+               pvr2_trace(
+                       PVR2_TRACE_INIT,"Mapping standards mask=0x%x (%.*s)",
+                       (int)id,bcnt,buf);
+       }
+
+       *countptr = 0;
+       std_cnt = 0;
+       fmsk = 0;
+       for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
+               if (!(idmsk & cmsk)) continue;
+               cmsk &= ~idmsk;
+               if (match_std(idmsk)) {
+                       std_cnt++;
+                       continue;
+               }
+               fmsk |= idmsk;
+       }
+
+       for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) {
+               if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
+       }
+
+       if (fmsk) {
+               char buf[50];
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "WARNING:"
+                       " Failed to classify the following standard(s): %.*s",
+                       bcnt,buf);
+       }
+
+       pvr2_trace(PVR2_TRACE_INIT,"Setting up %u unique standard(s)",
+                  std_cnt);
+       if (!std_cnt) return NULL; // paranoia
+
+       stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,
+                         GFP_KERNEL);
+       memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt);
+       for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx;
+
+       idx = 0;
+
+       /* Enumerate potential special cases */
+       for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) &&
+                       (idx < std_cnt)); idx2++) {
+               if (!(id & std_mixes[idx2])) continue;
+               if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
+       }
+       /* Now enumerate individual pieces */
+       for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
+               if (!(idmsk & cmsk)) continue;
+               cmsk &= ~idmsk;
+               if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
+               idx++;
+       }
+
+       *countptr = std_cnt;
+       return stddefs;
+}
+
+v4l2_std_id pvr2_std_get_usable(void)
+{
+       return CSTD_ALL;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.h b/drivers/media/video/pvrusb2/pvrusb2-std.h
new file mode 100644 (file)
index 0000000..07c3993
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_STD_H
+#define __PVRUSB2_STD_H
+
+#include <linux/videodev2.h>
+
+// Convert string describing one or more video standards into a mask of V4L
+// standard bits.  Return true if conversion succeeds otherwise return
+// false.  String is expected to be of the form: C1-x/y;C2-a/b where C1 and
+// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are
+// modulation schemes (e.g. "M", "B", "G", etc).
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+                      unsigned int bufSize);
+
+// Convert any arbitrary set of video standard bits into an unambiguous
+// readable string.  Return value is the number of bytes consumed in the
+// buffer.  The formatted string is of a form that can be parsed by our
+// sibling std_std_to_id() function.
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+                               v4l2_std_id id);
+
+// Create an array of suitable v4l2_standard structures given a bit mask of
+// video standards to support.  The array is allocated from the heap, and
+// the number of elements is returned in the first argument.
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+                                          v4l2_std_id id);
+
+// Return mask of which video standard bits are valid
+v4l2_std_id pvr2_std_get_usable(void);
+
+#endif /* __PVRUSB2_STD_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
new file mode 100644 (file)
index 0000000..38e9222
--- /dev/null
@@ -0,0 +1,925 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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/string.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include "pvrusb2-sysfs.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+#include "pvrusb2-debugifc.h"
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
+
+struct pvr2_sysfs {
+       struct pvr2_channel channel;
+       struct class_device *class_dev;
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+       struct pvr2_sysfs_debugifc *debugifc;
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+       struct pvr2_sysfs_ctl_item *item_first;
+       struct pvr2_sysfs_ctl_item *item_last;
+       struct sysfs_ops kops;
+       struct kobj_type ktype;
+       struct class_device_attribute attr_v4l_minor_number;
+       struct class_device_attribute attr_unit_number;
+       int v4l_minor_number_created_ok;
+       int unit_number_created_ok;
+};
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+struct pvr2_sysfs_debugifc {
+       struct class_device_attribute attr_debugcmd;
+       struct class_device_attribute attr_debuginfo;
+       int debugcmd_created_ok;
+       int debuginfo_created_ok;
+};
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+struct pvr2_sysfs_ctl_item {
+       struct class_device_attribute attr_name;
+       struct class_device_attribute attr_type;
+       struct class_device_attribute attr_min;
+       struct class_device_attribute attr_max;
+       struct class_device_attribute attr_enum;
+       struct class_device_attribute attr_bits;
+       struct class_device_attribute attr_val;
+       struct class_device_attribute attr_custom;
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *chptr;
+       struct pvr2_sysfs_ctl_item *item_next;
+       struct attribute *attr_gen[7];
+       struct attribute_group grp;
+       int created_ok;
+       char name[80];
+};
+
+struct pvr2_sysfs_class {
+       struct class class;
+};
+
+static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       const char *name;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+
+       name = pvr2_ctrl_get_desc(cptr);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name);
+
+       if (!name) return -EINVAL;
+
+       return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+}
+
+static ssize_t show_type(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       const char *name;
+       enum pvr2_ctl_type tp;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+
+       tp = pvr2_ctrl_get_type(cptr);
+       switch (tp) {
+       case pvr2_ctl_int: name = "integer"; break;
+       case pvr2_ctl_enum: name = "enum"; break;
+       case pvr2_ctl_bitmask: name = "bitmask"; break;
+       case pvr2_ctl_bool: name = "boolean"; break;
+       default: name = "?"; break;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name);
+
+       if (!name) return -EINVAL;
+
+       return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+}
+
+static ssize_t show_min(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       long val;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+       val = pvr2_ctrl_get_min(cptr);
+
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val);
+
+       return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+}
+
+static ssize_t show_max(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       long val;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+       val = pvr2_ctrl_get_max(cptr);
+
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val);
+
+       return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+}
+
+static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       int val,ret;
+       unsigned int cnt = 0;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+
+       ret = pvr2_ctrl_get_value(cptr,&val);
+       if (ret < 0) return ret;
+
+       ret = pvr2_ctrl_value_to_sym(cptr,~0,val,
+                                    buf,PAGE_SIZE-1,&cnt);
+
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
+                        sfp,id,cnt,buf,val);
+       buf[cnt] = '\n';
+       return cnt+1;
+}
+
+static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       int val,ret;
+       unsigned int cnt = 0;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+
+       ret = pvr2_ctrl_get_value(cptr,&val);
+       if (ret < 0) return ret;
+
+       ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val,
+                                           buf,PAGE_SIZE-1,&cnt);
+
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
+                        sfp,id,cnt,buf,val);
+       buf[cnt] = '\n';
+       return cnt+1;
+}
+
+static ssize_t show_enum(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       long val;
+       unsigned int bcnt,ccnt,ecnt;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+       ecnt = pvr2_ctrl_get_cnt(cptr);
+       bcnt = 0;
+       for (val = 0; val < ecnt; val++) {
+               pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+               if (!ccnt) continue;
+               bcnt += ccnt;
+               if (bcnt >= PAGE_SIZE) break;
+               buf[bcnt] = '\n';
+               bcnt++;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id);
+       return bcnt;
+}
+
+static ssize_t show_bits(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       int valid_bits,msk;
+       unsigned int bcnt,ccnt;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+       valid_bits = pvr2_ctrl_get_mask(cptr);
+       bcnt = 0;
+       for (msk = 1; valid_bits; msk <<= 1) {
+               if (!(msk & valid_bits)) continue;
+               valid_bits &= ~msk;
+               pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+               bcnt += ccnt;
+               if (bcnt >= PAGE_SIZE) break;
+               buf[bcnt] = '\n';
+               bcnt++;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id);
+       return bcnt;
+}
+
+static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,
+                        const char *buf,unsigned int count)
+{
+       struct pvr2_ctrl *cptr;
+       int ret;
+       int mask,val;
+
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (customfl) {
+               ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val);
+       } else {
+               ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val);
+       }
+       if (ret < 0) return ret;
+       ret = pvr2_ctrl_set_mask_value(cptr,mask,val);
+       pvr2_hdw_commit_ctl(sfp->channel.hdw);
+       return ret;
+}
+
+static ssize_t store_val_norm(int id,struct class_device *class_dev,
+                            const char *buf,size_t count)
+{
+       struct pvr2_sysfs *sfp;
+       int ret;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       ret = store_val_any(id,0,sfp,buf,count);
+       if (!ret) ret = count;
+       return ret;
+}
+
+static ssize_t store_val_custom(int id,struct class_device *class_dev,
+                               const char *buf,size_t count)
+{
+       struct pvr2_sysfs *sfp;
+       int ret;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       ret = store_val_any(id,1,sfp,buf,count);
+       if (!ret) ret = count;
+       return ret;
+}
+
+/*
+  Mike Isely <isely@pobox.com> 30-April-2005
+
+  This next batch of horrible preprocessor hackery is needed because the
+  kernel's class_device_attribute mechanism fails to pass the actual
+  attribute through to the show / store functions, which means we have no
+  way to package up any attribute-specific parameters, like for example the
+  control id.  So we work around this brain-damage by encoding the control
+  id into the show / store functions themselves and pick the function based
+  on the control id we're setting up.  These macros try to ease the pain.
+  Yuck.
+*/
+
+#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
+static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \
+{ return sf_name(ctl_id,class_dev,buf); }
+
+#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
+static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \
+{ return sf_name(ctl_id,class_dev,buf,count); }
+
+#define CREATE_BATCH(ctl_id) \
+CREATE_SHOW_INSTANCE(show_name,ctl_id) \
+CREATE_SHOW_INSTANCE(show_type,ctl_id) \
+CREATE_SHOW_INSTANCE(show_min,ctl_id) \
+CREATE_SHOW_INSTANCE(show_max,ctl_id) \
+CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
+CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
+CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
+CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
+CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
+CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
+
+CREATE_BATCH(0)
+CREATE_BATCH(1)
+CREATE_BATCH(2)
+CREATE_BATCH(3)
+CREATE_BATCH(4)
+CREATE_BATCH(5)
+CREATE_BATCH(6)
+CREATE_BATCH(7)
+CREATE_BATCH(8)
+CREATE_BATCH(9)
+CREATE_BATCH(10)
+CREATE_BATCH(11)
+CREATE_BATCH(12)
+CREATE_BATCH(13)
+CREATE_BATCH(14)
+CREATE_BATCH(15)
+CREATE_BATCH(16)
+CREATE_BATCH(17)
+CREATE_BATCH(18)
+CREATE_BATCH(19)
+CREATE_BATCH(20)
+CREATE_BATCH(21)
+CREATE_BATCH(22)
+CREATE_BATCH(23)
+CREATE_BATCH(24)
+CREATE_BATCH(25)
+CREATE_BATCH(26)
+CREATE_BATCH(27)
+CREATE_BATCH(28)
+CREATE_BATCH(29)
+CREATE_BATCH(30)
+CREATE_BATCH(31)
+CREATE_BATCH(32)
+CREATE_BATCH(33)
+CREATE_BATCH(34)
+CREATE_BATCH(35)
+CREATE_BATCH(36)
+CREATE_BATCH(37)
+CREATE_BATCH(38)
+CREATE_BATCH(39)
+CREATE_BATCH(40)
+CREATE_BATCH(41)
+CREATE_BATCH(42)
+CREATE_BATCH(43)
+CREATE_BATCH(44)
+CREATE_BATCH(45)
+CREATE_BATCH(46)
+CREATE_BATCH(47)
+CREATE_BATCH(48)
+CREATE_BATCH(49)
+CREATE_BATCH(50)
+CREATE_BATCH(51)
+CREATE_BATCH(52)
+CREATE_BATCH(53)
+CREATE_BATCH(54)
+CREATE_BATCH(55)
+CREATE_BATCH(56)
+CREATE_BATCH(57)
+CREATE_BATCH(58)
+CREATE_BATCH(59)
+
+struct pvr2_sysfs_func_set {
+       ssize_t (*show_name)(struct class_device *,char *);
+       ssize_t (*show_type)(struct class_device *,char *);
+       ssize_t (*show_min)(struct class_device *,char *);
+       ssize_t (*show_max)(struct class_device *,char *);
+       ssize_t (*show_enum)(struct class_device *,char *);
+       ssize_t (*show_bits)(struct class_device *,char *);
+       ssize_t (*show_val_norm)(struct class_device *,char *);
+       ssize_t (*store_val_norm)(struct class_device *,
+                                 const char *,size_t);
+       ssize_t (*show_val_custom)(struct class_device *,char *);
+       ssize_t (*store_val_custom)(struct class_device *,
+                                   const char *,size_t);
+};
+
+#define INIT_BATCH(ctl_id) \
+[ctl_id] = { \
+    .show_name = show_name_##ctl_id, \
+    .show_type = show_type_##ctl_id, \
+    .show_min = show_min_##ctl_id, \
+    .show_max = show_max_##ctl_id, \
+    .show_enum = show_enum_##ctl_id, \
+    .show_bits = show_bits_##ctl_id, \
+    .show_val_norm = show_val_norm_##ctl_id, \
+    .store_val_norm = store_val_norm_##ctl_id, \
+    .show_val_custom = show_val_custom_##ctl_id, \
+    .store_val_custom = store_val_custom_##ctl_id, \
+} \
+
+static struct pvr2_sysfs_func_set funcs[] = {
+       INIT_BATCH(0),
+       INIT_BATCH(1),
+       INIT_BATCH(2),
+       INIT_BATCH(3),
+       INIT_BATCH(4),
+       INIT_BATCH(5),
+       INIT_BATCH(6),
+       INIT_BATCH(7),
+       INIT_BATCH(8),
+       INIT_BATCH(9),
+       INIT_BATCH(10),
+       INIT_BATCH(11),
+       INIT_BATCH(12),
+       INIT_BATCH(13),
+       INIT_BATCH(14),
+       INIT_BATCH(15),
+       INIT_BATCH(16),
+       INIT_BATCH(17),
+       INIT_BATCH(18),
+       INIT_BATCH(19),
+       INIT_BATCH(20),
+       INIT_BATCH(21),
+       INIT_BATCH(22),
+       INIT_BATCH(23),
+       INIT_BATCH(24),
+       INIT_BATCH(25),
+       INIT_BATCH(26),
+       INIT_BATCH(27),
+       INIT_BATCH(28),
+       INIT_BATCH(29),
+       INIT_BATCH(30),
+       INIT_BATCH(31),
+       INIT_BATCH(32),
+       INIT_BATCH(33),
+       INIT_BATCH(34),
+       INIT_BATCH(35),
+       INIT_BATCH(36),
+       INIT_BATCH(37),
+       INIT_BATCH(38),
+       INIT_BATCH(39),
+       INIT_BATCH(40),
+       INIT_BATCH(41),
+       INIT_BATCH(42),
+       INIT_BATCH(43),
+       INIT_BATCH(44),
+       INIT_BATCH(45),
+       INIT_BATCH(46),
+       INIT_BATCH(47),
+       INIT_BATCH(48),
+       INIT_BATCH(49),
+       INIT_BATCH(50),
+       INIT_BATCH(51),
+       INIT_BATCH(52),
+       INIT_BATCH(53),
+       INIT_BATCH(54),
+       INIT_BATCH(55),
+       INIT_BATCH(56),
+       INIT_BATCH(57),
+       INIT_BATCH(58),
+       INIT_BATCH(59),
+};
+
+
+static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       struct pvr2_sysfs_func_set *fp;
+       struct pvr2_ctrl *cptr;
+       unsigned int cnt,acnt;
+       int ret;
+
+       if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
+               return;
+       }
+
+       fp = funcs + ctl_id;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
+       if (!cptr) return;
+
+       cip = kmalloc(sizeof(*cip),GFP_KERNEL);
+       if (!cip) return;
+       memset(cip,0,sizeof(*cip));
+       pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
+
+       cip->cptr = cptr;
+
+       cip->chptr = sfp;
+       cip->item_next = NULL;
+       if (sfp->item_last) {
+               sfp->item_last->item_next = cip;
+       } else {
+               sfp->item_first = cip;
+       }
+       sfp->item_last = cip;
+
+       cip->attr_name.attr.owner = THIS_MODULE;
+       cip->attr_name.attr.name = "name";
+       cip->attr_name.attr.mode = S_IRUGO;
+       cip->attr_name.show = fp->show_name;
+
+       cip->attr_type.attr.owner = THIS_MODULE;
+       cip->attr_type.attr.name = "type";
+       cip->attr_type.attr.mode = S_IRUGO;
+       cip->attr_type.show = fp->show_type;
+
+       cip->attr_min.attr.owner = THIS_MODULE;
+       cip->attr_min.attr.name = "min_val";
+       cip->attr_min.attr.mode = S_IRUGO;
+       cip->attr_min.show = fp->show_min;
+
+       cip->attr_max.attr.owner = THIS_MODULE;
+       cip->attr_max.attr.name = "max_val";
+       cip->attr_max.attr.mode = S_IRUGO;
+       cip->attr_max.show = fp->show_max;
+
+       cip->attr_val.attr.owner = THIS_MODULE;
+       cip->attr_val.attr.name = "cur_val";
+       cip->attr_val.attr.mode = S_IRUGO;
+
+       cip->attr_custom.attr.owner = THIS_MODULE;
+       cip->attr_custom.attr.name = "custom_val";
+       cip->attr_custom.attr.mode = S_IRUGO;
+
+       cip->attr_enum.attr.owner = THIS_MODULE;
+       cip->attr_enum.attr.name = "enum_val";
+       cip->attr_enum.attr.mode = S_IRUGO;
+       cip->attr_enum.show = fp->show_enum;
+
+       cip->attr_bits.attr.owner = THIS_MODULE;
+       cip->attr_bits.attr.name = "bit_val";
+       cip->attr_bits.attr.mode = S_IRUGO;
+       cip->attr_bits.show = fp->show_bits;
+
+       if (pvr2_ctrl_is_writable(cptr)) {
+               cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
+               cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
+       }
+
+       acnt = 0;
+       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_val.show = fp->show_val_norm;
+       cip->attr_val.store = fp->store_val_norm;
+       if (pvr2_ctrl_has_custom_symbols(cptr)) {
+               cip->attr_gen[acnt++] = &cip->attr_custom.attr;
+               cip->attr_custom.show = fp->show_val_custom;
+               cip->attr_custom.store = fp->store_val_custom;
+       }
+       switch (pvr2_ctrl_get_type(cptr)) {
+       case pvr2_ctl_enum:
+               // Control is an enumeration
+               cip->attr_gen[acnt++] = &cip->attr_enum.attr;
+               break;
+       case pvr2_ctl_int:
+               // Control is an integer
+               cip->attr_gen[acnt++] = &cip->attr_min.attr;
+               cip->attr_gen[acnt++] = &cip->attr_max.attr;
+               break;
+       case pvr2_ctl_bitmask:
+               // Control is an bitmask
+               cip->attr_gen[acnt++] = &cip->attr_bits.attr;
+               break;
+       default: break;
+       }
+
+       cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
+                       pvr2_ctrl_get_name(cptr));
+       cip->name[cnt] = 0;
+       cip->grp.name = cip->name;
+       cip->grp.attrs = cip->attr_gen;
+
+       ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+       if (ret) {
+               printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+                      __FUNCTION__, ret);
+               return;
+       }
+       cip->created_ok = !0;
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+static ssize_t debuginfo_show(struct class_device *,char *);
+static ssize_t debugcmd_show(struct class_device *,char *);
+static ssize_t debugcmd_store(struct class_device *,const char *,size_t count);
+
+static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
+{
+       struct pvr2_sysfs_debugifc *dip;
+       int ret;
+
+       dip = kmalloc(sizeof(*dip),GFP_KERNEL);
+       if (!dip) return;
+       memset(dip,0,sizeof(*dip));
+       dip->attr_debugcmd.attr.owner = THIS_MODULE;
+       dip->attr_debugcmd.attr.name = "debugcmd";
+       dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
+       dip->attr_debugcmd.show = debugcmd_show;
+       dip->attr_debugcmd.store = debugcmd_store;
+       dip->attr_debuginfo.attr.owner = THIS_MODULE;
+       dip->attr_debuginfo.attr.name = "debuginfo";
+       dip->attr_debuginfo.attr.mode = S_IRUGO;
+       dip->attr_debuginfo.show = debuginfo_show;
+       sfp->debugifc = dip;
+       ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               dip->debugcmd_created_ok = !0;
+       }
+       ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               dip->debuginfo_created_ok = !0;
+       }
+}
+
+
+static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
+{
+       if (!sfp->debugifc) return;
+       if (sfp->debugifc->debuginfo_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debuginfo);
+       }
+       if (sfp->debugifc->debugcmd_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debugcmd);
+       }
+       kfree(sfp->debugifc);
+       sfp->debugifc = NULL;
+}
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+
+static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
+{
+       unsigned int idx,cnt;
+       cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
+       for (idx = 0; idx < cnt; idx++) {
+               pvr2_sysfs_add_control(sfp,idx);
+       }
+}
+
+
+static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
+{
+       struct pvr2_sysfs_ctl_item *cip1,*cip2;
+       for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
+               cip2 = cip1->item_next;
+               if (cip1->created_ok) {
+                       sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+               }
+               pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
+               kfree(cip1);
+       }
+}
+
+
+static void pvr2_sysfs_class_release(struct class *class)
+{
+       struct pvr2_sysfs_class *clp;
+       clp = container_of(class,struct pvr2_sysfs_class,class);
+       pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
+       kfree(clp);
+}
+
+
+static void pvr2_sysfs_release(struct class_device *class_dev)
+{
+       pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
+       kfree(class_dev);
+}
+
+
+static void class_dev_destroy(struct pvr2_sysfs *sfp)
+{
+       if (!sfp->class_dev) return;
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+       pvr2_sysfs_tear_down_debugifc(sfp);
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+       pvr2_sysfs_tear_down_controls(sfp);
+       if (sfp->v4l_minor_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_minor_number);
+       }
+       if (sfp->unit_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_unit_number);
+       }
+       pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
+       sfp->class_dev->class_data = NULL;
+       class_device_unregister(sfp->class_dev);
+       sfp->class_dev = NULL;
+}
+
+
+static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw));
+}
+
+
+static ssize_t unit_number_show(struct class_device *class_dev,char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_get_unit_number(sfp->channel.hdw));
+}
+
+
+static void class_dev_create(struct pvr2_sysfs *sfp,
+                            struct pvr2_sysfs_class *class_ptr)
+{
+       struct usb_device *usb_dev;
+       struct class_device *class_dev;
+       int ret;
+
+       usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
+       if (!usb_dev) return;
+       class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
+       if (!class_dev) return;
+       memset(class_dev,0,sizeof(*class_dev));
+
+       pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
+
+       class_dev->class = &class_ptr->class;
+       if (pvr2_hdw_get_sn(sfp->channel.hdw)) {
+               snprintf(class_dev->class_id,BUS_ID_SIZE,"sn-%lu",
+                        pvr2_hdw_get_sn(sfp->channel.hdw));
+       } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) {
+               snprintf(class_dev->class_id,BUS_ID_SIZE,"unit-%c",
+                        pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a');
+       } else {
+               kfree(class_dev);
+               return;
+       }
+
+       class_dev->dev = &usb_dev->dev;
+
+       sfp->class_dev = class_dev;
+       class_dev->class_data = sfp;
+       ret = class_device_register(class_dev);
+       if (ret) {
+               printk(KERN_ERR "%s: class_device_register failed\n",
+                      __FUNCTION__);
+               kfree(class_dev);
+               return;
+       }
+
+       sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
+       sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
+       sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
+       sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
+       sfp->attr_v4l_minor_number.store = NULL;
+       ret = class_device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_minor_number);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               sfp->v4l_minor_number_created_ok = !0;
+       }
+
+       sfp->attr_unit_number.attr.owner = THIS_MODULE;
+       sfp->attr_unit_number.attr.name = "unit_number";
+       sfp->attr_unit_number.attr.mode = S_IRUGO;
+       sfp->attr_unit_number.show = unit_number_show;
+       sfp->attr_unit_number.store = NULL;
+       ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+       if (ret < 0) {
+               printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+                      __FUNCTION__, ret);
+       } else {
+               sfp->unit_number_created_ok = !0;
+       }
+
+       pvr2_sysfs_add_controls(sfp);
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+       pvr2_sysfs_add_debugifc(sfp);
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+}
+
+
+static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = container_of(chp,struct pvr2_sysfs,channel);
+       if (!sfp->channel.mc_head->disconnect_flag) return;
+       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
+       class_dev_destroy(sfp);
+       pvr2_channel_done(&sfp->channel);
+       kfree(sfp);
+}
+
+
+struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
+                                    struct pvr2_sysfs_class *class_ptr)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = kmalloc(sizeof(*sfp),GFP_KERNEL);
+       if (!sfp) return sfp;
+       memset(sfp,0,sizeof(*sfp));
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
+       pvr2_channel_init(&sfp->channel,mp);
+       sfp->channel.check_func = pvr2_sysfs_internal_check;
+
+       class_dev_create(sfp,class_ptr);
+       return sfp;
+}
+
+
+static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp,
+                             int numenvp,char *buf,int size)
+{
+       /* Even though we don't do anything here, we still need this function
+          because sysfs will still try to call it. */
+       return 0;
+}
+
+struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
+{
+       struct pvr2_sysfs_class *clp;
+       clp = kmalloc(sizeof(*clp),GFP_KERNEL);
+       if (!clp) return clp;
+       memset(clp,0,sizeof(*clp));
+       pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
+       clp->class.name = "pvrusb2";
+       clp->class.class_release = pvr2_sysfs_class_release;
+       clp->class.release = pvr2_sysfs_release;
+       clp->class.uevent = pvr2_sysfs_hotplug;
+       if (class_register(&clp->class)) {
+               pvr2_sysfs_trace(
+                       "Registration failed for pvr2_sysfs_class id=%p",clp);
+               kfree(clp);
+               clp = NULL;
+       }
+       return clp;
+}
+
+
+void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
+{
+       class_unregister(&clp->class);
+}
+
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+static ssize_t debuginfo_show(struct class_device *class_dev,char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       pvr2_hdw_trigger_module_log(sfp->channel.hdw);
+       return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
+}
+
+
+static ssize_t debugcmd_show(struct class_device *class_dev,char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
+}
+
+
+static ssize_t debugcmd_store(struct class_device *class_dev,
+                             const char *buf,size_t count)
+{
+       struct pvr2_sysfs *sfp;
+       int ret;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+
+       ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
+       if (ret < 0) return ret;
+       return count;
+}
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
new file mode 100644 (file)
index 0000000..ff9373b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_SYSFS_H
+#define __PVRUSB2_SYSFS_H
+
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include "pvrusb2-context.h"
+
+struct pvr2_sysfs;
+struct pvr2_sysfs_class;
+
+struct pvr2_sysfs_class *pvr2_sysfs_class_create(void);
+void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *);
+
+struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *,
+                                    struct pvr2_sysfs_class *);
+
+#endif /* __PVRUSB2_SYSFS_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
new file mode 100644 (file)
index 0000000..af9f246
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2.h"
+#include "pvrusb2-util.h"
+#include "pvrusb2-tuner.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+
+struct pvr2_tuner_handler {
+       struct pvr2_hdw *hdw;
+       struct pvr2_i2c_client *client;
+       struct pvr2_i2c_handler i2c_handler;
+       int type_update_fl;
+};
+
+
+static void set_type(struct pvr2_tuner_handler *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       struct tuner_setup setup;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type);
+       if (((int)(hdw->tuner_type)) < 0) return;
+
+       setup.addr = ADDR_UNSET;
+       setup.type = hdw->tuner_type;
+       setup.mode_mask = T_RADIO | T_ANALOG_TV;
+       /* We may really want mode_mask to be T_ANALOG_TV for now */
+       pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup);
+       ctxt->type_update_fl = 0;
+}
+
+
+static int tuner_check(struct pvr2_tuner_handler *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       if (hdw->tuner_updated) ctxt->type_update_fl = !0;
+       return ctxt->type_update_fl != 0;
+}
+
+
+static void tuner_update(struct pvr2_tuner_handler *ctxt)
+{
+       if (ctxt->type_update_fl) set_type(ctxt);
+}
+
+
+static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt)
+{
+       ctxt->client->handler = NULL;
+       kfree(ctxt);
+}
+
+
+static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt)
+{
+       return scnprintf(buf,cnt,"handler: pvrusb2-tuner");
+}
+
+
+const static struct pvr2_i2c_handler_functions tuner_funcs = {
+       .detach = (void (*)(void *))pvr2_tuner_detach,
+       .check = (int (*)(void *))tuner_check,
+       .update = (void (*)(void *))tuner_update,
+       .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe,
+};
+
+
+int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+       struct pvr2_tuner_handler *ctxt;
+       if (cp->handler) return 0;
+
+       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       if (!ctxt) return 0;
+       memset(ctxt,0,sizeof(*ctxt));
+
+       ctxt->i2c_handler.func_data = ctxt;
+       ctxt->i2c_handler.func_table = &tuner_funcs;
+       ctxt->type_update_fl = !0;
+       ctxt->client = cp;
+       ctxt->hdw = hdw;
+       cp->handler = &ctxt->i2c_handler;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up",
+                  cp->client->addr);
+       return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-tuner.h
new file mode 100644 (file)
index 0000000..556f12a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_TUNER_H
+#define __PVRUSB2_TUNER_H
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+#endif /* __PVRUSB2_TUNER_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-util.h b/drivers/media/video/pvrusb2/pvrusb2-util.h
new file mode 100644 (file)
index 0000000..e53aee4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_UTIL_H
+#define __PVRUSB2_UTIL_H
+
+#define PVR2_DECOMPOSE_LE(t,i,d) \
+    do {    \
+       (t)[i] = (d) & 0xff;\
+       (t)[i+1] = ((d) >> 8) & 0xff;\
+       (t)[i+2] = ((d) >> 16) & 0xff;\
+       (t)[i+3] = ((d) >> 24) & 0xff;\
+    } while(0)
+
+#define PVR2_DECOMPOSE_BE(t,i,d) \
+    do {    \
+       (t)[i+3] = (d) & 0xff;\
+       (t)[i+2] = ((d) >> 8) & 0xff;\
+       (t)[i+1] = ((d) >> 16) & 0xff;\
+       (t)[i] = ((d) >> 24) & 0xff;\
+    } while(0)
+
+#define PVR2_COMPOSE_LE(t,i) \
+    ((((u32)((t)[i+3])) << 24) | \
+     (((u32)((t)[i+2])) << 16) | \
+     (((u32)((t)[i+1])) << 8) | \
+     ((u32)((t)[i])))
+
+#define PVR2_COMPOSE_BE(t,i) \
+    ((((u32)((t)[i])) << 24) | \
+     (((u32)((t)[i+1])) << 16) | \
+     (((u32)((t)[i+2])) << 8) | \
+     ((u32)((t)[i+3])))
+
+
+#endif /* __PVRUSB2_UTIL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
new file mode 100644 (file)
index 0000000..72f444c
--- /dev/null
@@ -0,0 +1,1087 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/videodev.h>
+#include "pvrusb2-context.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-v4l2.h"
+#include "pvrusb2-ioread.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+
+/* Mike Isely <isely@pobox.com> 23-Sep-2006 - This function is prototyped
+ * only for V4L1 but is implemented regardless of the V4L1 compatibility
+ * option state.  V4L2 has no replacement for this and we need it.  For now
+ * copy the prototype here so we can avoid the compiler warning. */
+extern struct video_device* video_devdata(struct file*);
+
+struct pvr2_v4l2_dev;
+struct pvr2_v4l2_fh;
+struct pvr2_v4l2;
+
+
+struct pvr2_v4l2_dev {
+       struct pvr2_v4l2 *v4lp;
+       struct video_device *vdev;
+       struct pvr2_context_stream *stream;
+       enum pvr2_config config;
+};
+
+struct pvr2_v4l2_fh {
+       struct pvr2_channel channel;
+       struct pvr2_v4l2_dev *dev_info;
+       enum v4l2_priority prio;
+       struct pvr2_ioread *rhp;
+       struct file *file;
+       struct pvr2_v4l2 *vhead;
+       struct pvr2_v4l2_fh *vnext;
+       struct pvr2_v4l2_fh *vprev;
+       wait_queue_head_t wait_data;
+       int fw_mode_flag;
+};
+
+struct pvr2_v4l2 {
+       struct pvr2_channel channel;
+       struct pvr2_v4l2_fh *vfirst;
+       struct pvr2_v4l2_fh *vlast;
+
+       struct v4l2_prio_state prio;
+
+       /* streams */
+       struct pvr2_v4l2_dev video_dev;
+};
+
+static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "Offset for device's minor");
+
+static struct v4l2_capability pvr_capability ={
+       .driver         = "pvrusb2",
+       .card           = "Hauppauge WinTV pvr-usb2",
+       .bus_info       = "usb",
+       .version        = KERNEL_VERSION(0,8,0),
+       .capabilities   = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+                          V4L2_CAP_READWRITE),
+       .reserved       = {0,0,0,0}
+};
+
+static struct v4l2_tuner pvr_v4l2_tuners[]= {
+       {
+               .index      = 0,
+               .name       = "TV Tuner",
+               .type           = V4L2_TUNER_ANALOG_TV,
+               .capability     = (V4L2_TUNER_CAP_NORM |
+                                  V4L2_TUNER_CAP_STEREO |
+                                  V4L2_TUNER_CAP_LANG1 |
+                                  V4L2_TUNER_CAP_LANG2),
+               .rangelow   = 0,
+               .rangehigh  = 0,
+               .rxsubchans     = V4L2_TUNER_SUB_STEREO,
+               .audmode        = V4L2_TUNER_MODE_STEREO,
+               .signal         = 0,
+               .afc            = 0,
+               .reserved       = {0,0,0,0}
+       }
+};
+
+static struct v4l2_fmtdesc pvr_fmtdesc [] = {
+       {
+               .index          = 0,
+               .type           = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .flags          = V4L2_FMT_FLAG_COMPRESSED,
+               .description    = "MPEG1/2",
+               // This should really be V4L2_PIX_FMT_MPEG, but xawtv
+               // breaks when I do that.
+               .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
+               .reserved       = { 0, 0, 0, 0 }
+       }
+};
+
+#define PVR_FORMAT_PIX  0
+#define PVR_FORMAT_VBI  1
+
+static struct v4l2_format pvr_format [] = {
+       [PVR_FORMAT_PIX] = {
+               .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .fmt    = {
+                       .pix        = {
+                               .width          = 720,
+                               .height             = 576,
+                               // This should really be V4L2_PIX_FMT_MPEG,
+                               // but xawtv breaks when I do that.
+                               .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
+                               .field          = V4L2_FIELD_INTERLACED,
+                               .bytesperline   = 0,  // doesn't make sense
+                                                     // here
+                               //FIXME : Don't know what to put here...
+                               .sizeimage          = (32*1024),
+                               .colorspace     = 0, // doesn't make sense here
+                               .priv           = 0
+                       }
+               }
+       },
+       [PVR_FORMAT_VBI] = {
+               .type   = V4L2_BUF_TYPE_VBI_CAPTURE,
+               .fmt    = {
+                       .vbi        = {
+                               .sampling_rate = 27000000,
+                               .offset = 248,
+                               .samples_per_line = 1443,
+                               .sample_format = V4L2_PIX_FMT_GREY,
+                               .start = { 0, 0 },
+                               .count = { 0, 0 },
+                               .flags = 0,
+                               .reserved = { 0, 0 }
+                       }
+               }
+       }
+};
+
+/*
+ * pvr_ioctl()
+ *
+ * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
+ *
+ */
+static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+                             unsigned int cmd, void *arg)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_v4l2 *vp = fh->vhead;
+       struct pvr2_v4l2_dev *dev_info = fh->dev_info;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int ret = -EINVAL;
+
+       if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+               v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
+       }
+
+       if (!pvr2_hdw_dev_ok(hdw)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "ioctl failed - bad or no context");
+               return -EFAULT;
+       }
+
+       /* check priority */
+       switch (cmd) {
+       case VIDIOC_S_CTRL:
+       case VIDIOC_S_STD:
+       case VIDIOC_S_INPUT:
+       case VIDIOC_S_TUNER:
+       case VIDIOC_S_FREQUENCY:
+               ret = v4l2_prio_check(&vp->prio, &fh->prio);
+               if (ret)
+                       return ret;
+       }
+
+       switch (cmd) {
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
+
+               ret = 0;
+               break;
+       }
+
+       case VIDIOC_G_PRIORITY:
+       {
+               enum v4l2_priority *p = arg;
+
+               *p = v4l2_prio_max(&vp->prio);
+               ret = 0;
+               break;
+       }
+
+       case VIDIOC_S_PRIORITY:
+       {
+               enum v4l2_priority *prio = arg;
+
+               ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
+               break;
+       }
+
+       case VIDIOC_ENUMSTD:
+       {
+               struct v4l2_standard *vs = (struct v4l2_standard *)arg;
+               int idx = vs->index;
+               ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
+               break;
+       }
+
+       case VIDIOC_G_STD:
+       {
+               int val = 0;
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
+               *(v4l2_std_id *)arg = val;
+               break;
+       }
+
+       case VIDIOC_S_STD:
+       {
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
+                       *(v4l2_std_id *)arg);
+               break;
+       }
+
+       case VIDIOC_ENUMINPUT:
+       {
+               struct pvr2_ctrl *cptr;
+               struct v4l2_input *vi = (struct v4l2_input *)arg;
+               struct v4l2_input tmp;
+               unsigned int cnt;
+
+               cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+
+               memset(&tmp,0,sizeof(tmp));
+               tmp.index = vi->index;
+               ret = 0;
+               switch (vi->index) {
+               case PVR2_CVAL_INPUT_TV:
+               case PVR2_CVAL_INPUT_RADIO:
+                       tmp.type = V4L2_INPUT_TYPE_TUNER;
+                       break;
+               case PVR2_CVAL_INPUT_SVIDEO:
+               case PVR2_CVAL_INPUT_COMPOSITE:
+                       tmp.type = V4L2_INPUT_TYPE_CAMERA;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+               if (ret < 0) break;
+
+               cnt = 0;
+               pvr2_ctrl_get_valname(cptr,vi->index,
+                                     tmp.name,sizeof(tmp.name)-1,&cnt);
+               tmp.name[cnt] = 0;
+
+               /* Don't bother with audioset, since this driver currently
+                  always switches the audio whenever the video is
+                  switched. */
+
+               /* Handling std is a tougher problem.  It doesn't make
+                  sense in cases where a device might be multi-standard.
+                  We could just copy out the current value for the
+                  standard, but it can change over time.  For now just
+                  leave it zero. */
+
+               memcpy(vi, &tmp, sizeof(tmp));
+
+               ret = 0;
+               break;
+       }
+
+       case VIDIOC_G_INPUT:
+       {
+               struct pvr2_ctrl *cptr;
+               struct v4l2_input *vi = (struct v4l2_input *)arg;
+               int val;
+               cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+               val = 0;
+               ret = pvr2_ctrl_get_value(cptr,&val);
+               vi->index = val;
+               break;
+       }
+
+       case VIDIOC_S_INPUT:
+       {
+               struct v4l2_input *vi = (struct v4l2_input *)arg;
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+                       vi->index);
+               break;
+       }
+
+       case VIDIOC_ENUMAUDIO:
+       {
+               ret = -EINVAL;
+               break;
+       }
+
+       case VIDIOC_G_AUDIO:
+       {
+               ret = -EINVAL;
+               break;
+       }
+
+       case VIDIOC_S_AUDIO:
+       {
+               ret = -EINVAL;
+               break;
+       }
+       case VIDIOC_G_TUNER:
+       {
+               struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+               unsigned int status_mask;
+               int val;
+               if (vt->index !=0) break;
+
+               status_mask = pvr2_hdw_get_signal_status(hdw);
+
+               memcpy(vt, &pvr_v4l2_tuners[vt->index],
+                      sizeof(struct v4l2_tuner));
+
+               vt->signal = 0;
+               if (status_mask & PVR2_SIGNAL_OK) {
+                       if (status_mask & PVR2_SIGNAL_STEREO) {
+                               vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+                       } else {
+                               vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+                       }
+                       if (status_mask & PVR2_SIGNAL_SAP) {
+                               vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 |
+                                                  V4L2_TUNER_SUB_LANG2);
+                       }
+                       vt->signal = 65535;
+               }
+
+               val = 0;
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
+                       &val);
+               vt->audmode = val;
+               break;
+       }
+
+       case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
+
+               if (vt->index != 0)
+                       break;
+
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
+                       vt->audmode);
+       }
+
+       case VIDIOC_S_FREQUENCY:
+       {
+               const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
+                       vf->frequency * 62500);
+               break;
+       }
+
+       case VIDIOC_G_FREQUENCY:
+       {
+               struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
+               int val = 0;
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
+                       &val);
+               val /= 62500;
+               vf->frequency = val;
+               break;
+       }
+
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
+
+               /* Only one format is supported : mpeg.*/
+               if (fd->index != 0)
+                       break;
+
+               memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
+               ret = 0;
+               break;
+       }
+
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *vf = (struct v4l2_format *)arg;
+               int val;
+               switch(vf->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
+                              sizeof(struct v4l2_format));
+                       val = 0;
+                       pvr2_ctrl_get_value(
+                               pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
+                               &val);
+                       vf->fmt.pix.width = val;
+                       val = 0;
+                       pvr2_ctrl_get_value(
+                               pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
+                               &val);
+                       vf->fmt.pix.height = val;
+                       ret = 0;
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       // ????? Still need to figure out to do VBI correctly
+                       ret = -EINVAL;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       }
+
+       case VIDIOC_TRY_FMT:
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *vf = (struct v4l2_format *)arg;
+
+               ret = 0;
+               switch(vf->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+                       int lmin,lmax;
+                       struct pvr2_ctrl *hcp,*vcp;
+                       int h = vf->fmt.pix.height;
+                       int w = vf->fmt.pix.width;
+                       hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
+                       vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
+
+                       lmin = pvr2_ctrl_get_min(hcp);
+                       lmax = pvr2_ctrl_get_max(hcp);
+                       if (w < lmin) {
+                               w = lmin;
+                       } else if (w > lmax) {
+                               w = lmax;
+                       }
+                       lmin = pvr2_ctrl_get_min(vcp);
+                       lmax = pvr2_ctrl_get_max(vcp);
+                       if (h < lmin) {
+                               h = lmin;
+                       } else if (h > lmax) {
+                               h = lmax;
+                       }
+
+                       memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
+                              sizeof(struct v4l2_format));
+                       vf->fmt.pix.width = w;
+                       vf->fmt.pix.height = h;
+
+                       if (cmd == VIDIOC_S_FMT) {
+                               pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
+                               pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
+                       }
+               } break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       // ????? Still need to figure out to do VBI correctly
+                       ret = -EINVAL;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       }
+
+       case VIDIOC_STREAMON:
+       {
+               ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
+               if (ret < 0) return ret;
+               ret = pvr2_hdw_set_streaming(hdw,!0);
+               break;
+       }
+
+       case VIDIOC_STREAMOFF:
+       {
+               ret = pvr2_hdw_set_streaming(hdw,0);
+               break;
+       }
+
+       case VIDIOC_QUERYCTRL:
+       {
+               struct pvr2_ctrl *cptr;
+               struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
+               ret = 0;
+               if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+                       cptr = pvr2_hdw_get_ctrl_nextv4l(
+                               hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
+                       if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
+               } else {
+                       cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
+               }
+               if (!cptr) {
+                       pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                                  "QUERYCTRL id=0x%x not implemented here",
+                                  vc->id);
+                       ret = -EINVAL;
+                       break;
+               }
+
+               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                          "QUERYCTRL id=0x%x mapping name=%s (%s)",
+                          vc->id,pvr2_ctrl_get_name(cptr),
+                          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);
+               switch (pvr2_ctrl_get_type(cptr)) {
+               case pvr2_ctl_enum:
+                       vc->type = V4L2_CTRL_TYPE_MENU;
+                       vc->minimum = 0;
+                       vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
+                       vc->step = 1;
+                       break;
+               case pvr2_ctl_bool:
+                       vc->type = V4L2_CTRL_TYPE_BOOLEAN;
+                       vc->minimum = 0;
+                       vc->maximum = 1;
+                       vc->step = 1;
+                       break;
+               case pvr2_ctl_int:
+                       vc->type = V4L2_CTRL_TYPE_INTEGER;
+                       vc->minimum = pvr2_ctrl_get_min(cptr);
+                       vc->maximum = pvr2_ctrl_get_max(cptr);
+                       vc->step = 1;
+                       break;
+               default:
+                       pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                                  "QUERYCTRL id=0x%x name=%s not mappable",
+                                  vc->id,pvr2_ctrl_get_name(cptr));
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       }
+
+       case VIDIOC_QUERYMENU:
+       {
+               struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
+               unsigned int cnt = 0;
+               ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
+                                           vm->index,
+                                           vm->name,sizeof(vm->name)-1,
+                                           &cnt);
+               vm->name[cnt] = 0;
+               break;
+       }
+
+       case VIDIOC_G_CTRL:
+       {
+               struct v4l2_control *vc = (struct v4l2_control *)arg;
+               int val = 0;
+               ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
+                                         &val);
+               vc->value = val;
+               break;
+       }
+
+       case VIDIOC_S_CTRL:
+       {
+               struct v4l2_control *vc = (struct v4l2_control *)arg;
+               ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
+                                         vc->value);
+               break;
+       }
+
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctls =
+                       (struct v4l2_ext_controls *)arg;
+               struct v4l2_ext_control *ctrl;
+               unsigned int idx;
+               int val;
+               for (idx = 0; idx < ctls->count; idx++) {
+                       ctrl = ctls->controls + idx;
+                       ret = pvr2_ctrl_get_value(
+                               pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
+                       if (ret) {
+                               ctls->error_idx = idx;
+                               break;
+                       }
+                       /* Ensure that if read as a 64 bit value, the user
+                          will still get a hopefully sane value */
+                       ctrl->value64 = 0;
+                       ctrl->value = val;
+               }
+               break;
+       }
+
+       case VIDIOC_S_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctls =
+                       (struct v4l2_ext_controls *)arg;
+               struct v4l2_ext_control *ctrl;
+               unsigned int idx;
+               for (idx = 0; idx < ctls->count; idx++) {
+                       ctrl = ctls->controls + idx;
+                       ret = pvr2_ctrl_set_value(
+                               pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
+                               ctrl->value);
+                       if (ret) {
+                               ctls->error_idx = idx;
+                               break;
+                       }
+               }
+               break;
+       }
+
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctls =
+                       (struct v4l2_ext_controls *)arg;
+               struct v4l2_ext_control *ctrl;
+               struct pvr2_ctrl *pctl;
+               unsigned int idx;
+               /* For the moment just validate that the requested control
+                  actually exists. */
+               for (idx = 0; idx < ctls->count; idx++) {
+                       ctrl = ctls->controls + idx;
+                       pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
+                       if (!pctl) {
+                               ret = -EINVAL;
+                               ctls->error_idx = idx;
+                               break;
+                       }
+               }
+               break;
+       }
+
+       case VIDIOC_LOG_STATUS:
+       {
+               pvr2_hdw_trigger_module_log(hdw);
+               ret = 0;
+               break;
+       }
+
+       default :
+               ret = v4l_compat_translate_ioctl(inode,file,cmd,
+                                                arg,pvr2_v4l2_do_ioctl);
+       }
+
+       pvr2_hdw_commit_ctl(hdw);
+
+       if (ret < 0) {
+               if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+                       pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                                  "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
+               } else {
+                       if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+                               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                                          "pvr2_v4l2_do_ioctl failure, ret=%d"
+                                          " command was:",ret);
+                               v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
+                                               cmd);
+                       }
+               }
+       } else {
+               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                          "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
+                          ret,ret);
+       }
+       return ret;
+}
+
+
+static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
+{
+       printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
+              dip->vdev->minor,pvr2_config_get_name(dip->config));
+       video_unregister_device(dip->vdev);
+}
+
+
+static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
+{
+       pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
+       pvr2_v4l2_dev_destroy(&vp->video_dev);
+
+       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
+       pvr2_channel_done(&vp->channel);
+       kfree(vp);
+}
+
+
+static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_v4l2 *vp;
+       vp = container_of(chp,struct pvr2_v4l2,channel);
+       if (!vp->channel.mc_head->disconnect_flag) return;
+       if (vp->vfirst) return;
+       pvr2_v4l2_destroy_no_lock(vp);
+}
+
+
+static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
+                          unsigned int cmd, unsigned long arg)
+{
+
+/* Temporary hack : use ivtv api until a v4l2 one is available. */
+#define IVTV_IOC_G_CODEC        0xFFEE7703
+#define IVTV_IOC_S_CODEC        0xFFEE7704
+       if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
+       return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
+}
+
+
+static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+{
+       struct pvr2_v4l2_fh *fhp = file->private_data;
+       struct pvr2_v4l2 *vp = fhp->vhead;
+       struct pvr2_context *mp = fhp->vhead->channel.mc_head;
+
+       pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
+
+       if (fhp->rhp) {
+               struct pvr2_stream *sp;
+               struct pvr2_hdw *hdw;
+               hdw = fhp->channel.mc_head->hdw;
+               pvr2_hdw_set_streaming(hdw,0);
+               sp = pvr2_ioread_get_stream(fhp->rhp);
+               if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
+               pvr2_ioread_destroy(fhp->rhp);
+               fhp->rhp = NULL;
+       }
+       v4l2_prio_close(&vp->prio, &fhp->prio);
+       file->private_data = NULL;
+
+       pvr2_context_enter(mp); do {
+               if (fhp->vnext) {
+                       fhp->vnext->vprev = fhp->vprev;
+               } else {
+                       vp->vlast = fhp->vprev;
+               }
+               if (fhp->vprev) {
+                       fhp->vprev->vnext = fhp->vnext;
+               } else {
+                       vp->vfirst = fhp->vnext;
+               }
+               fhp->vnext = NULL;
+               fhp->vprev = NULL;
+               fhp->vhead = NULL;
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p",fhp);
+               kfree(fhp);
+               if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+                       pvr2_v4l2_destroy_no_lock(vp);
+               }
+       } while (0); pvr2_context_exit(mp);
+       return 0;
+}
+
+
+static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+{
+       struct pvr2_v4l2_dev *dip = NULL; /* Our own context pointer */
+       struct pvr2_v4l2_fh *fhp;
+       struct pvr2_v4l2 *vp;
+       struct pvr2_hdw *hdw;
+
+       {
+               struct video_device *vdev = video_devdata(file);
+               dip = (struct pvr2_v4l2_dev *)video_get_drvdata(vdev);
+       }
+
+       if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
+
+       vp = dip->v4lp;
+       hdw = vp->channel.hdw;
+
+       pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
+
+       if (!pvr2_hdw_dev_ok(hdw)) {
+               pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
+                          "pvr2_v4l2_open: hardware not ready");
+               return -EIO;
+       }
+
+       fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
+       if (!fhp) {
+               return -ENOMEM;
+       }
+       memset(fhp,0,sizeof(*fhp));
+
+       init_waitqueue_head(&fhp->wait_data);
+       fhp->dev_info = dip;
+
+       pvr2_context_enter(vp->channel.mc_head); do {
+               pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+               pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+               fhp->vnext = NULL;
+               fhp->vprev = vp->vlast;
+               if (vp->vlast) {
+                       vp->vlast->vnext = fhp;
+               } else {
+                       vp->vfirst = fhp;
+               }
+               vp->vlast = fhp;
+               fhp->vhead = vp;
+       } while (0); pvr2_context_exit(vp->channel.mc_head);
+
+       fhp->file = file;
+       file->private_data = fhp;
+       v4l2_prio_open(&vp->prio,&fhp->prio);
+
+       fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
+
+       return 0;
+}
+
+
+static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
+{
+       wake_up(&fhp->wait_data);
+}
+
+static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
+{
+       int ret;
+       struct pvr2_stream *sp;
+       struct pvr2_hdw *hdw;
+       if (fh->rhp) return 0;
+
+       /* First read() attempt.  Try to claim the stream and start
+          it... */
+       if ((ret = pvr2_channel_claim_stream(&fh->channel,
+                                            fh->dev_info->stream)) != 0) {
+               /* Someone else must already have it */
+               return ret;
+       }
+
+       fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
+       if (!fh->rhp) {
+               pvr2_channel_claim_stream(&fh->channel,NULL);
+               return -ENOMEM;
+       }
+
+       hdw = fh->channel.mc_head->hdw;
+       sp = fh->dev_info->stream->stream;
+       pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
+       pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
+       pvr2_hdw_set_streaming(hdw,!0);
+       ret = pvr2_ioread_set_enabled(fh->rhp,!0);
+
+       return ret;
+}
+
+
+static ssize_t pvr2_v4l2_read(struct file *file,
+                             char __user *buff, size_t count, loff_t *ppos)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       int ret;
+
+       if (fh->fw_mode_flag) {
+               struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+               char *tbuf;
+               int c1,c2;
+               int tcnt = 0;
+               unsigned int offs = *ppos;
+
+               tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
+               if (!tbuf) return -ENOMEM;
+
+               while (count) {
+                       c1 = count;
+                       if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
+                       c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
+                       if (c2 < 0) {
+                               tcnt = c2;
+                               break;
+                       }
+                       if (!c2) break;
+                       if (copy_to_user(buff,tbuf,c2)) {
+                               tcnt = -EFAULT;
+                               break;
+                       }
+                       offs += c2;
+                       tcnt += c2;
+                       buff += c2;
+                       count -= c2;
+                       *ppos += c2;
+               }
+               kfree(tbuf);
+               return tcnt;
+       }
+
+       if (!fh->rhp) {
+               ret = pvr2_v4l2_iosetup(fh);
+               if (ret) {
+                       return ret;
+               }
+       }
+
+       for (;;) {
+               ret = pvr2_ioread_read(fh->rhp,buff,count);
+               if (ret >= 0) break;
+               if (ret != -EAGAIN) break;
+               if (file->f_flags & O_NONBLOCK) break;
+               /* Doing blocking I/O.  Wait here. */
+               ret = wait_event_interruptible(
+                       fh->wait_data,
+                       pvr2_ioread_avail(fh->rhp) >= 0);
+               if (ret < 0) break;
+       }
+
+       return ret;
+}
+
+
+static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
+{
+       unsigned int mask = 0;
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       int ret;
+
+       if (fh->fw_mode_flag) {
+               mask |= POLLIN | POLLRDNORM;
+               return mask;
+       }
+
+       if (!fh->rhp) {
+               ret = pvr2_v4l2_iosetup(fh);
+               if (ret) return POLLERR;
+       }
+
+       poll_wait(file,&fh->wait_data,wait);
+
+       if (pvr2_ioread_avail(fh->rhp) >= 0) {
+               mask |= POLLIN | POLLRDNORM;
+       }
+
+       return mask;
+}
+
+
+static struct file_operations vdev_fops = {
+       .owner      = THIS_MODULE,
+       .open       = pvr2_v4l2_open,
+       .release    = pvr2_v4l2_release,
+       .read       = pvr2_v4l2_read,
+       .ioctl      = pvr2_v4l2_ioctl,
+       .llseek     = no_llseek,
+       .poll       = pvr2_v4l2_poll,
+};
+
+
+#define VID_HARDWARE_PVRUSB2    38  /* FIXME : need a good value */
+
+static struct video_device vdev_template = {
+       .owner      = THIS_MODULE,
+       .type       = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
+       .type2      = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
+                      | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
+                      | V4L2_CAP_READWRITE),
+       .hardware   = VID_HARDWARE_PVRUSB2,
+       .fops       = &vdev_fops,
+};
+
+
+static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
+                              struct pvr2_v4l2 *vp,
+                              enum pvr2_config cfg)
+{
+       int mindevnum;
+       int unit_number;
+       int v4l_type;
+       dip->v4lp = vp;
+       dip->config = cfg;
+
+
+       switch (cfg) {
+       case pvr2_config_mpeg:
+               v4l_type = VFL_TYPE_GRABBER;
+               dip->stream = &vp->channel.mc_head->video_stream;
+               break;
+       case pvr2_config_vbi:
+               v4l_type = VFL_TYPE_VBI;
+               break;
+       case pvr2_config_radio:
+               v4l_type = VFL_TYPE_RADIO;
+               break;
+       default:
+               /* Bail out (this should be impossible) */
+               err("Failed to set up pvrusb2 v4l dev"
+                   " due to unrecognized config");
+               return;
+       }
+
+       if (!dip->stream) {
+               err("Failed to set up pvrusb2 v4l dev"
+                   " due to missing stream instance");
+               return;
+       }
+
+       dip->vdev = video_device_alloc();
+       if (!dip->vdev) {
+               err("Alloc of pvrusb2 v4l video device failed");
+               return;
+       }
+
+       memcpy(dip->vdev,&vdev_template,sizeof(vdev_template));
+       dip->vdev->release = video_device_release;
+       video_set_drvdata(dip->vdev,dip);
+
+       mindevnum = -1;
+       unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               mindevnum = video_nr[unit_number];
+       }
+       if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) &&
+           (video_register_device(dip->vdev, v4l_type, -1) < 0)) {
+               err("Failed to register pvrusb2 v4l video device");
+       } else {
+               printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
+                      dip->vdev->minor,pvr2_config_get_name(dip->config));
+       }
+
+
+       pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
+                                       dip->vdev->minor);
+}
+
+
+struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
+{
+       struct pvr2_v4l2 *vp;
+
+       vp = kmalloc(sizeof(*vp),GFP_KERNEL);
+       if (!vp) return vp;
+       memset(vp,0,sizeof(*vp));
+       pvr2_channel_init(&vp->channel,mnp);
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
+
+       vp->channel.check_func = pvr2_v4l2_internal_check;
+
+       /* register streams */
+       pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg);
+
+
+       return vp;
+}
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
new file mode 100644 (file)
index 0000000..9a995e2
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 __PVRUSB2_V4L2_H
+#define __PVRUSB2_V4L2_H
+
+#include "pvrusb2-context.h"
+
+struct pvr2_v4l2;
+
+struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *);
+
+#endif /* __PVRUSB2_V4L2_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
new file mode 100644 (file)
index 0000000..05f2cdd
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   saa711x support that is available in the v4l available starting
+   with linux 2.6.15.
+
+*/
+
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/saa7115.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct pvr2_v4l_decoder {
+       struct pvr2_i2c_handler handler;
+       struct pvr2_decoder_ctrl ctrl;
+       struct pvr2_i2c_client *client;
+       struct pvr2_hdw *hdw;
+       unsigned long stale_mask;
+};
+
+
+static void set_input(struct pvr2_v4l_decoder *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       struct v4l2_routing route;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
+       switch(hdw->input_val) {
+       case PVR2_CVAL_INPUT_TV:
+               route.input = SAA7115_COMPOSITE4;
+               break;
+       case PVR2_CVAL_INPUT_COMPOSITE:
+               route.input = SAA7115_COMPOSITE5;
+               break;
+       case PVR2_CVAL_INPUT_SVIDEO:
+               route.input = SAA7115_SVIDEO2;
+               break;
+       case PVR2_CVAL_INPUT_RADIO:
+               // ????? No idea yet what to do here
+       default:
+               return;
+       }
+       route.output = 0;
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
+}
+
+
+static int check_input(struct pvr2_v4l_decoder *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       return hdw->input_dirty != 0;
+}
+
+
+static void set_audio(struct pvr2_v4l_decoder *ctxt)
+{
+       u32 val;
+       struct pvr2_hdw *hdw = ctxt->hdw;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d",
+                  hdw->srate_val);
+       switch (hdw->srate_val) {
+       default:
+       case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+               val = 48000;
+               break;
+       case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+               val = 44100;
+               break;
+       case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+               val = 32000;
+               break;
+       }
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
+}
+
+
+static int check_audio(struct pvr2_v4l_decoder *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       return hdw->srate_dirty != 0;
+}
+
+
+struct pvr2_v4l_decoder_ops {
+       void (*update)(struct pvr2_v4l_decoder *);
+       int (*check)(struct pvr2_v4l_decoder *);
+};
+
+
+static const struct pvr2_v4l_decoder_ops decoder_ops[] = {
+       { .update = set_input, .check = check_input},
+       { .update = set_audio, .check = check_audio},
+};
+
+
+static void decoder_detach(struct pvr2_v4l_decoder *ctxt)
+{
+       ctxt->client->handler = NULL;
+       ctxt->hdw->decoder_ctrl = NULL;
+       kfree(ctxt);
+}
+
+
+static int decoder_check(struct pvr2_v4l_decoder *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (ctxt->stale_mask & msk) continue;
+               if (decoder_ops[idx].check(ctxt)) {
+                       ctxt->stale_mask |= msk;
+               }
+       }
+       return ctxt->stale_mask != 0;
+}
+
+
+static void decoder_update(struct pvr2_v4l_decoder *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (!(ctxt->stale_mask & msk)) continue;
+               ctxt->stale_mask &= ~msk;
+               decoder_ops[idx].update(ctxt);
+       }
+}
+
+
+static int decoder_detect(struct pvr2_i2c_client *cp)
+{
+       /* Attempt to query the decoder - let's see if it will answer */
+       struct v4l2_tuner vt;
+       int ret;
+
+       memset(&vt,0,sizeof(vt));
+       ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt);
+       return ret == 0; /* Return true if it answered */
+}
+
+
+static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl)
+{
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl);
+       pvr2_v4l2_cmd_stream(ctxt->client,fl);
+}
+
+
+static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt)
+{
+       struct v4l2_tuner vt;
+       int ret;
+
+       memset(&vt,0,sizeof(vt));
+       ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
+       if (ret < 0) return -EINVAL;
+       return vt.signal ? 1 : 0;
+}
+
+
+static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
+{
+       return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
+}
+
+
+const static struct pvr2_i2c_handler_functions hfuncs = {
+       .detach = (void (*)(void *))decoder_detach,
+       .check = (int (*)(void *))decoder_check,
+       .update = (void (*)(void *))decoder_update,
+       .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
+};
+
+
+int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw,
+                              struct pvr2_i2c_client *cp)
+{
+       struct pvr2_v4l_decoder *ctxt;
+
+       if (hdw->decoder_ctrl) return 0;
+       if (cp->handler) return 0;
+       if (!decoder_detect(cp)) return 0;
+
+       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       if (!ctxt) return 0;
+       memset(ctxt,0,sizeof(*ctxt));
+
+       ctxt->handler.func_data = ctxt;
+       ctxt->handler.func_table = &hfuncs;
+       ctxt->ctrl.ctxt = ctxt;
+       ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
+       ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
+       ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
+       ctxt->client = cp;
+       ctxt->hdw = hdw;
+       ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
+                                 sizeof(decoder_ops[0]))) - 1;
+       hdw->decoder_ctrl = &ctxt->ctrl;
+       cp->handler = &ctxt->handler;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
+                  cp->client->addr);
+       return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
new file mode 100644 (file)
index 0000000..2b917fd
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_VIDEO_V4L_H
+#define __PVRUSB2_VIDEO_V4L_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles device video processing.  This interface is
+   used internally by the driver; higher level code should only
+   interact through the interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+
+#endif /* __PVRUSB2_VIDEO_V4L_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
new file mode 100644 (file)
index 0000000..2413e51
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   wm8775.
+
+*/
+
+#include "pvrusb2-wm8775.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct pvr2_v4l_wm8775 {
+       struct pvr2_i2c_handler handler;
+       struct pvr2_i2c_client *client;
+       struct pvr2_hdw *hdw;
+       unsigned long stale_mask;
+};
+
+
+static void set_input(struct pvr2_v4l_wm8775 *ctxt)
+{
+       struct v4l2_routing route;
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       int msk = 0;
+
+       memset(&route,0,sizeof(route));
+
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)",
+                  hdw->input_val,msk);
+
+       // Always point to input #1 no matter what
+       route.input = 2;
+       pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
+}
+
+static int check_input(struct pvr2_v4l_wm8775 *ctxt)
+{
+       struct pvr2_hdw *hdw = ctxt->hdw;
+       return hdw->input_dirty != 0;
+}
+
+
+struct pvr2_v4l_wm8775_ops {
+       void (*update)(struct pvr2_v4l_wm8775 *);
+       int (*check)(struct pvr2_v4l_wm8775 *);
+};
+
+
+static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = {
+       { .update = set_input, .check = check_input},
+};
+
+
+static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt,
+                                    char *buf,unsigned int cnt)
+{
+       return scnprintf(buf,cnt,"handler: pvrusb2-wm8775");
+}
+
+
+static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt)
+{
+       ctxt->client->handler = NULL;
+       kfree(ctxt);
+}
+
+
+static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (ctxt->stale_mask & msk) continue;
+               if (wm8775_ops[idx].check(ctxt)) {
+                       ctxt->stale_mask |= msk;
+               }
+       }
+       return ctxt->stale_mask != 0;
+}
+
+
+static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt)
+{
+       unsigned long msk;
+       unsigned int idx;
+
+       for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
+            idx++) {
+               msk = 1 << idx;
+               if (!(ctxt->stale_mask & msk)) continue;
+               ctxt->stale_mask &= ~msk;
+               wm8775_ops[idx].update(ctxt);
+       }
+}
+
+
+const static struct pvr2_i2c_handler_functions hfuncs = {
+       .detach = (void (*)(void *))wm8775_detach,
+       .check = (int (*)(void *))wm8775_check,
+       .update = (void (*)(void *))wm8775_update,
+       .describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe,
+};
+
+
+int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+       struct pvr2_v4l_wm8775 *ctxt;
+
+       if (cp->handler) return 0;
+
+       ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+       if (!ctxt) return 0;
+       memset(ctxt,0,sizeof(*ctxt));
+
+       ctxt->handler.func_data = ctxt;
+       ctxt->handler.func_table = &hfuncs;
+       ctxt->client = cp;
+       ctxt->hdw = hdw;
+       ctxt->stale_mask = (1 << (sizeof(wm8775_ops)/
+                                 sizeof(wm8775_ops[0]))) - 1;
+       cp->handler = &ctxt->handler;
+       pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up",
+                  cp->client->addr);
+       return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
new file mode 100644 (file)
index 0000000..8aaeff4
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_WM8775_H
+#define __PVRUSB2_WM8775_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which performs analog -> digital audio conversion for
+   external audio inputs.  This interface is used internally by the
+   driver; higher level code should only interact through the
+   interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+
+#endif /* __PVRUSB2_WM8775_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h
new file mode 100644 (file)
index 0000000..074533e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_H
+#define __PVRUSB2_H
+
+/* Maximum number of pvrusb2 instances we can track at once.  You
+   might want to increase this - however the driver operation will not
+   be impaired if it is too small.  Instead additional units just
+   won't have an ID assigned and it might not be possible to specify
+   module paramters for those extra units. */
+#define PVR_NUM 20
+
+#endif /* __PVRUSB2_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
new file mode 100644 (file)
index 0000000..c29593f
--- /dev/null
@@ -0,0 +1,50 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 1
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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 "pwc-dec1.h"
+
+
+void pwc_dec1_init(int type, int release, void *buffer, void *table)
+{
+
+}
+
+void pwc_dec1_exit(void)
+{
+
+
+
+}
+
+int pwc_dec1_alloc(struct pwc_device *pwc)
+{
+       pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
+       if (pwc->decompress_data == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
new file mode 100644 (file)
index 0000000..8b62ddc
--- /dev/null
@@ -0,0 +1,43 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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 PWC_DEC1_H
+#define PWC_DEC1_H
+
+#include "pwc.h"
+
+struct pwc_dec1_private
+{
+       int version;
+
+};
+
+int  pwc_dec1_alloc(struct pwc_device *pwc);
+void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
+void pwc_dec1_exit(void);
+
+#endif
+
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
new file mode 100644 (file)
index 0000000..9e2d91f
--- /dev/null
@@ -0,0 +1,941 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 2 et 3
+   (C) 2004-2006  Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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 "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+#include <media/pwc-ioctl.h>
+
+#include <linux/string.h>
+
+/*
+ * USE_LOOKUP_TABLE_TO_CLAMP
+ *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
+ *   1: use a faster lookup table for cpu with a big cache (intel)
+ */
+#define USE_LOOKUP_TABLE_TO_CLAMP      1
+/*
+ * UNROLL_LOOP_FOR_COPYING_BLOCK
+ *   0: use a loop for a smaller code (but little slower)
+ *   1: when unrolling the loop, gcc produces some faster code (perhaps only
+ *   valid for intel processor class). Activating this option, automaticaly
+ *   activate USE_LOOKUP_TABLE_TO_CLAMP
+ */
+#define UNROLL_LOOP_FOR_COPY           1
+#if UNROLL_LOOP_FOR_COPY
+# undef USE_LOOKUP_TABLE_TO_CLAMP
+# define USE_LOOKUP_TABLE_TO_CLAMP 1
+#endif
+
+/*
+ * ENABLE_BAYER_DECODER
+ *   0: bayer decoder is not build (save some space)
+ *   1: bayer decoder is build and can be used
+ */
+#define ENABLE_BAYER_DECODER 0
+
+static void build_subblock_pattern(struct pwc_dec23_private *pdec)
+{
+       static const unsigned int initial_values[12] = {
+               -0x526500, -0x221200, 0x221200, 0x526500,
+                          -0x3de200, 0x3de200,
+               -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
+                          -0x12c200, 0x12c200
+
+       };
+       static const unsigned int values_derivated[12] = {
+               0xa4ca, 0x4424, -0x4424, -0xa4ca,
+                       0x7bc4, -0x7bc4,
+               0xdb69, 0x5aba, -0x5aba, -0xdb69,
+                       0x2584, -0x2584
+       };
+       unsigned int temp_values[12];
+       int i, j;
+
+       memcpy(temp_values, initial_values, sizeof(initial_values));
+       for (i = 0; i < 256; i++) {
+               for (j = 0; j < 12; j++) {
+                       pdec->table_subblock[i][j] = temp_values[j];
+                       temp_values[j] += values_derivated[j];
+               }
+       }
+}
+
+static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
+{
+       unsigned char *p;
+       unsigned int bit, byte, mask, val;
+       unsigned int bitpower = 1;
+
+       for (bit = 0; bit < 8; bit++) {
+               mask = bitpower - 1;
+               p = pdec->table_bitpowermask[bit];
+               for (byte = 0; byte < 256; byte++) {
+                       val = (byte & mask);
+                       if (byte & bitpower)
+                               val = -val;
+                       *p++ = val;
+               }
+               bitpower<<=1;
+       }
+}
+
+
+static void build_table_color(const unsigned int romtable[16][8],
+                             unsigned char p0004[16][1024],
+                             unsigned char p8004[16][256])
+{
+       int compression_mode, j, k, bit, pw;
+       unsigned char *p0, *p8;
+       const unsigned int *r;
+
+       /* We have 16 compressions tables */
+       for (compression_mode = 0; compression_mode < 16; compression_mode++) {
+               p0 = p0004[compression_mode];
+               p8 = p8004[compression_mode];
+               r  = romtable[compression_mode];
+
+               for (j = 0; j < 8; j++, r++, p0 += 128) {
+
+                       for (k = 0; k < 16; k++) {
+                               if (k == 0)
+                                       bit = 1;
+                               else if (k >= 1 && k < 3)
+                                       bit = (r[0] >> 15) & 7;
+                               else if (k >= 3 && k < 6)
+                                       bit = (r[0] >> 12) & 7;
+                               else if (k >= 6 && k < 10)
+                                       bit = (r[0] >> 9) & 7;
+                               else if (k >= 10 && k < 13)
+                                       bit = (r[0] >> 6) & 7;
+                               else if (k >= 13 && k < 15)
+                                       bit = (r[0] >> 3) & 7;
+                               else
+                                       bit = (r[0]) & 7;
+                               if (k == 0)
+                                       *p8++ = 8;
+                               else
+                                       *p8++ = j - bit;
+                               *p8++ = bit;
+
+                               pw = 1 << bit;
+                               p0[k + 0x00] = (1 * pw) + 0x80;
+                               p0[k + 0x10] = (2 * pw) + 0x80;
+                               p0[k + 0x20] = (3 * pw) + 0x80;
+                               p0[k + 0x30] = (4 * pw) + 0x80;
+                               p0[k + 0x40] = (-1 * pw) + 0x80;
+                               p0[k + 0x50] = (-2 * pw) + 0x80;
+                               p0[k + 0x60] = (-3 * pw) + 0x80;
+                               p0[k + 0x70] = (-4 * pw) + 0x80;
+                       }       /* end of for (k=0; k<16; k++, p8++) */
+               }       /* end of for (j=0; j<8; j++ , table++) */
+       } /* end of foreach compression_mode */
+}
+
+/*
+ *
+ */
+static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
+{
+#define SCALEBITS 15
+#define ONE_HALF  (1UL << (SCALEBITS - 1))
+       int i;
+       unsigned int offset1 = ONE_HALF;
+       unsigned int offset2 = 0x0000;
+
+       for (i=0; i<256; i++) {
+               pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
+               pdec->table_d800[i] = offset2;
+
+               offset1 += 0x7bc4;
+               offset2 += 0x7bc4;
+       }
+}
+
+/*
+ * To decode the stream:
+ *   if look_bits(2) == 0:     # op == 2 in the lookup table
+ *      skip_bits(2)
+ *      end of the stream
+ *   elif look_bits(3) == 7:   # op == 1 in the lookup table
+ *      skip_bits(3)
+ *      yyyy = get_bits(4)
+ *      xxxx = get_bits(8)
+ *   else:                     # op == 0 in the lookup table
+ *      skip_bits(x)
+ *
+ * For speedup processing, we build a lookup table and we takes the first 6 bits.
+ *
+ * struct {
+ *   unsigned char op;     // operation to execute
+ *   unsigned char bits;    // bits use to perform operation
+ *   unsigned char offset1; // offset to add to access in the table_0004 % 16
+ *   unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ * How to build this table ?
+ *   op == 2 when (i%4)==0
+ *   op == 1 when (i%8)==7
+ *   op == 0 otherwise
+ *
+ */
+static const unsigned char hash_table_ops[64*4] = {
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x01, 0x30,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x20,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x00,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x02, 0x10,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x60,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x40,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x40,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x01, 0x70,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x20,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x00,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x02, 0x50,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x60,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x40,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x40,
+       0x01, 0x00, 0x00, 0x00
+};
+
+/*
+ *
+ */
+static const unsigned int MulIdx[16][16] = {
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+       {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
+       {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
+       {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
+       {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
+       {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
+       {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
+       {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
+       {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
+       {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
+       {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
+       {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
+       {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
+       {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
+       {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
+       {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
+};
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+#define MAX_OUTER_CROP_VALUE   (512)
+static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
+#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
+#else
+#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#endif
+
+
+/* If the type or the command change, we rebuild the lookup table */
+int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
+{
+       int flags, version, shift, i;
+       struct pwc_dec23_private *pdec;
+
+       if (pwc->decompress_data == NULL) {
+               pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+               if (pdec == NULL)
+                       return -ENOMEM;
+               pwc->decompress_data = pdec;
+       }
+       pdec = pwc->decompress_data;
+
+       if (DEVICE_USE_CODEC3(type)) {
+               flags = cmd[2] & 0x18;
+               if (flags == 8)
+                       pdec->nbits = 7;        /* More bits, mean more bits to encode the stream, but better quality */
+               else if (flags == 0x10)
+                       pdec->nbits = 8;
+               else
+                       pdec->nbits = 6;
+
+               version = cmd[2] >> 5;
+               build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+               build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+
+       } else {
+
+               flags = cmd[2] & 6;
+               if (flags == 2)
+                       pdec->nbits = 7;
+               else if (flags == 4)
+                       pdec->nbits = 8;
+               else
+                       pdec->nbits = 6;
+
+               version = cmd[2] >> 3;
+               build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+               build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+       }
+
+       /* Informations can be coded on a variable number of bits but never less than 8 */
+       shift = 8 - pdec->nbits;
+       pdec->scalebits = SCALEBITS - shift;
+       pdec->nbitsmask = 0xFF >> shift;
+
+       fill_table_dc00_d800(pdec);
+       build_subblock_pattern(pdec);
+       build_bit_powermask_table(pdec);
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+       /* Build the static table to clamp value [0-255] */
+       for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
+               pwc_crop_table[i] = 0;
+       for (i=0; i<256; i++)
+               pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
+       for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
+               pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
+#endif
+
+       return 0;
+}
+
+/*
+ * Copy the 4x4 image block to Y plane buffer
+ */
+static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       const int *c = src;
+       unsigned char *d = dst;
+
+       *d++ = cm[c[0] >> scalebits];
+       *d++ = cm[c[1] >> scalebits];
+       *d++ = cm[c[2] >> scalebits];
+       *d++ = cm[c[3] >> scalebits];
+
+       d = dst + bytes_per_line;
+       *d++ = cm[c[4] >> scalebits];
+       *d++ = cm[c[5] >> scalebits];
+       *d++ = cm[c[6] >> scalebits];
+       *d++ = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line*2;
+       *d++ = cm[c[8] >> scalebits];
+       *d++ = cm[c[9] >> scalebits];
+       *d++ = cm[c[10] >> scalebits];
+       *d++ = cm[c[11] >> scalebits];
+
+       d = dst + bytes_per_line*3;
+       *d++ = cm[c[12] >> scalebits];
+       *d++ = cm[c[13] >> scalebits];
+       *d++ = cm[c[14] >> scalebits];
+       *d++ = cm[c[15] >> scalebits];
+#else
+       int i;
+       const int *c = src;
+       unsigned char *d = dst;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*2;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*3;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+#endif
+}
+
+/*
+ * Copy the 4x4 image block to a CrCb plane buffer
+ *
+ */
+static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       const int *c = src;
+       unsigned char *d = dst;
+
+       *d++ = cm[c[0] >> scalebits];
+       *d++ = cm[c[4] >> scalebits];
+       *d++ = cm[c[1] >> scalebits];
+       *d++ = cm[c[5] >> scalebits];
+       *d++ = cm[c[2] >> scalebits];
+       *d++ = cm[c[6] >> scalebits];
+       *d++ = cm[c[3] >> scalebits];
+       *d++ = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line;
+       *d++ = cm[c[12] >> scalebits];
+       *d++ = cm[c[8] >> scalebits];
+       *d++ = cm[c[13] >> scalebits];
+       *d++ = cm[c[9] >> scalebits];
+       *d++ = cm[c[14] >> scalebits];
+       *d++ = cm[c[10] >> scalebits];
+       *d++ = cm[c[15] >> scalebits];
+       *d++ = cm[c[11] >> scalebits];
+#else
+       int i;
+       const int *c1 = src;
+       const int *c2 = src + 4;
+       unsigned char *d = dst;
+
+       for (i = 0; i < 4; i++, c1++, c2++) {
+               *d++ = CLAMP((*c1) >> scalebits);
+               *d++ = CLAMP((*c2) >> scalebits);
+       }
+       c1 = src + 12;
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c1++, c2++) {
+               *d++ = CLAMP((*c1) >> scalebits);
+               *d++ = CLAMP((*c2) >> scalebits);
+       }
+#endif
+}
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Format: 8x2 pixels
+ *   . G . G . G . G . G . G . G
+ *   . . . . . . . . . . . . . .
+ *   . G . G . G . G . G . G . G
+ *   . . . . . . . . . . . . . .
+ *   or
+ *   . . . . . . . . . . . . . .
+ *   G . G . G . G . G . G . G .
+ *   . . . . . . . . . . . . . .
+ *   G . G . G . G . G . G . G .
+*/
+static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       unsigned char *d = dst;
+       const int *c = src;
+
+       d[0] = cm[c[0] >> scalebits];
+       d[2] = cm[c[1] >> scalebits];
+       d[4] = cm[c[2] >> scalebits];
+       d[6] = cm[c[3] >> scalebits];
+       d[8] = cm[c[4] >> scalebits];
+       d[10] = cm[c[5] >> scalebits];
+       d[12] = cm[c[6] >> scalebits];
+       d[14] = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line;
+       d[0] = cm[c[8] >> scalebits];
+       d[2] = cm[c[9] >> scalebits];
+       d[4] = cm[c[10] >> scalebits];
+       d[6] = cm[c[11] >> scalebits];
+       d[8] = cm[c[12] >> scalebits];
+       d[10] = cm[c[13] >> scalebits];
+       d[12] = cm[c[14] >> scalebits];
+       d[14] = cm[c[15] >> scalebits];
+#else
+       int i;
+       unsigned char *d;
+       const int *c = src;
+
+       d = dst;
+       for (i = 0; i < 8; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 8; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+#endif
+}
+#endif
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Format: 4x4 pixels
+ *   R . R . R . R
+ *   . B . B . B .
+ *   R . R . R . R
+ *   . B . B . B .
+ */
+static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       unsigned char *d = dst;
+       const int *c = src;
+
+       d[0] = cm[c[0] >> scalebits];
+       d[2] = cm[c[1] >> scalebits];
+       d[4] = cm[c[2] >> scalebits];
+       d[6] = cm[c[3] >> scalebits];
+
+       d = dst + bytes_per_line;
+       d[1] = cm[c[4] >> scalebits];
+       d[3] = cm[c[5] >> scalebits];
+       d[5] = cm[c[6] >> scalebits];
+       d[7] = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line*2;
+       d[0] = cm[c[8] >> scalebits];
+       d[2] = cm[c[9] >> scalebits];
+       d[4] = cm[c[10] >> scalebits];
+       d[6] = cm[c[11] >> scalebits];
+
+       d = dst + bytes_per_line*3;
+       d[1] = cm[c[12] >> scalebits];
+       d[3] = cm[c[13] >> scalebits];
+       d[5] = cm[c[14] >> scalebits];
+       d[7] = cm[c[15] >> scalebits];
+#else
+       int i;
+       unsigned char *d;
+       const int *c = src;
+
+       d = dst;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2+1] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*2;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*3;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2+1] = CLAMP((*c) >> scalebits);
+#endif
+}
+#endif
+
+/*
+ * To manage the stream, we keep bits in a 32 bits register.
+ * fill_nbits(n): fill the reservoir with at least n bits
+ * skip_bits(n): discard n bits from the reservoir
+ * get_bits(n): fill the reservoir, returns the first n bits and discard the
+ *              bits from the reservoir.
+ * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
+ *                 contains at least n bits. bits returned is discarded.
+ */
+#define fill_nbits(pdec, nbits_wanted) do { \
+   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
+    { \
+      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
+      pdec->nbits_in_reservoir += 8; \
+    } \
+}  while(0);
+
+#define skip_nbits(pdec, nbits_to_skip) do { \
+   pdec->reservoir >>= (nbits_to_skip); \
+   pdec->nbits_in_reservoir -= (nbits_to_skip); \
+}  while(0);
+
+#define get_nbits(pdec, nbits_wanted, result) do { \
+   fill_nbits(pdec, nbits_wanted); \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define __get_nbits(pdec, nbits_wanted, result) do { \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define look_nbits(pdec, nbits_wanted) \
+   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
+
+/*
+ * Decode a 4x4 pixel block
+ */
+static void decode_block(struct pwc_dec23_private *pdec,
+                        const unsigned char *ptable0004,
+                        const unsigned char *ptable8004)
+{
+       unsigned int primary_color;
+       unsigned int channel_v, offset1, op;
+       int i;
+
+       fill_nbits(pdec, 16);
+       __get_nbits(pdec, pdec->nbits, primary_color);
+
+       if (look_nbits(pdec,2) == 0) {
+               skip_nbits(pdec, 2);
+               /* Very simple, the color is the same for all pixels of the square */
+               for (i = 0; i < 16; i++)
+                       pdec->temp_colors[i] = pdec->table_dc00[primary_color];
+
+               return;
+       }
+
+       /* This block is encoded with small pattern */
+       for (i = 0; i < 16; i++)
+               pdec->temp_colors[i] = pdec->table_d800[primary_color];
+
+       __get_nbits(pdec, 3, channel_v);
+       channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
+
+       ptable0004 += (channel_v * 128);
+       ptable8004 += (channel_v * 32);
+
+       offset1 = 0;
+       do
+       {
+               unsigned int htable_idx, rows = 0;
+               const unsigned int *block;
+
+               /* [  zzzz y x x ]
+                *     xx == 00 :=> end of the block def, remove the two bits from the stream
+                *    yxx == 111
+                *    yxx == any other value
+                *
+                */
+               fill_nbits(pdec, 16);
+               htable_idx = look_nbits(pdec, 6);
+               op = hash_table_ops[htable_idx * 4];
+
+               if (op == 2) {
+                       skip_nbits(pdec, 2);
+
+               } else if (op == 1) {
+                       /* 15bits [ xxxx xxxx yyyy 111 ]
+                        * yyy => offset in the table8004
+                        * xxx => offset in the tabled004 (tree)
+                        */
+                       unsigned int mask, shift;
+                       unsigned int nbits, col1;
+                       unsigned int yyyy;
+
+                       skip_nbits(pdec, 3);
+                       /* offset1 += yyyy */
+                       __get_nbits(pdec, 4, yyyy);
+                       offset1 += 1 + yyyy;
+                       offset1 &= 0x0F;
+                       nbits = ptable8004[offset1 * 2];
+
+                       /* col1 = xxxx xxxx */
+                       __get_nbits(pdec, nbits+1, col1);
+
+                       /* Bit mask table */
+                       mask = pdec->table_bitpowermask[nbits][col1];
+                       shift = ptable8004[offset1 * 2 + 1];
+                       rows = ((mask << shift) + 0x80) & 0xFF;
+
+                       block = pdec->table_subblock[rows];
+                       for (i = 0; i < 16; i++)
+                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+               } else {
+                       /* op == 0
+                        * offset1 is coded on 3 bits
+                        */
+                       unsigned int shift;
+
+                       offset1 += hash_table_ops [htable_idx * 4 + 2];
+                       offset1 &= 0x0F;
+
+                       rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
+                       block = pdec->table_subblock[rows];
+                       for (i = 0; i < 16; i++)
+                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+                       shift = hash_table_ops[htable_idx * 4 + 1];
+                       skip_nbits(pdec, shift);
+               }
+
+       } while (op != 2);
+
+}
+
+static void DecompressBand23(struct pwc_dec23_private *pdec,
+                            const unsigned char *rawyuv,
+                            unsigned char *planar_y,
+                            unsigned char *planar_u,
+                            unsigned char *planar_v,
+                            unsigned int   compressed_image_width,
+                            unsigned int   real_image_width)
+{
+       int compression_index, nblocks;
+       const unsigned char *ptable0004;
+       const unsigned char *ptable8004;
+
+       pdec->reservoir = 0;
+       pdec->nbits_in_reservoir = 0;
+       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
+
+       get_nbits(pdec, 4, compression_index);
+
+       /* pass 1: uncompress Y component */
+       nblocks = compressed_image_width / 4;
+
+       ptable0004 = pdec->table_0004_pass1[compression_index];
+       ptable8004 = pdec->table_8004_pass1[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
+               planar_y += 4;
+               nblocks--;
+       }
+
+       /* pass 2: uncompress UV component */
+       nblocks = compressed_image_width / 8;
+
+       ptable0004 = pdec->table_0004_pass2[compression_index];
+       ptable8004 = pdec->table_8004_pass2[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
+
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
+
+               planar_v += 8;
+               planar_u += 8;
+               nblocks -= 2;
+       }
+
+}
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Size need to be a multiple of 8 in width
+ *
+ * Return a block of four line encoded like this:
+ *
+ *   G R G R G R G R G R G R G R G R
+ *   B G B G B G B G B G B G B G B G
+ *   G R G R G R G R G R G R G R G R
+ *   B G B G B G B G B G B G B G B G
+ *
+ */
+static void DecompressBandBayer(struct pwc_dec23_private *pdec,
+                               const unsigned char *rawyuv,
+                               unsigned char *rgbbayer,
+                               unsigned int   compressed_image_width,
+                               unsigned int   real_image_width)
+{
+       int compression_index, nblocks;
+       const unsigned char *ptable0004;
+       const unsigned char *ptable8004;
+       unsigned char *dest;
+
+       pdec->reservoir = 0;
+       pdec->nbits_in_reservoir = 0;
+       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
+
+       get_nbits(pdec, 4, compression_index);
+
+       /* pass 1: uncompress RB component */
+       nblocks = compressed_image_width / 4;
+
+       ptable0004 = pdec->table_0004_pass1[compression_index];
+       ptable8004 = pdec->table_8004_pass1[compression_index];
+       dest = rgbbayer;
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits);
+               dest += 8;
+               nblocks--;
+       }
+
+       /* pass 2: uncompress G component */
+       nblocks = compressed_image_width / 8;
+
+       ptable0004 = pdec->table_0004_pass2[compression_index];
+       ptable8004 = pdec->table_8004_pass2[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits);
+
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits);
+
+               rgbbayer += 16;
+               nblocks -= 2;
+       }
+}
+#endif
+
+
+/**
+ *
+ * Uncompress a pwc23 buffer.
+ *
+ * pwc.view: size of the image wanted
+ * pwc.image: size of the image returned by the camera
+ * pwc.offset: (x,y) to displayer image in the view
+ *
+ * src: raw data
+ * dst: image output
+ * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER
+ */
+void pwc_dec23_decompress(const struct pwc_device *pwc,
+                         const void *src,
+                         void *dst,
+                         int flags)
+{
+       int bandlines_left, stride, bytes_per_block;
+
+       bandlines_left = pwc->image.y / 4;
+       bytes_per_block = pwc->view.x * 4;
+
+       if (flags & PWCX_FLAG_BAYER) {
+#if ENABLE_BAYER_DECODER
+               /* RGB Bayer format */
+               unsigned char *rgbout;
+
+               stride = pwc->view.x * pwc->offset.y;
+               rgbout = dst + stride + pwc->offset.x;
+
+
+               while (bandlines_left--) {
+
+                       DecompressBandBayer(pwc->decompress_data,
+                                           src,
+                                           rgbout,
+                                           pwc->image.x, pwc->view.x);
+
+                       src += pwc->vbandlength;
+                       rgbout += bytes_per_block;
+
+               }
+#else
+               memset(dst, 0, pwc->view.x * pwc->view.y);
+#endif
+
+       } else {
+               /* YUV420P image format */
+               unsigned char *pout_planar_y;
+               unsigned char *pout_planar_u;
+               unsigned char *pout_planar_v;
+               unsigned int   plane_size;
+
+               plane_size = pwc->view.x * pwc->view.y;
+
+               /* offset in Y plane */
+               stride = pwc->view.x * pwc->offset.y;
+               pout_planar_y = dst + stride + pwc->offset.x;
+
+               /* offsets in U/V planes */
+               stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
+               pout_planar_u = dst + plane_size + stride;
+               pout_planar_v = dst + plane_size + plane_size / 4 + stride;
+
+               while (bandlines_left--) {
+
+                       DecompressBand23(pwc->decompress_data,
+                                        src,
+                                        pout_planar_y, pout_planar_u, pout_planar_v,
+                                        pwc->image.x, pwc->view.x);
+                       src += pwc->vbandlength;
+                       pout_planar_y += bytes_per_block;
+                       pout_planar_u += pwc->view.x;
+                       pout_planar_v += pwc->view.x;
+
+               }
+
+       }
+
+}
+
+void pwc_dec23_exit(void)
+{
+       /* Do nothing */
+
+}
+
+/**
+ * Allocate a private structure used by lookup table.
+ * You must call kfree() to free the memory allocated.
+ */
+int pwc_dec23_alloc(struct pwc_device *pwc)
+{
+       pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+       if (pwc->decompress_data == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
new file mode 100644 (file)
index 0000000..1c55298
--- /dev/null
@@ -0,0 +1,67 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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 PWC_DEC23_H
+#define PWC_DEC23_H
+
+#include "pwc.h"
+
+struct pwc_dec23_private
+{
+  unsigned int scalebits;
+  unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
+
+  unsigned int reservoir;
+  unsigned int nbits_in_reservoir;
+  const unsigned char *stream;
+  int temp_colors[16];
+
+  unsigned char table_0004_pass1[16][1024];
+  unsigned char table_0004_pass2[16][1024];
+  unsigned char table_8004_pass1[16][256];
+  unsigned char table_8004_pass2[16][256];
+  unsigned int  table_subblock[256][12];
+
+  unsigned char table_bitpowermask[8][256];
+  unsigned int  table_d800[256];
+  unsigned int  table_dc00[256];
+
+};
+
+
+int pwc_dec23_alloc(struct pwc_device *pwc);
+int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
+void pwc_dec23_exit(void);
+void pwc_dec23_decompress(const struct pwc_device *pwc,
+                         const void *src,
+                         void *dst,
+                         int flags);
+
+
+
+#endif
+
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
+
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
new file mode 100644 (file)
index 0000000..b7eb3ce
--- /dev/null
@@ -0,0 +1,1202 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU 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/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+
+static struct v4l2_queryctrl pwc_controls[] = {
+       {
+           .id      = V4L2_CID_BRIGHTNESS,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Brightness",
+           .minimum = 0,
+           .maximum = 128,
+           .step    = 1,
+           .default_value = 64,
+       },
+       {
+           .id      = V4L2_CID_CONTRAST,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Contrast",
+           .minimum = 0,
+           .maximum = 64,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_SATURATION,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Saturation",
+           .minimum = -100,
+           .maximum = 100,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_GAMMA,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Gamma",
+           .minimum = 0,
+           .maximum = 32,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_RED_BALANCE,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Red Gain",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_BLUE_BALANCE,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Blue Gain",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_AUTO_WHITE_BALANCE,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Auto White Balance",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_EXPOSURE,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Shutter Speed (Exposure)",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 200,
+       },
+       {
+           .id      = V4L2_CID_AUTOGAIN,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Auto Gain Enabled",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 1,
+       },
+       {
+           .id      = V4L2_CID_GAIN,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Gain Level",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_SAVE_USER,
+           .type    = V4L2_CTRL_TYPE_BUTTON,
+           .name    = "Save User Settings",
+           .minimum = 0,
+           .maximum = 0,
+           .step    = 0,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_RESTORE_USER,
+           .type    = V4L2_CTRL_TYPE_BUTTON,
+           .name    = "Restore User Settings",
+           .minimum = 0,
+           .maximum = 0,
+           .step    = 0,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_RESTORE_FACTORY,
+           .type    = V4L2_CTRL_TYPE_BUTTON,
+           .name    = "Restore Factory Settings",
+           .minimum = 0,
+           .maximum = 0,
+           .step    = 0,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_COLOUR_MODE,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Colour mode",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_AUTOCONTOUR,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Auto contour",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_CONTOUR,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Contour",
+           .minimum = 0,
+           .maximum = 63,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_BACKLIGHT,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Backlight compensation",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+         .id      = V4L2_CID_PRIVATE_FLICKERLESS,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Flickerless",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_NOISE_REDUCTION,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Noise reduction",
+           .minimum = 0,
+           .maximum = 3,
+           .step    = 1,
+           .default_value = 0,
+       },
+};
+
+
+static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
+{
+       memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+       f->fmt.pix.width        = pdev->view.x;
+       f->fmt.pix.height       = pdev->view.y;
+       f->fmt.pix.field        = V4L2_FIELD_NONE;
+       if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;
+               f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
+               f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       } else {
+               /* vbandlength contains 4 lines ...  */
+               f->fmt.pix.bytesperline = pdev->vbandlength/4;
+               f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
+               if (DEVICE_USE_CODEC1(pdev->type))
+                       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC1;
+               else
+                       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC2;
+       }
+       PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
+                       "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
+                       f->fmt.pix.width,
+                       f->fmt.pix.height,
+                       f->fmt.pix.bytesperline,
+                       f->fmt.pix.sizeimage,
+                       (f->fmt.pix.pixelformat)&255,
+                       (f->fmt.pix.pixelformat>>8)&255,
+                       (f->fmt.pix.pixelformat>>16)&255,
+                       (f->fmt.pix.pixelformat>>24)&255);
+}
+
+/* ioctl(VIDIOC_TRY_FMT) */
+static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+               return -EINVAL;
+       }
+
+       switch (f->fmt.pix.pixelformat) {
+               case V4L2_PIX_FMT_YUV420:
+                       break;
+               case V4L2_PIX_FMT_PWC1:
+                       if (DEVICE_USE_CODEC23(pdev->type)) {
+                               PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
+                               return -EINVAL;
+                       }
+                       break;
+               case V4L2_PIX_FMT_PWC2:
+                       if (DEVICE_USE_CODEC1(pdev->type)) {
+                               PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       PWC_DEBUG_IOCTL("Unsupported pixel format\n");
+                       return -EINVAL;
+
+       }
+
+       if (f->fmt.pix.width > pdev->view_max.x)
+               f->fmt.pix.width = pdev->view_max.x;
+       else if (f->fmt.pix.width < pdev->view_min.x)
+               f->fmt.pix.width = pdev->view_min.x;
+
+       if (f->fmt.pix.height > pdev->view_max.y)
+               f->fmt.pix.height = pdev->view_max.y;
+       else if (f->fmt.pix.height < pdev->view_min.y)
+               f->fmt.pix.height = pdev->view_min.y;
+
+       return 0;
+}
+
+/* ioctl(VIDIOC_SET_FMT) */
+static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+       int ret, fps, snapshot, compression, pixelformat;
+
+       ret = pwc_vidioc_try_fmt(pdev, f);
+       if (ret<0)
+               return ret;
+
+       pixelformat = f->fmt.pix.pixelformat;
+       compression = pdev->vcompression;
+       snapshot = 0;
+       fps = pdev->vframes;
+       if (f->fmt.pix.priv) {
+               compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
+               snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);
+               fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+               if (fps == 0)
+                       fps = pdev->vframes;
+       }
+
+       if (pixelformat == V4L2_PIX_FMT_YUV420)
+               pdev->vpalette = VIDEO_PALETTE_YUV420P;
+       else
+               pdev->vpalette = VIDEO_PALETTE_RAW;
+
+       PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
+                       "compression=%d snapshot=%d format=%c%c%c%c\n",
+                       f->fmt.pix.width, f->fmt.pix.height, fps,
+                       compression, snapshot,
+                       (pixelformat)&255,
+                       (pixelformat>>8)&255,
+                       (pixelformat>>16)&255,
+                       (pixelformat>>24)&255);
+
+       ret = pwc_try_video_mode(pdev,
+                                f->fmt.pix.width,
+                                f->fmt.pix.height,
+                                fps,
+                                compression,
+                                snapshot);
+
+       PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);
+
+       if (ret)
+               return ret;
+
+       pwc_vidioc_fill_fmt(pdev, f);
+
+       return 0;
+
+}
+
+int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, void *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct pwc_device *pdev;
+       DECLARE_WAITQUEUE(wait, current);
+
+       if (vdev == NULL)
+               return -EFAULT;
+       pdev = vdev->priv;
+       if (pdev == NULL)
+               return -EFAULT;
+
+#if CONFIG_PWC_DEBUG
+       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
+               v4l_printk_ioctl(cmd);
+#endif
+
+
+       switch (cmd) {
+               /* Query cabapilities */
+               case VIDIOCGCAP:
+               {
+                       struct video_capability *caps = arg;
+
+                       strcpy(caps->name, vdev->name);
+                       caps->type = VID_TYPE_CAPTURE;
+                       caps->channels = 1;
+                       caps->audios = 1;
+                       caps->minwidth  = pdev->view_min.x;
+                       caps->minheight = pdev->view_min.y;
+                       caps->maxwidth  = pdev->view_max.x;
+                       caps->maxheight = pdev->view_max.y;
+                       break;
+               }
+
+               /* Channel functions (simulate 1 channel) */
+               case VIDIOCGCHAN:
+               {
+                       struct video_channel *v = arg;
+
+                       if (v->channel != 0)
+                               return -EINVAL;
+                       v->flags = 0;
+                       v->tuners = 0;
+                       v->type = VIDEO_TYPE_CAMERA;
+                       strcpy(v->name, "Webcam");
+                       return 0;
+               }
+
+               case VIDIOCSCHAN:
+               {
+                       /* The spec says the argument is an integer, but
+                          the bttv driver uses a video_channel arg, which
+                          makes sense becasue it also has the norm flag.
+                        */
+                       struct video_channel *v = arg;
+                       if (v->channel != 0)
+                               return -EINVAL;
+                       return 0;
+               }
+
+
+               /* Picture functions; contrast etc. */
+               case VIDIOCGPICT:
+               {
+                       struct video_picture *p = arg;
+                       int val;
+
+                       val = pwc_get_brightness(pdev);
+                       if (val >= 0)
+                               p->brightness = (val<<9);
+                       else
+                               p->brightness = 0xffff;
+                       val = pwc_get_contrast(pdev);
+                       if (val >= 0)
+                               p->contrast = (val<<10);
+                       else
+                               p->contrast = 0xffff;
+                       /* Gamma, Whiteness, what's the difference? :) */
+                       val = pwc_get_gamma(pdev);
+                       if (val >= 0)
+                               p->whiteness = (val<<11);
+                       else
+                               p->whiteness = 0xffff;
+                       if (pwc_get_saturation(pdev, &val)<0)
+                               p->colour = 0xffff;
+                       else
+                               p->colour = 32768 + val * 327;
+                       p->depth = 24;
+                       p->palette = pdev->vpalette;
+                       p->hue = 0xFFFF; /* N/A */
+                       break;
+               }
+
+               case VIDIOCSPICT:
+               {
+                       struct video_picture *p = arg;
+                       /*
+                        *      FIXME:  Suppose we are mid read
+                               ANSWER: No problem: the firmware of the camera
+                                       can handle brightness/contrast/etc
+                                       changes at _any_ time, and the palette
+                                       is used exactly once in the uncompress
+                                       routine.
+                        */
+                       pwc_set_brightness(pdev, p->brightness);
+                       pwc_set_contrast(pdev, p->contrast);
+                       pwc_set_gamma(pdev, p->whiteness);
+                       pwc_set_saturation(pdev, (p->colour-32768)/327);
+                       if (p->palette && p->palette != pdev->vpalette) {
+                               switch (p->palette) {
+                                       case VIDEO_PALETTE_YUV420P:
+                                       case VIDEO_PALETTE_RAW:
+                                               pdev->vpalette = p->palette;
+                                               return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+                                               break;
+                                       default:
+                                               return -EINVAL;
+                                               break;
+                               }
+                       }
+                       break;
+               }
+
+               /* Window/size parameters */
+               case VIDIOCGWIN:
+               {
+                       struct video_window *vw = arg;
+
+                       vw->x = 0;
+                       vw->y = 0;
+                       vw->width = pdev->view.x;
+                       vw->height = pdev->view.y;
+                       vw->chromakey = 0;
+                       vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
+                                  (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+                       break;
+               }
+
+               case VIDIOCSWIN:
+               {
+                       struct video_window *vw = arg;
+                       int fps, snapshot, ret;
+
+                       fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+                       snapshot = vw->flags & PWC_FPS_SNAPSHOT;
+                       if (fps == 0)
+                               fps = pdev->vframes;
+                       if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+                               return 0;
+                       ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
+                       if (ret)
+                               return ret;
+                       break;
+               }
+
+               /* We don't have overlay support (yet) */
+               case VIDIOCGFBUF:
+               {
+                       struct video_buffer *vb = arg;
+
+                       memset(vb,0,sizeof(*vb));
+                       break;
+               }
+
+               /* mmap() functions */
+               case VIDIOCGMBUF:
+               {
+                       /* Tell the user program how much memory is needed for a mmap() */
+                       struct video_mbuf *vm = arg;
+                       int i;
+
+                       memset(vm, 0, sizeof(*vm));
+                       vm->size = pwc_mbufs * pdev->len_per_image;
+                       vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */
+                       for (i = 0; i < pwc_mbufs; i++)
+                               vm->offsets[i] = i * pdev->len_per_image;
+                       break;
+               }
+
+               case VIDIOCMCAPTURE:
+               {
+                       /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+                       struct video_mmap *vm = arg;
+
+                       PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
+                       if (vm->frame < 0 || vm->frame >= pwc_mbufs)
+                               return -EINVAL;
+
+                       /* xawtv is nasty. It probes the available palettes
+                          by setting a very small image size and trying
+                          various palettes... The driver doesn't support
+                          such small images, so I'm working around it.
+                        */
+                       if (vm->format)
+                       {
+                               switch (vm->format)
+                               {
+                                       case VIDEO_PALETTE_YUV420P:
+                                       case VIDEO_PALETTE_RAW:
+                                               break;
+                                       default:
+                                               return -EINVAL;
+                                               break;
+                               }
+                       }
+
+                       if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
+                           (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
+                               int ret;
+
+                               PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+                               ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+                               if (ret)
+                                       return ret;
+                       } /* ... size mismatch */
+
+                       /* FIXME: should we lock here? */
+                       if (pdev->image_used[vm->frame])
+                               return -EBUSY;  /* buffer wasn't available. Bummer */
+                       pdev->image_used[vm->frame] = 1;
+
+                       /* Okay, we're done here. In the SYNC call we wait until a
+                          frame comes available, then expand image into the given
+                          buffer.
+                          In contrast to the CPiA cam the Philips cams deliver a
+                          constant stream, almost like a grabber card. Also,
+                          we have separate buffers for the rawdata and the image,
+                          meaning we can nearly always expand into the requested buffer.
+                        */
+                       PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n");
+                       break;
+               }
+
+               case VIDIOCSYNC:
+               {
+                       /* The doc says: "Whenever a buffer is used it should
+                          call VIDIOCSYNC to free this frame up and continue."
+
+                          The only odd thing about this whole procedure is
+                          that MCAPTURE flags the buffer as "in use", and
+                          SYNC immediately unmarks it, while it isn't
+                          after SYNC that you know that the buffer actually
+                          got filled! So you better not start a CAPTURE in
+                          the same frame immediately (use double buffering).
+                          This is not a problem for this cam, since it has
+                          extra intermediate buffers, but a hardware
+                          grabber card will then overwrite the buffer
+                          you're working on.
+                        */
+                       int *mbuf = arg;
+                       int ret;
+
+                       PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
+
+                       /* bounds check */
+                       if (*mbuf < 0 || *mbuf >= pwc_mbufs)
+                               return -EINVAL;
+                       /* check if this buffer was requested anyway */
+                       if (pdev->image_used[*mbuf] == 0)
+                               return -EINVAL;
+
+                       /* Add ourselves to the frame wait-queue.
+
+                          FIXME: needs auditing for safety.
+                          QUESTION: In what respect? I think that using the
+                                    frameq is safe now.
+                        */
+                       add_wait_queue(&pdev->frameq, &wait);
+                       while (pdev->full_frames == NULL) {
+                               /* Check for unplugged/etc. here */
+                               if (pdev->error_status) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -pdev->error_status;
+                               }
+
+                               if (signal_pending(current)) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -ERESTARTSYS;
+                               }
+                               schedule();
+                               set_current_state(TASK_INTERRUPTIBLE);
+                       }
+                       remove_wait_queue(&pdev->frameq, &wait);
+                       set_current_state(TASK_RUNNING);
+
+                       /* The frame is ready. Expand in the image buffer
+                          requested by the user. I don't care if you
+                          mmap() 5 buffers and request data in this order:
+                          buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+                          Grabber hardware may not be so forgiving.
+                        */
+                       PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n");
+                       pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
+                       /* Decompress, etc */
+                       ret = pwc_handle_frame(pdev);
+                       pdev->image_used[*mbuf] = 0;
+                       if (ret)
+                               return -EFAULT;
+                       break;
+               }
+
+               case VIDIOCGAUDIO:
+               {
+                       struct video_audio *v = arg;
+
+                       strcpy(v->name, "Microphone");
+                       v->audio = -1; /* unknown audio minor */
+                       v->flags = 0;
+                       v->mode = VIDEO_SOUND_MONO;
+                       v->volume = 0;
+                       v->bass = 0;
+                       v->treble = 0;
+                       v->balance = 0x8000;
+                       v->step = 1;
+                       break;
+               }
+
+               case VIDIOCSAUDIO:
+               {
+                       /* Dummy: nothing can be set */
+                       break;
+               }
+
+               case VIDIOCGUNIT:
+               {
+                       struct video_unit *vu = arg;
+
+                       vu->video = pdev->vdev->minor & 0x3F;
+                       vu->audio = -1; /* not known yet */
+                       vu->vbi = -1;
+                       vu->radio = -1;
+                       vu->teletext = -1;
+                       break;
+               }
+
+               /* V4L2 Layer */
+               case VIDIOC_QUERYCAP:
+               {
+                   struct v4l2_capability *cap = arg;
+
+                   PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
+                                      "try to use the v4l2 layer\n");
+                   strcpy(cap->driver,PWC_NAME);
+                   strlcpy(cap->card, vdev->name, sizeof(cap->card));
+                   usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
+                   cap->version = PWC_VERSION_CODE;
+                   cap->capabilities =
+                       V4L2_CAP_VIDEO_CAPTURE  |
+                       V4L2_CAP_STREAMING      |
+                       V4L2_CAP_READWRITE;
+                   return 0;
+               }
+
+               case VIDIOC_ENUMINPUT:
+               {
+                   struct v4l2_input *i = arg;
+
+                   if ( i->index )     /* Only one INPUT is supported */
+                         return -EINVAL;
+
+                   memset(i, 0, sizeof(struct v4l2_input));
+                   strcpy(i->name, "usb");
+                   return 0;
+               }
+
+               case VIDIOC_G_INPUT:
+               {
+                   int *i = arg;
+                   *i = 0;     /* Only one INPUT is supported */
+                   return 0;
+               }
+               case VIDIOC_S_INPUT:
+               {
+                       int *i = arg;
+
+                       if ( *i ) {     /* Only one INPUT is supported */
+                               PWC_DEBUG_IOCTL("Only one input source is"\
+                                       " supported with this webcam.\n");
+                               return -EINVAL;
+                       }
+                       return 0;
+               }
+
+               /* TODO: */
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *c = arg;
+                       int i;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
+                       for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
+                               if (pwc_controls[i].id == c->id) {
+                                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
+                                       memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
+                                       return 0;
+                               }
+                       }
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
+
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *c = arg;
+                       int ret;
+
+                       switch (c->id)
+                       {
+                               case V4L2_CID_BRIGHTNESS:
+                                       c->value = pwc_get_brightness(pdev);
+                                       if (c->value<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_CONTRAST:
+                                       c->value = pwc_get_contrast(pdev);
+                                       if (c->value<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_SATURATION:
+                                       ret = pwc_get_saturation(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_GAMMA:
+                                       c->value = pwc_get_gamma(pdev);
+                                       if (c->value<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_RED_BALANCE:
+                                       ret = pwc_get_red_gain(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value >>= 8;
+                                       return 0;
+                               case V4L2_CID_BLUE_BALANCE:
+                                       ret = pwc_get_blue_gain(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value >>= 8;
+                                       return 0;
+                               case V4L2_CID_AUTO_WHITE_BALANCE:
+                                       ret = pwc_get_awb(pdev);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value = (ret == PWC_WB_MANUAL)?0:1;
+                                       return 0;
+                               case V4L2_CID_GAIN:
+                                       ret = pwc_get_agc(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value >>= 8;
+                                       return 0;
+                               case V4L2_CID_AUTOGAIN:
+                                       ret = pwc_get_agc(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value = (c->value < 0)?1:0;
+                                       return 0;
+                               case V4L2_CID_EXPOSURE:
+                                       ret = pwc_get_shutter_speed(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_COLOUR_MODE:
+                                       ret = pwc_get_colour_mode(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_AUTOCONTOUR:
+                                       ret = pwc_get_contour(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       c->value=(c->value == -1?1:0);
+                                       return 0;
+                               case V4L2_CID_PRIVATE_CONTOUR:
+                                       ret = pwc_get_contour(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       c->value >>= 10;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_BACKLIGHT:
+                                       ret = pwc_get_backlight(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_FLICKERLESS:
+                                       ret = pwc_get_flicker(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       c->value=(c->value?1:0);
+                                       return 0;
+                               case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+                                       ret = pwc_get_dynamic_noise(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       return 0;
+
+                               case V4L2_CID_PRIVATE_SAVE_USER:
+                               case V4L2_CID_PRIVATE_RESTORE_USER:
+                               case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+                                       return -EINVAL;
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *c = arg;
+                       int ret;
+
+                       switch (c->id)
+                       {
+                               case V4L2_CID_BRIGHTNESS:
+                                       c->value <<= 9;
+                                       ret = pwc_set_brightness(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_CONTRAST:
+                                       c->value <<= 10;
+                                       ret = pwc_set_contrast(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_SATURATION:
+                                       ret = pwc_set_saturation(pdev, c->value);
+                                       if (ret<0)
+                                         return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_GAMMA:
+                                       c->value <<= 11;
+                                       ret = pwc_set_gamma(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_RED_BALANCE:
+                                       c->value <<= 8;
+                                       ret = pwc_set_red_gain(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_BLUE_BALANCE:
+                                       c->value <<= 8;
+                                       ret = pwc_set_blue_gain(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_AUTO_WHITE_BALANCE:
+                                       c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
+                                       ret = pwc_set_awb(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_EXPOSURE:
+                                       c->value <<= 8;
+                                       ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_AUTOGAIN:
+                                       /* autogain off means nothing without a gain */
+                                       if (c->value == 0)
+                                               return 0;
+                                       ret = pwc_set_agc(pdev, c->value, 0);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_GAIN:
+                                       c->value <<= 8;
+                                       ret = pwc_set_agc(pdev, 0, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_SAVE_USER:
+                                       if (pwc_save_user(pdev))
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_RESTORE_USER:
+                                       if (pwc_restore_user(pdev))
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+                                       if (pwc_restore_factory(pdev))
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_COLOUR_MODE:
+                                       ret = pwc_set_colour_mode(pdev, c->value);
+                                       if (ret < 0)
+                                         return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_AUTOCONTOUR:
+                                 c->value=(c->value == 1)?-1:0;
+                                 ret = pwc_set_contour(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+                               case V4L2_CID_PRIVATE_CONTOUR:
+                                 c->value <<= 10;
+                                 ret = pwc_set_contour(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+                               case V4L2_CID_PRIVATE_BACKLIGHT:
+                                 ret = pwc_set_backlight(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+                               case V4L2_CID_PRIVATE_FLICKERLESS:
+                                 ret = pwc_set_flicker(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                               case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+                                 ret = pwc_set_dynamic_noise(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+
+                       }
+                       return -EINVAL;
+               }
+
+               case VIDIOC_ENUM_FMT:
+               {
+                       struct v4l2_fmtdesc *f = arg;
+                       int index;
+
+                       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                             return -EINVAL;
+
+                       /* We only support two format: the raw format, and YUV */
+                       index = f->index;
+                       memset(f,0,sizeof(struct v4l2_fmtdesc));
+                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       f->index = index;
+                       switch(index)
+                       {
+                               case 0:
+                                       /* RAW format */
+                                       f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
+                                       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+                                       strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
+                                       break;
+                               case 1:
+                                       f->pixelformat = V4L2_PIX_FMT_YUV420;
+                                       strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
+                                       break;
+                               default:
+                                       return -EINVAL;
+                       }
+                       return 0;
+               }
+
+               case VIDIOC_G_FMT:
+               {
+                       struct v4l2_format *f = arg;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
+                       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                             return -EINVAL;
+
+                       pwc_vidioc_fill_fmt(pdev, f);
+
+                       return 0;
+               }
+
+               case VIDIOC_TRY_FMT:
+                       return pwc_vidioc_try_fmt(pdev, arg);
+
+               case VIDIOC_S_FMT:
+                       return pwc_vidioc_set_fmt(pdev, arg);
+
+               case VIDIOC_G_STD:
+               {
+                       v4l2_std_id *std = arg;
+                       *std = V4L2_STD_UNKNOWN;
+                       return 0;
+               }
+
+               case VIDIOC_S_STD:
+               {
+                       v4l2_std_id *std = arg;
+                       if (*std != V4L2_STD_UNKNOWN)
+                               return -EINVAL;
+                       return 0;
+               }
+
+               case VIDIOC_ENUMSTD:
+               {
+                       struct v4l2_standard *std = arg;
+                       if (std->index != 0)
+                               return -EINVAL;
+                       std->id = V4L2_STD_UNKNOWN;
+                       strncpy(std->name, "webcam", sizeof(std->name));
+                       return 0;
+               }
+
+               case VIDIOC_REQBUFS:
+               {
+                       struct v4l2_requestbuffers *rb = arg;
+                       int nbuffers;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
+                       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+                       if (rb->memory != V4L2_MEMORY_MMAP)
+                               return -EINVAL;
+
+                       nbuffers = rb->count;
+                       if (nbuffers < 2)
+                               nbuffers = 2;
+                       else if (nbuffers > pwc_mbufs)
+                               nbuffers = pwc_mbufs;
+                       /* Force to use our # of buffers */
+                       rb->count = pwc_mbufs;
+                       return 0;
+               }
+
+               case VIDIOC_QUERYBUF:
+               {
+                       struct v4l2_buffer *buf = arg;
+                       int index;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
+                               return -EINVAL;
+                       }
+                       if (buf->memory != V4L2_MEMORY_MMAP) {
+                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n");
+                               return -EINVAL;
+                       }
+                       index = buf->index;
+                       if (index < 0 || index >= pwc_mbufs) {
+                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
+                               return -EINVAL;
+                       }
+
+                       memset(buf, 0, sizeof(struct v4l2_buffer));
+                       buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       buf->index = index;
+                       buf->m.offset = index * pdev->len_per_image;
+                       if (pdev->vpalette == VIDEO_PALETTE_RAW)
+                               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+                       else
+                               buf->bytesused = pdev->view.size;
+                       buf->field = V4L2_FIELD_NONE;
+                       buf->memory = V4L2_MEMORY_MMAP;
+                       //buf->flags = V4L2_BUF_FLAG_MAPPED;
+                       buf->length = pdev->len_per_image;
+
+                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
+                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
+                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
+
+                       return 0;
+               }
+
+               case VIDIOC_QBUF:
+               {
+                       struct v4l2_buffer *buf = arg;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+                       if (buf->memory != V4L2_MEMORY_MMAP)
+                               return -EINVAL;
+                       if (buf->index < 0 || buf->index >= pwc_mbufs)
+                               return -EINVAL;
+
+                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+                       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+
+                       return 0;
+               }
+
+               case VIDIOC_DQBUF:
+               {
+                       struct v4l2_buffer *buf = arg;
+                       int ret;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+
+                       /* Add ourselves to the frame wait-queue.
+
+                          FIXME: needs auditing for safety.
+                          QUESTION: In what respect? I think that using the
+                                    frameq is safe now.
+                        */
+                       add_wait_queue(&pdev->frameq, &wait);
+                       while (pdev->full_frames == NULL) {
+                               if (pdev->error_status) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -pdev->error_status;
+                               }
+
+                               if (signal_pending(current)) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -ERESTARTSYS;
+                               }
+                               schedule();
+                               set_current_state(TASK_INTERRUPTIBLE);
+                       }
+                       remove_wait_queue(&pdev->frameq, &wait);
+                       set_current_state(TASK_RUNNING);
+
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
+                       /* Decompress data in pdev->images[pdev->fill_image] */
+                       ret = pwc_handle_frame(pdev);
+                       if (ret)
+                               return -EFAULT;
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
+
+                       buf->index = pdev->fill_image;
+                       if (pdev->vpalette == VIDEO_PALETTE_RAW)
+                               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+                       else
+                               buf->bytesused = pdev->view.size;
+                       buf->flags = V4L2_BUF_FLAG_MAPPED;
+                       buf->field = V4L2_FIELD_NONE;
+                       do_gettimeofday(&buf->timestamp);
+                       buf->sequence = 0;
+                       buf->memory = V4L2_MEMORY_MMAP;
+                       buf->m.offset = pdev->fill_image * pdev->len_per_image;
+                       buf->length = buf->bytesused;
+                       pwc_next_image(pdev);
+
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
+                       return 0;
+
+               }
+
+               case VIDIOC_STREAMON:
+               {
+                       /* WARNING: pwc_try_video_mode() called pwc_isoc_init */
+                       pwc_isoc_init(pdev);
+                       return 0;
+               }
+
+               case VIDIOC_STREAMOFF:
+               {
+                       pwc_isoc_cleanup(pdev);
+                       return 0;
+               }
+
+               default:
+                       return pwc_ioctl(pdev, cmd, arg);
+       } /* ..switch */
+       return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
new file mode 100644 (file)
index 0000000..76b2e96
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * tlv320aic23b - driver version 0.0.1
+ *
+ * Copyright (C) 2006 Scott Alfter <salfter@ssai.us>
+ *
+ * Based on wm8775 driver
+ *
+ * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
+ * Copyright (C) 2005 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("tlv320aic23b driver");
+MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+
+struct tlv320aic23b_state {
+       u8 muted;
+};
+
+static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val)
+{
+       int i;
+
+       if ((reg < 0 || reg > 9) && (reg != 15)) {
+               v4l_err(client, "Invalid register R%d\n", reg);
+               return -1;
+       }
+
+       for (i = 0; i < 3; i++) {
+               if (i2c_smbus_write_byte_data(client, (reg << 1) |
+                                       (val >> 8), val & 0xff) == 0) {
+                       return 0;
+               }
+       }
+       v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+       return -1;
+}
+
+static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd,
+                         void *arg)
+{
+       struct tlv320aic23b_state *state = i2c_get_clientdata(client);
+       struct v4l2_control *ctrl = arg;
+       u32* freq = arg;
+
+       switch (cmd) {
+       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+               switch (*freq) {
+                       case 32000: /* set sample rate to 32 kHz */
+                               tlv320aic23b_write(client, 8, 0x018);
+                               break;
+                       case 44100: /* set sample rate to 44.1 kHz */
+                               tlv320aic23b_write(client, 8, 0x022);
+                               break;
+                       case 48000: /* set sample rate to 48 kHz */
+                               tlv320aic23b_write(client, 8, 0x000);
+                               break;
+                       default:
+                               return -EINVAL;
+               }
+               break;
+
+       case VIDIOC_G_CTRL:
+               if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               ctrl->value = state->muted;
+               break;
+
+       case VIDIOC_S_CTRL:
+               if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               state->muted = ctrl->value;
+               tlv320aic23b_write(client, 0, 0x180); /* mute both channels */
+               /* set gain on both channels to +3.0 dB */
+               if (!state->muted)
+                       tlv320aic23b_write(client, 0, 0x119);
+               break;
+
+       case VIDIOC_LOG_STATUS:
+               v4l_info(client, "Input: %s\n",
+                           state->muted ? "muted" : "active");
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static struct i2c_driver i2c_driver;
+
+static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *client;
+       struct tlv320aic23b_state *state;
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return 0;
+
+       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (client == 0)
+               return -ENOMEM;
+
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &i2c_driver;
+       snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b");
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+       state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL);
+       if (state == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+       state->muted = 0;
+       i2c_set_clientdata(client, state);
+
+       /* initialize tlv320aic23b */
+       tlv320aic23b_write(client, 15, 0x000);  /* RESET */
+       tlv320aic23b_write(client, 6, 0x00A);   /* turn off DAC & mic input */
+       tlv320aic23b_write(client, 7, 0x049);   /* left-justified, 24-bit, master mode */
+       tlv320aic23b_write(client, 0, 0x119);   /* set gain on both channels to +3.0 dB */
+       tlv320aic23b_write(client, 8, 0x000);   /* set sample rate to 48 kHz */
+       tlv320aic23b_write(client, 9, 0x001);   /* activate digital interface */
+
+       i2c_attach_client(client);
+
+       return 0;
+}
+
+static int tlv320aic23b_probe(struct i2c_adapter *adapter)
+{
+       if (adapter->class & I2C_CLASS_TV_ANALOG)
+               return i2c_probe(adapter, &addr_data, tlv320aic23b_attach);
+       return 0;
+}
+
+static int tlv320aic23b_detach(struct i2c_client *client)
+{
+       int err;
+
+       err = i2c_detach_client(client);
+       if (err) {
+               return err;
+       }
+       kfree(client);
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+       .driver = {
+               .name = "tlv320aic23b",
+       },
+       .id             = I2C_DRIVERID_TLV320AIC23B,
+       .attach_adapter = tlv320aic23b_probe,
+       .detach_client  = tlv320aic23b_detach,
+       .command        = tlv320aic23b_command,
+};
+
+
+static int __init tlv320aic23b_init_module(void)
+{
+       return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit tlv320aic23b_cleanup_module(void)
+{
+       i2c_del_driver(&i2c_driver);
+}
+
+module_init(tlv320aic23b_init_module);
+module_exit(tlv320aic23b_cleanup_module);
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
new file mode 100644 (file)
index 0000000..56e01b6
--- /dev/null
@@ -0,0 +1,1120 @@
+/*
+ * Driver for Logitech Quickcam Messenger usb video camera
+ * Copyright (C) Jaya Kumar
+ *
+ * This work was sponsored by CIS(M) Sdn Bhd.
+ * History:
+ * 05/08/2006 - Jaya Kumar
+ * I wrote this based on the konicawc by Simon Evans.
+ * -
+ * Full credit for reverse engineering and creating an initial
+ * working linux driver for the VV6422 goes to the qce-ga project by
+ * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell,
+ * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as
+ * others.
+ * ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/usb/input.h>
+
+#include "usbvideo.h"
+#include "quickcam_messenger.h"
+
+/*
+ * Version Information
+ */
+
+#ifdef CONFIG_USB_DEBUG
+static int debug;
+#define DEBUG(n, format, arg...) \
+       if (n <= debug) {        \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+       }
+#else
+#define DEBUG(n, arg...)
+static const int debug = 0;
+#endif
+
+#define DRIVER_VERSION "v0.01"
+#define DRIVER_DESC "Logitech Quickcam Messenger USB"
+
+#define USB_LOGITECH_VENDOR_ID 0x046D
+#define USB_QCM_PRODUCT_ID     0x08F0
+
+#define MAX_CAMERAS    1
+
+#define MAX_COLOUR     32768
+#define MAX_HUE                32768
+#define MAX_BRIGHTNESS 32768
+#define MAX_CONTRAST   32768
+#define MAX_WHITENESS  32768
+
+static int size = SIZE_320X240;
+static int colour = MAX_COLOUR;
+static int hue = MAX_HUE;
+static int brightness =        MAX_BRIGHTNESS;
+static int contrast =  MAX_CONTRAST;
+static int whiteness = MAX_WHITENESS;
+
+static struct usbvideo *cams;
+
+static struct usb_device_id qcm_table [] = {
+       { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, qcm_table);
+
+#ifdef CONFIG_INPUT
+static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
+{
+       struct input_dev *input_dev;
+
+       usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
+       strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
+
+       cam->input = input_dev = input_allocate_device();
+       if (!input_dev) {
+               warn("insufficient mem for cam input device");
+               return;
+       }
+
+       input_dev->name = "QCM button";
+       input_dev->phys = cam->input_physname;
+       usb_to_input_id(dev, &input_dev->id);
+       input_dev->cdev.dev = &dev->dev;
+
+       input_dev->evbit[0] = BIT(EV_KEY);
+       input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+       input_dev->private = cam;
+
+       input_register_device(cam->input);
+}
+
+static void qcm_unregister_input(struct qcm *cam)
+{
+       if (cam->input) {
+               input_unregister_device(cam->input);
+               cam->input = NULL;
+       }
+}
+
+static void qcm_report_buttonstat(struct qcm *cam)
+{
+       if (cam->input) {
+               input_report_key(cam->input, BTN_0, cam->button_sts);
+               input_sync(cam->input);
+       }
+}
+
+static void qcm_int_irq(struct urb *urb, struct pt_regs *regs)
+{
+       int ret;
+       struct uvd *uvd = urb->context;
+       struct qcm *cam;
+
+       if (!CAMERA_IS_OPERATIONAL(uvd))
+               return;
+
+       if (!uvd->streaming)
+               return;
+
+       uvd->stats.urb_count++;
+
+       if (urb->status < 0)
+               uvd->stats.iso_err_count++;
+       else {
+               if (urb->actual_length > 0 ) {
+                       cam = (struct qcm *) uvd->user_data;
+                       if (cam->button_sts_buf == 0x88)
+                               cam->button_sts = 0x0;
+                       else if (cam->button_sts_buf == 0x80)
+                               cam->button_sts = 0x1;
+                       qcm_report_buttonstat(cam);
+               }
+       }
+
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret < 0)
+               err("usb_submit_urb error (%d)", ret);
+}
+
+static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd)
+{
+       int errflag;
+       usb_fill_int_urb(cam->button_urb, uvd->dev,
+                       usb_rcvintpipe(uvd->dev, uvd->video_endp + 1),
+                       &cam->button_sts_buf,
+                       1,
+                       qcm_int_irq,
+                       uvd, 16);
+
+       errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL);
+       if (errflag)
+               err ("usb_submit_int ret %d", errflag);
+       return errflag;
+}
+
+static void qcm_stop_int_data(struct qcm *cam)
+{
+       usb_kill_urb(cam->button_urb);
+}
+
+static int qcm_alloc_int_urb(struct qcm *cam)
+{
+       cam->button_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+       if (!cam->button_urb)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void qcm_free_int(struct qcm *cam)
+{
+       if (cam->button_urb)
+               usb_free_urb(cam->button_urb);
+}
+#endif /* CONFIG_INPUT */
+
+static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val)
+{
+       int ret;
+
+       /* we'll wait up to 3 slices but no more */
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+               reg, 0, &val, 1, 3*HZ);
+       return ret;
+}
+
+static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val)
+{
+       int ret;
+
+       /* we'll wait up to 3 slices but no more */
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+               reg, 0, &val, 2, 3*HZ);
+       return ret;
+}
+
+static int qcm_stv_getw(struct usb_device *dev, unsigned short reg,
+                                                       __le16 *val)
+{
+       int ret;
+
+       /* we'll wait up to 3 slices but no more */
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+               reg, 0, val, 2, 3*HZ);
+       return ret;
+}
+
+static int qcm_camera_on(struct uvd *uvd)
+{
+       int ret;
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01));
+       return 0;
+}
+
+static int qcm_camera_off(struct uvd *uvd)
+{
+       int ret;
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
+       return 0;
+}
+
+static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b)
+{
+       unsigned int segment, valsat;
+       signed int   h = (signed int) hue;
+       unsigned int s = (sat - 32768) * 2;     /* rescale */
+       unsigned int v = val;
+       unsigned int p;
+
+       /*
+       the registers controling gain are 8 bit of which
+       we affect only the last 4 bits with our gain.
+       we know that if saturation is 0, (unsaturated) then
+       we're grayscale (center axis of the colour cone) so
+       we set rgb=value. we use a formula obtained from
+       wikipedia to map the cone to the RGB plane. it's
+       as follows for the human value case of h=0..360,
+       s=0..1, v=0..1
+       h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s)
+       q = v(1 - f*s) , t = v(1 - (1-f)s)
+       h_i==0 => r=v , g=t, b=p
+       h_i==1 => r=q , g=v, b=p
+       h_i==2 => r=p , g=v, b=t
+       h_i==3 => r=p , g=q, b=v
+       h_i==4 => r=t , g=p, b=v
+       h_i==5 => r=v , g=p, b=q
+       the bottom side (the point) and the stuff just up
+       of that is black so we simplify those two cases.
+       */
+       if (sat < 32768) {
+               /* anything less than this is unsaturated */
+               *r = val;
+               *g = val;
+               *b = val;
+               return;
+       }
+       if (val <= (0xFFFF/8)) {
+               /* anything less than this is black */
+               *r = 0;
+               *g = 0;
+               *b = 0;
+               return;
+       }
+
+       /* the rest of this code is copying tukkat's
+       implementation of the hsv2rgb conversion as taken
+       from qc-usb-messenger code. the 10923 is 0xFFFF/6
+       to divide the cone into 6 sectors.  */
+
+       segment = (h + 10923) & 0xFFFF;
+       segment = segment*3 >> 16;              /* 0..2: 0=R, 1=G, 2=B */
+       hue -= segment * 21845;                 /* -10923..10923 */
+       h = hue;
+       h *= 3;
+       valsat = v*s >> 16;                     /* 0..65534 */
+       p = v - valsat;
+       if (h >= 0) {
+               unsigned int t = v - (valsat * (32769 - h) >> 15);
+               switch (segment) {
+               case 0: /* R-> */
+                       *r = v;
+                       *g = t;
+                       *b = p;
+                       break;
+               case 1: /* G-> */
+                       *r = p;
+                       *g = v;
+                       *b = t;
+                       break;
+               case 2: /* B-> */
+                       *r = t;
+                       *g = p;
+                       *b = v;
+                       break;
+               }
+       } else {
+               unsigned int q = v - (valsat * (32769 + h) >> 15);
+               switch (segment) {
+               case 0: /* ->R */
+                       *r = v;
+                       *g = p;
+                       *b = q;
+                       break;
+               case 1: /* ->G */
+                       *r = q;
+                       *g = v;
+                       *b = p;
+                       break;
+               case 2: /* ->B */
+                       *r = p;
+                       *g = q;
+                       *b = v;
+                       break;
+               }
+       }
+}
+
+static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue,
+       u16 saturation, u16 value)
+{
+       int ret;
+       u16 r=0,g=0,b=0;
+
+       /* this code is based on qc-usb-messenger */
+       qcm_hsv2rgb(hue, saturation, value, &r, &g, &b);
+
+       r >>= 12;
+       g >>= 12;
+       b >>= 12;
+
+       /* min val is 8 */
+       r = max((u16) 8, r);
+       g = max((u16) 8, g);
+       b = max((u16) 8, b);
+
+       r |= 0x30;
+       g |= 0x30;
+       b |= 0x30;
+
+       /* set the r,g,b gain registers */
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b));
+
+       /* doing as qc-usb did */
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+
+       return 0;
+}
+
+static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure)
+{
+       int ret;
+       int formedval;
+
+       /* calculation was from qc-usb-messenger driver */
+       formedval = ( exposure >> 12 );
+
+       /* max value for formedval is 14 */
+       formedval = min(formedval, 14);
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev,
+                       0x143A, 0xF0 | formedval));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+       return 0;
+}
+
+static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast,
+                                       int hue, int colour)
+{
+       int ret;
+       /* brightness is exposure, contrast is gain, colour is saturation */
+       CHECK_RET(ret,
+               qcm_sensor_set_exposure(uvd, brightness));
+       CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast));
+
+       return 0;
+}
+
+static int qcm_sensor_setsize(struct uvd *uvd, u8 size)
+{
+       int ret;
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size));
+       return 0;
+}
+
+static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness)
+{
+       int ret;
+       /* some rescaling as done by the qc-usb-messenger code */
+       if (whiteness > 0xC000)
+               whiteness = 0xC000 + (whiteness & 0x3FFF)*8;
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D,
+                               (whiteness >> 8) & 0xFF));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E,
+                               (whiteness >> 16) & 0x03));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+
+       return 0;
+}
+
+static int qcm_sensor_init(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int ret;
+       int i;
+
+       for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) {
+               CHECK_RET(ret, qcm_stv_setb(uvd->dev,
+                                       regval_table[i].reg,
+                                       regval_table[i].val));
+       }
+
+       CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1,
+                               cpu_to_le16(ISOC_PACKET_SIZE)));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08));
+       CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01));
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
+
+       CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+
+       CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness,
+                       uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour));
+
+       CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
+       CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+
+       return 0;
+}
+
+static int qcm_set_camera_size(struct uvd *uvd)
+{
+       int ret;
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+       cam->width = camera_sizes[cam->size].width;
+       cam->height = camera_sizes[cam->size].height;
+       uvd->videosize = VIDEOSIZE(cam->width, cam->height);
+
+       return 0;
+}
+
+static int qcm_setup_on_open(struct uvd *uvd)
+{
+       int ret;
+
+       CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue,
+                               uvd->vpic.colour, uvd->vpic.contrast));
+       CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness));
+       CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
+       CHECK_RET(ret, qcm_set_camera_size(uvd));
+       CHECK_RET(ret, qcm_camera_on(uvd));
+       return 0;
+}
+
+static void qcm_adjust_picture(struct uvd *uvd)
+{
+       int ret;
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       ret = qcm_camera_off(uvd);
+       if (ret) {
+               err("can't turn camera off. abandoning pic adjustment");
+               return;
+       }
+
+       /* if there's been a change in contrast, hue, or
+       colour then we need to recalculate hsv in order
+       to update gains */
+       if ((cam->contrast != uvd->vpic.contrast) ||
+               (cam->hue != uvd->vpic.hue) ||
+               (cam->colour != uvd->vpic.colour)) {
+               cam->contrast = uvd->vpic.contrast;
+               cam->hue = uvd->vpic.hue;
+               cam->colour = uvd->vpic.colour;
+               ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour,
+                                               cam->contrast);
+               if (ret) {
+                       err("can't set gains. abandoning pic adjustment");
+                       return;
+               }
+       }
+
+       if (cam->brightness != uvd->vpic.brightness) {
+               cam->brightness = uvd->vpic.brightness;
+               ret = qcm_sensor_set_exposure(uvd, cam->brightness);
+               if (ret) {
+                       err("can't set exposure. abandoning pic adjustment");
+                       return;
+               }
+       }
+
+       if (cam->whiteness != uvd->vpic.whiteness) {
+               cam->whiteness = uvd->vpic.whiteness;
+               qcm_sensor_set_shutter(uvd, cam->whiteness);
+               if (ret) {
+                       err("can't set shutter. abandoning pic adjustment");
+                       return;
+               }
+       }
+
+       ret = qcm_camera_on(uvd);
+       if (ret) {
+               err("can't reenable camera. pic adjustment failed");
+               return;
+       }
+}
+
+static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen)
+{
+       int datalen;
+       int totaldata;
+       struct framehdr {
+               __be16 id;
+               __be16 len;
+       };
+       struct framehdr *fhdr;
+
+       totaldata = 0;
+       while (framelen) {
+               fhdr = (struct framehdr *) cdata;
+               datalen = be16_to_cpu(fhdr->len);
+               framelen -= 4;
+               cdata += 4;
+
+               if ((fhdr->id) == cpu_to_be16(0x8001)) {
+                       RingQueue_Enqueue(&uvd->dp, marker, 4);
+                       totaldata += 4;
+                       continue;
+               }
+               if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) {
+                       RingQueue_Enqueue(&uvd->dp, cdata, datalen);
+                       totaldata += datalen;
+               }
+               framelen -= datalen;
+               cdata += datalen;
+       }
+       return totaldata;
+}
+
+static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb)
+{
+       int totlen;
+       int i;
+       unsigned char *cdata;
+
+       totlen=0;
+       for (i = 0; i < dataurb->number_of_packets; i++) {
+               int n = dataurb->iso_frame_desc[i].actual_length;
+               int st = dataurb->iso_frame_desc[i].status;
+
+               cdata = dataurb->transfer_buffer +
+                       dataurb->iso_frame_desc[i].offset;
+
+               if (st < 0) {
+                       warn("Data error: packet=%d. len=%d. status=%d.",
+                             i, n, st);
+                       uvd->stats.iso_err_count++;
+                       continue;
+               }
+               if (!n)
+                       continue;
+
+               totlen += qcm_process_frame(uvd, cdata, n);
+       }
+       return totlen;
+}
+
+static void resubmit_urb(struct uvd *uvd, struct urb *urb)
+{
+       int ret;
+
+       urb->dev = uvd->dev;
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret)
+               err("usb_submit_urb error (%d)", ret);
+}
+
+static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs)
+{
+       int len;
+       struct uvd *uvd = urb->context;
+
+       if (!CAMERA_IS_OPERATIONAL(uvd))
+               return;
+
+       if (!uvd->streaming)
+               return;
+
+       uvd->stats.urb_count++;
+
+       if (!urb->actual_length) {
+               resubmit_urb(uvd, urb);
+               return;
+       }
+
+       len = qcm_compress_iso(uvd, urb);
+       resubmit_urb(uvd, urb);
+       uvd->stats.urb_length = len;
+       uvd->stats.data_count += len;
+       if (len)
+               RingQueue_WakeUpInterruptible(&uvd->dp);
+}
+
+static int qcm_start_data(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int i;
+       int errflag;
+       int pktsz;
+       int err;
+
+       pktsz = uvd->iso_packet_len;
+       if (!CAMERA_IS_OPERATIONAL(uvd)) {
+               err("Camera is not operational");
+               return -EFAULT;
+       }
+
+       err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive);
+       if (err < 0) {
+               err("usb_set_interface error");
+               uvd->last_error = err;
+               return -EBUSY;
+       }
+
+       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+               int j, k;
+               struct urb *urb = uvd->sbuf[i].urb;
+               urb->dev = uvd->dev;
+               urb->context = uvd;
+               urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp);
+               urb->interval = 1;
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = uvd->sbuf[i].data;
+               urb->complete = qcm_isoc_irq;
+               urb->number_of_packets = FRAMES_PER_DESC;
+               urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
+               for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length = pktsz;
+               }
+       }
+
+       uvd->streaming = 1;
+       uvd->curframe = -1;
+       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+               errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+               if (errflag)
+                       err ("usb_submit_isoc(%d) ret %d", i, errflag);
+       }
+
+       CHECK_RET(err, qcm_setup_input_int(cam, uvd));
+       CHECK_RET(err, qcm_camera_on(uvd));
+       return 0;
+}
+
+static void qcm_stop_data(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int i, j;
+       int ret;
+
+       if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
+               return;
+
+       ret = qcm_camera_off(uvd);
+       if (ret)
+               warn("couldn't turn the cam off.");
+
+       uvd->streaming = 0;
+
+       /* Unschedule all of the iso td's */
+       for (i=0; i < USBVIDEO_NUMSBUF; i++)
+               usb_kill_urb(uvd->sbuf[i].urb);
+
+       qcm_stop_int_data(cam);
+
+       if (!uvd->remove_pending) {
+               /* Set packet size to 0 */
+               j = usb_set_interface(uvd->dev, uvd->iface,
+                                       uvd->ifaceAltInactive);
+               if (j < 0) {
+                       err("usb_set_interface() error %d.", j);
+                       uvd->last_error = j;
+               }
+       }
+}
+
+static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int x;
+       struct rgb *rgbL0;
+       struct rgb *rgbL1;
+       struct bayL0 *bayL0;
+       struct bayL1 *bayL1;
+       int hor,ver,hordel,verdel;
+       assert(frame != NULL);
+
+       switch (cam->size) {
+       case SIZE_160X120:
+               hor = 162; ver = 124; hordel = 1; verdel = 2;
+               break;
+       case SIZE_320X240:
+       default:
+               hor = 324; ver = 248; hordel = 2; verdel = 4;
+               break;
+       }
+
+       if (frame->scanstate == ScanState_Scanning) {
+               while (RingQueue_GetLength(&uvd->dp) >=
+                        4 + (hor*verdel + hordel)) {
+                       if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+                           (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
+                           (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
+                           (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) {
+                               frame->curline = 0;
+                               frame->scanstate = ScanState_Lines;
+                               frame->frameState = FrameState_Grabbing;
+                               RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
+                       /*
+                       * if we're starting, we need to discard the first
+                       * 4 lines of y bayer data
+                       * and the first 2 gr elements of x bayer data
+                       */
+                               RING_QUEUE_DEQUEUE_BYTES(&uvd->dp,
+                                                       (hor*verdel + hordel));
+                               break;
+                       }
+                       RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+               }
+       }
+
+       if (frame->scanstate == ScanState_Scanning)
+               return;
+
+       /* now we can start processing bayer data so long as we have at least
+       * 2 lines worth of data. this is the simplest demosaicing method that
+       * I could think of. I use each 2x2 bayer element without interpolation
+       * to generate 4 rgb pixels.
+       */
+       while ( frame->curline < cam->height &&
+               (RingQueue_GetLength(&uvd->dp) >= hor*2)) {
+               /* get 2 lines of bayer for demosaicing
+                * into 2 lines of RGB */
+               RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2);
+               bayL0 = (struct bayL0 *) cam->scratch;
+               bayL1 = (struct bayL1 *) (cam->scratch + hor);
+               /* frame->curline is the rgb y line */
+               rgbL0 = (struct rgb *)
+                               ( frame->data + (cam->width*3*frame->curline));
+               /* w/2 because we're already doing 2 pixels */
+               rgbL1 = rgbL0 + (cam->width/2);
+
+               for (x=0; x < cam->width; x+=2) {
+                       rgbL0->r = bayL0->r;
+                       rgbL0->g = bayL0->g;
+                       rgbL0->b = bayL1->b;
+
+                       rgbL0->r2 = bayL0->r;
+                       rgbL0->g2 = bayL1->g;
+                       rgbL0->b2 = bayL1->b;
+
+                       rgbL1->r = bayL0->r;
+                       rgbL1->g = bayL1->g;
+                       rgbL1->b = bayL1->b;
+
+                       rgbL1->r2 = bayL0->r;
+                       rgbL1->g2 = bayL1->g;
+                       rgbL1->b2 = bayL1->b;
+
+                       rgbL0++;
+                       rgbL1++;
+
+                       bayL0++;
+                       bayL1++;
+               }
+
+               frame->seqRead_Length += cam->width*3*2;
+               frame->curline += 2;
+       }
+       /* See if we filled the frame */
+       if (frame->curline == cam->height) {
+               frame->frameState = FrameState_Done_Hold;
+               frame->curline = 0;
+               uvd->curframe = -1;
+               uvd->stats.frame_num++;
+       }
+}
+
+/* taken from konicawc */
+static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw)
+{
+       int ret;
+       int newsize;
+       int oldsize;
+       int x = vw->width;
+       int y = vw->height;
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       if (x > 0 && y > 0) {
+               DEBUG(2, "trying to find size %d,%d", x, y);
+               for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
+                       if ((camera_sizes[newsize].width == x) &&
+                               (camera_sizes[newsize].height == y))
+                               break;
+               }
+       } else
+               newsize = cam->size;
+
+       if (newsize > MAX_FRAME_SIZE) {
+               DEBUG(1, "couldn't find size %d,%d", x, y);
+               return -EINVAL;
+       }
+
+       if (newsize == cam->size) {
+               DEBUG(1, "Nothing to do");
+               return 0;
+       }
+
+       qcm_stop_data(uvd);
+
+       if (cam->size != newsize) {
+               oldsize = cam->size;
+               cam->size = newsize;
+               ret = qcm_set_camera_size(uvd);
+               if (ret) {
+                       err("Couldn't set camera size, err=%d",ret);
+                       /* restore the original size */
+                       cam->size = oldsize;
+                       return ret;
+               }
+       }
+
+       /* Flush the input queue and clear any current frame in progress */
+
+       RingQueue_Flush(&uvd->dp);
+       if (uvd->curframe != -1) {
+               uvd->frame[uvd->curframe].curline = 0;
+               uvd->frame[uvd->curframe].seqRead_Length = 0;
+               uvd->frame[uvd->curframe].seqRead_Index = 0;
+       }
+
+       CHECK_RET(ret, qcm_start_data(uvd));
+       return 0;
+}
+
+static int qcm_configure_video(struct uvd *uvd)
+{
+       int ret;
+       memset(&uvd->vpic, 0, sizeof(uvd->vpic));
+       memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
+
+       uvd->vpic.colour = colour;
+       uvd->vpic.hue = hue;
+       uvd->vpic.brightness = brightness;
+       uvd->vpic.contrast = contrast;
+       uvd->vpic.whiteness = whiteness;
+       uvd->vpic.depth = 24;
+       uvd->vpic.palette = VIDEO_PALETTE_RGB24;
+
+       memset(&uvd->vcap, 0, sizeof(uvd->vcap));
+       strcpy(uvd->vcap.name, "QCM USB Camera");
+       uvd->vcap.type = VID_TYPE_CAPTURE;
+       uvd->vcap.channels = 1;
+       uvd->vcap.audios = 0;
+
+       uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
+       uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
+       uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
+       uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
+
+       memset(&uvd->vchan, 0, sizeof(uvd->vchan));
+       uvd->vchan.flags = 0 ;
+       uvd->vchan.tuners = 0;
+       uvd->vchan.channel = 0;
+       uvd->vchan.type = VIDEO_TYPE_CAMERA;
+       strcpy(uvd->vchan.name, "Camera");
+
+       CHECK_RET(ret, qcm_sensor_init(uvd));
+       return 0;
+}
+
+static int qcm_probe(struct usb_interface *intf,
+                       const struct usb_device_id *devid)
+{
+       int err;
+       struct uvd *uvd;
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct qcm *cam;
+       size_t buffer_size;
+       unsigned char video_ep;
+       struct usb_host_interface *interface;
+       struct usb_endpoint_descriptor *endpoint;
+       int i,j;
+       unsigned int ifacenum, ifacenum_inact=0;
+       __le16 sensor_id;
+
+       /* we don't support multiconfig cams */
+       if (dev->descriptor.bNumConfigurations != 1)
+               return -ENODEV;
+
+       /* first check for the video interface and not
+       * the audio interface */
+       interface = &intf->cur_altsetting[0];
+       if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+               || (interface->desc.bInterfaceSubClass !=
+                       USB_CLASS_VENDOR_SPEC))
+               return -ENODEV;
+
+       /*
+       walk through each endpoint in each setting in the interface
+       stop when we find the one that's an isochronous IN endpoint.
+       */
+       for (i=0; i < intf->num_altsetting; i++) {
+               interface = &intf->cur_altsetting[i];
+               ifacenum = interface->desc.bAlternateSetting;
+               /* walk the end points */
+               for (j=0; j < interface->desc.bNumEndpoints; j++) {
+                       endpoint = &interface->endpoint[j].desc;
+
+                       if ((endpoint->bEndpointAddress &
+                               USB_ENDPOINT_DIR_MASK) != USB_DIR_IN)
+                               continue; /* not input then not good */
+
+                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                       if (!buffer_size) {
+                               ifacenum_inact = ifacenum;
+                               continue; /* 0 pkt size is not what we want */
+                       }
+
+                       if ((endpoint->bmAttributes &
+                               USB_ENDPOINT_XFERTYPE_MASK) ==
+                               USB_ENDPOINT_XFER_ISOC) {
+                               video_ep = endpoint->bEndpointAddress;
+                               /* break out of the search */
+                               goto good_videoep;
+                       }
+               }
+       }
+       /* failed out since nothing useful was found */
+       err("No suitable endpoint was found\n");
+       return -ENODEV;
+
+good_videoep:
+       /* disable isochronous stream before doing anything else */
+       err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0);
+       if (err < 0) {
+               err("Failed to disable sensor stream");
+               return -EIO;
+       }
+
+       /*
+       Check that this is the same unknown sensor that is known to work. This
+       sensor is suspected to be the ST VV6422C001. I'll check the same value
+       that the qc-usb driver checks. This value is probably not even the
+       sensor ID since it matches the USB dev ID. Oh well. If it doesn't
+       match, it's probably a diff sensor so exit and apologize.
+       */
+       err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id);
+       if (err < 0) {
+               err("Couldn't read sensor values. Err %d\n",err);
+               return err;
+       }
+       if (sensor_id != cpu_to_le16(0x08F0)) {
+               err("Sensor ID %x != %x. Unsupported. Sorry\n",
+                       le16_to_cpu(sensor_id), (0x08F0));
+               return -ENODEV;
+       }
+
+       uvd = usbvideo_AllocateDevice(cams);
+       if (!uvd)
+               return -ENOMEM;
+
+       cam = (struct qcm *) uvd->user_data;
+
+       /* buf for doing demosaicing */
+       cam->scratch = kmalloc(324*2, GFP_KERNEL);
+       if (!cam->scratch) /* uvd freed in dereg */
+               return -ENOMEM;
+
+       /* yes, if we fail after here, cam->scratch gets freed
+       by qcm_free_uvd */
+
+       err = qcm_alloc_int_urb(cam);
+       if (err < 0)
+               return err;
+
+       /* yes, if we fail after here, int urb gets freed
+       by qcm_free_uvd */
+
+       RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
+       cam->width = camera_sizes[size].width;
+       cam->height = camera_sizes[size].height;
+       cam->size = size;
+
+       uvd->debug = debug;
+       uvd->flags = 0;
+       uvd->dev = dev;
+       uvd->iface = intf->altsetting->desc.bInterfaceNumber;
+       uvd->ifaceAltActive = ifacenum;
+       uvd->ifaceAltInactive = ifacenum_inact;
+       uvd->video_endp = video_ep;
+       uvd->iso_packet_len = buffer_size;
+       uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
+       uvd->defaultPalette = VIDEO_PALETTE_RGB24;
+       uvd->canvas = VIDEOSIZE(320, 240);
+       uvd->videosize = VIDEOSIZE(cam->width, cam->height);
+       err = qcm_configure_video(uvd);
+       if (err) {
+               err("failed to configure video settings");
+               return err;
+       }
+
+       err = usbvideo_RegisterVideoDevice(uvd);
+       if (err) { /* the uvd gets freed in Deregister */
+               err("usbvideo_RegisterVideoDevice() failed.");
+               return err;
+       }
+
+       uvd->max_frame_size = (320 * 240 * 3);
+       qcm_register_input(cam, dev);
+       usb_set_intfdata(intf, uvd);
+       return 0;
+}
+
+static void qcm_free_uvd(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       kfree(cam->scratch);
+       qcm_unregister_input(cam);
+       qcm_free_int(cam);
+}
+
+static struct usbvideo_cb qcm_driver = {
+       .probe =                qcm_probe,
+       .setupOnOpen =          qcm_setup_on_open,
+       .processData =          qcm_process_isoc,
+       .setVideoMode =         qcm_set_video_mode,
+       .startDataPump =        qcm_start_data,
+       .stopDataPump =         qcm_stop_data,
+       .adjustPicture =        qcm_adjust_picture,
+       .userFree =             qcm_free_uvd
+};
+
+static int __init qcm_init(void)
+{
+       info(DRIVER_DESC " " DRIVER_VERSION);
+
+       return usbvideo_register(
+               &cams,
+               MAX_CAMERAS,
+               sizeof(struct qcm),
+               "QCM",
+               &qcm_driver,
+               THIS_MODULE,
+               qcm_table);
+}
+
+static void __exit qcm_exit(void)
+{
+       usbvideo_Deregister(&cams);
+}
+
+module_param(size, int, 0);
+MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240");
+module_param(colour, int, 0);
+MODULE_PARM_DESC(colour, "Initial colour");
+module_param(hue, int, 0);
+MODULE_PARM_DESC(hue, "Initial hue");
+module_param(brightness, int, 0);
+MODULE_PARM_DESC(brightness, "Initial brightness");
+module_param(contrast, int, 0);
+MODULE_PARM_DESC(contrast, "Initial contrast");
+module_param(whiteness, int, 0);
+MODULE_PARM_DESC(whiteness, "Initial whiteness");
+
+#ifdef CONFIG_USB_DEBUG
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+#endif
+
+module_init(qcm_init);
+module_exit(qcm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_DESCRIPTION("QCM USB Camera");
+MODULE_SUPPORTED_DEVICE("QCM USB Camera");
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h
new file mode 100644 (file)
index 0000000..baab9c0
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef quickcam_messenger_h
+#define quickcam_messenger_h
+
+#ifndef CONFIG_INPUT
+/* if we're not using input we dummy out these functions */
+#define qcm_register_input(...)
+#define qcm_unregister_input(...)
+#define qcm_report_buttonstat(...)
+#define qcm_setup_input_int(...) 0
+#define qcm_stop_int_data(...)
+#define qcm_alloc_int_urb(...) 0
+#define qcm_free_int(...)
+#endif
+
+
+#define CHECK_RET(ret, expr) \
+       if ((ret = expr) < 0) return ret
+
+/* Control Registers for the STVV6422 ASIC
+ * - this define is taken from the qc-usb-messenger code
+ */
+#define STV_ISO_ENABLE         0x1440
+#define ISOC_PACKET_SIZE       1023
+
+/* Chip identification number including revision indicator */
+#define CMOS_SENSOR_IDREV      0xE00A
+
+struct rgb {
+       u8 b;
+       u8 g;
+       u8 r;
+       u8 b2;
+       u8 g2;
+       u8 r2;
+};
+
+struct bayL0 {
+#ifdef __BIG_ENDIAN
+       u8 r;
+       u8 g;
+#elif __LITTLE_ENDIAN
+       u8 g;
+       u8 r;
+#else
+#error not byte order defined
+#endif
+};
+
+struct bayL1 {
+#ifdef __BIG_ENDIAN
+       u8 g;
+       u8 b;
+#elif __LITTLE_ENDIAN
+       u8 b;
+       u8 g;
+#else
+#error not byte order defined
+#endif
+};
+
+struct cam_size {
+       u16     width;
+       u16     height;
+       u8      cmd;
+};
+
+static const struct cam_size camera_sizes[] = {
+       { 160, 120, 0xf },
+       { 320, 240, 0x2 },
+};
+
+enum frame_sizes {
+       SIZE_160X120    = 0,
+       SIZE_320X240    = 1,
+};
+
+#define MAX_FRAME_SIZE SIZE_320X240
+
+struct qcm {
+       u16 colour;
+       u16 hue;
+       u16 brightness;
+       u16 contrast;
+       u16 whiteness;
+
+       u8 size;
+       int height;
+       int width;
+       u8 *scratch;
+       struct urb *button_urb;
+       u8 button_sts;
+       u8 button_sts_buf;
+
+#ifdef CONFIG_INPUT
+       struct input_dev *input;
+       char input_physname[64];
+#endif
+};
+
+struct regval {
+       u16 reg;
+       u8 val;
+};
+/* this table is derived from the
+qc-usb-messenger code */
+static const struct regval regval_table[] = {
+       { STV_ISO_ENABLE, 0x00 },
+       { 0x1436, 0x00 }, { 0x1432, 0x03 },
+       { 0x143a, 0xF9 }, { 0x0509, 0x38 },
+       { 0x050a, 0x38 }, { 0x050b, 0x38 },
+       { 0x050c, 0x2A }, { 0x050d, 0x01 },
+       { 0x1431, 0x00 }, { 0x1433, 0x34 },
+       { 0x1438, 0x18 }, { 0x1439, 0x00 },
+       { 0x143b, 0x05 }, { 0x143c, 0x00 },
+       { 0x143e, 0x01 }, { 0x143d, 0x00 },
+       { 0x1442, 0xe2 }, { 0x1500, 0xd0 },
+       { 0x1500, 0xd0 }, { 0x1500, 0x50 },
+       { 0x1501, 0xaf }, { 0x1502, 0xc2 },
+       { 0x1503, 0x45 }, { 0x1505, 0x02 },
+       { 0x150e, 0x8e }, { 0x150f, 0x37 },
+       { 0x15c0, 0x00 },
+};
+
+static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF };
+
+#endif /* quickcam_messenger_h */
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c
new file mode 100644 (file)
index 0000000..ed8542e
--- /dev/null
@@ -0,0 +1,187 @@
+/***************************************************************************
+ * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image       *
+ * Processor and Control Chip                                              *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
+ * driver maintained by Michel Xhaard <mxhaard@magic.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; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU 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 "zc0301_sensor.h"
+
+
+static struct zc0301_sensor pb0330;
+
+
+static int pb0330_init(struct zc0301_device* cam)
+{
+       int err = 0;
+
+       err += zc0301_write_reg(cam, 0x0000, 0x01);
+       err += zc0301_write_reg(cam, 0x0008, 0x03);
+       err += zc0301_write_reg(cam, 0x0010, 0x0A);
+       err += zc0301_write_reg(cam, 0x0002, 0x00);
+       err += zc0301_write_reg(cam, 0x0003, 0x02);
+       err += zc0301_write_reg(cam, 0x0004, 0x80);
+       err += zc0301_write_reg(cam, 0x0005, 0x01);
+       err += zc0301_write_reg(cam, 0x0006, 0xE0);
+       err += zc0301_write_reg(cam, 0x0001, 0x01);
+       err += zc0301_write_reg(cam, 0x0012, 0x05);
+       err += zc0301_write_reg(cam, 0x0012, 0x07);
+       err += zc0301_write_reg(cam, 0x0098, 0x00);
+       err += zc0301_write_reg(cam, 0x009A, 0x00);
+       err += zc0301_write_reg(cam, 0x011A, 0x00);
+       err += zc0301_write_reg(cam, 0x011C, 0x00);
+       err += zc0301_write_reg(cam, 0x0012, 0x05);
+
+       err += zc0301_i2c_write(cam, 0x01, 0x0006);
+       err += zc0301_i2c_write(cam, 0x02, 0x0011);
+       err += zc0301_i2c_write(cam, 0x03, 0x01E7);
+       err += zc0301_i2c_write(cam, 0x04, 0x0287);
+       err += zc0301_i2c_write(cam, 0x06, 0x0003);
+       err += zc0301_i2c_write(cam, 0x07, 0x3002);
+       err += zc0301_i2c_write(cam, 0x20, 0x1100);
+       err += zc0301_i2c_write(cam, 0x2F, 0xF7B0);
+       err += zc0301_i2c_write(cam, 0x30, 0x0005);
+       err += zc0301_i2c_write(cam, 0x31, 0x0000);
+       err += zc0301_i2c_write(cam, 0x34, 0x0100);
+       err += zc0301_i2c_write(cam, 0x35, 0x0060);
+       err += zc0301_i2c_write(cam, 0x3D, 0x068F);
+       err += zc0301_i2c_write(cam, 0x40, 0x01E0);
+       err += zc0301_i2c_write(cam, 0x58, 0x0078);
+       err += zc0301_i2c_write(cam, 0x62, 0x0411);
+
+       err += zc0301_write_reg(cam, 0x0087, 0x10);
+       err += zc0301_write_reg(cam, 0x0101, 0x37);
+       err += zc0301_write_reg(cam, 0x0012, 0x05);
+       err += zc0301_write_reg(cam, 0x0100, 0x0D);
+       err += zc0301_write_reg(cam, 0x0189, 0x06);
+       err += zc0301_write_reg(cam, 0x01AD, 0x00);
+       err += zc0301_write_reg(cam, 0x01C5, 0x03);
+       err += zc0301_write_reg(cam, 0x01CB, 0x13);
+       err += zc0301_write_reg(cam, 0x0250, 0x08);
+       err += zc0301_write_reg(cam, 0x0301, 0x08);
+       err += zc0301_write_reg(cam, 0x01A8, 0x60);
+       err += zc0301_write_reg(cam, 0x018D, 0x6C);
+       err += zc0301_write_reg(cam, 0x01AD, 0x09);
+       err += zc0301_write_reg(cam, 0x01AE, 0x15);
+       err += zc0301_write_reg(cam, 0x010A, 0x50);
+       err += zc0301_write_reg(cam, 0x010B, 0xF8);
+       err += zc0301_write_reg(cam, 0x010C, 0xF8);
+       err += zc0301_write_reg(cam, 0x010D, 0xF8);
+       err += zc0301_write_reg(cam, 0x010E, 0x50);
+       err += zc0301_write_reg(cam, 0x010F, 0xF8);
+       err += zc0301_write_reg(cam, 0x0110, 0xF8);
+       err += zc0301_write_reg(cam, 0x0111, 0xF8);
+       err += zc0301_write_reg(cam, 0x0112, 0x50);
+       err += zc0301_write_reg(cam, 0x0008, 0x03);
+       err += zc0301_write_reg(cam, 0x01C6, 0x08);
+       err += zc0301_write_reg(cam, 0x01CB, 0x0F);
+       err += zc0301_write_reg(cam, 0x010A, 0x50);
+       err += zc0301_write_reg(cam, 0x010B, 0xF8);
+       err += zc0301_write_reg(cam, 0x010C, 0xF8);
+       err += zc0301_write_reg(cam, 0x010D, 0xF8);
+       err += zc0301_write_reg(cam, 0x010E, 0x50);
+       err += zc0301_write_reg(cam, 0x010F, 0xF8);
+       err += zc0301_write_reg(cam, 0x0110, 0xF8);
+       err += zc0301_write_reg(cam, 0x0111, 0xF8);
+       err += zc0301_write_reg(cam, 0x0112, 0x50);
+       err += zc0301_write_reg(cam, 0x0180, 0x00);
+       err += zc0301_write_reg(cam, 0x0019, 0x00);
+
+       err += zc0301_i2c_write(cam, 0x05, 0x0066);
+       err += zc0301_i2c_write(cam, 0x09, 0x02B2);
+       err += zc0301_i2c_write(cam, 0x10, 0x0002);
+
+       err += zc0301_write_reg(cam, 0x011D, 0x60);
+       err += zc0301_write_reg(cam, 0x0190, 0x00);
+       err += zc0301_write_reg(cam, 0x0191, 0x07);
+       err += zc0301_write_reg(cam, 0x0192, 0x8C);
+       err += zc0301_write_reg(cam, 0x0195, 0x00);
+       err += zc0301_write_reg(cam, 0x0196, 0x00);
+       err += zc0301_write_reg(cam, 0x0197, 0x8A);
+       err += zc0301_write_reg(cam, 0x018C, 0x10);
+       err += zc0301_write_reg(cam, 0x018F, 0x20);
+       err += zc0301_write_reg(cam, 0x01A9, 0x14);
+       err += zc0301_write_reg(cam, 0x01AA, 0x24);
+       err += zc0301_write_reg(cam, 0x001D, 0xD7);
+       err += zc0301_write_reg(cam, 0x001E, 0xF0);
+       err += zc0301_write_reg(cam, 0x001F, 0xF8);
+       err += zc0301_write_reg(cam, 0x0020, 0xFF);
+       err += zc0301_write_reg(cam, 0x01AD, 0x09);
+       err += zc0301_write_reg(cam, 0x01AE, 0x15);
+       err += zc0301_write_reg(cam, 0x0180, 0x40);
+       err += zc0301_write_reg(cam, 0x0180, 0x42);
+
+       msleep(100);
+
+       return err;
+}
+
+
+static struct zc0301_sensor pb0330 = {
+       .name = "PB-0330",
+       .init = &pb0330_init,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_JPEG,
+               .priv = 8,
+       },
+};
+
+
+int zc0301_probe_pb0330(struct zc0301_device* cam)
+{
+       int r0, err = 0;
+
+       err += zc0301_write_reg(cam, 0x0000, 0x01);
+       err += zc0301_write_reg(cam, 0x0010, 0x0a);
+       err += zc0301_write_reg(cam, 0x0001, 0x01);
+       err += zc0301_write_reg(cam, 0x0012, 0x03);
+       err += zc0301_write_reg(cam, 0x0012, 0x01);
+
+       msleep(10);
+
+       r0 = zc0301_i2c_read(cam, 0x00, 2);
+
+       if (r0 < 0 || err)
+               return -EIO;
+
+       if (r0 != 0x8243)
+               return -ENODEV;
+
+       zc0301_attach_sensor(cam, &pb0330);
+
+       return 0;
+}
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
new file mode 100644 (file)
index 0000000..a0ba07c
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ *  drivers/mtd/nand/ams-delta.c
+ *
+ *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ *  Derived from drivers/mtd/toto.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.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   Amstrad E3 (Delta).
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/board-ams-delta.h>
+
+/*
+ * MTD structure for E3 (Delta)
+ */
+static struct mtd_info *ams_delta_mtd = NULL;
+
+#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
+
+/*
+ * Define partitions for flash devices
+ */
+
+static struct mtd_partition partition_info[] = {
+       { .name         = "Kernel",
+         .offset       = 0,
+         .size         = 3 * SZ_1M + SZ_512K },
+       { .name         = "u-boot",
+         .offset       = 3 * SZ_1M + SZ_512K,
+         .size         = SZ_256K },
+       { .name         = "u-boot params",
+         .offset       = 3 * SZ_1M + SZ_512K + SZ_256K,
+         .size         = SZ_256K },
+       { .name         = "Amstrad LDR",
+         .offset       = 4 * SZ_1M,
+         .size         = SZ_256K },
+       { .name         = "File system",
+         .offset       = 4 * SZ_1M + 1 * SZ_256K,
+         .size         = 27 * SZ_1M },
+       { .name         = "PBL reserved",
+         .offset       = 32 * SZ_1M - 3 * SZ_256K,
+         .size         =  3 * SZ_256K },
+};
+
+static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+{
+       struct nand_chip *this = mtd->priv;
+
+       omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
+       omap_writew(byte, this->IO_ADDR_W);
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
+       ndelay(40);
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
+                              AMS_DELTA_LATCH2_NAND_NWE);
+}
+
+static u_char ams_delta_read_byte(struct mtd_info *mtd)
+{
+       u_char res;
+       struct nand_chip *this = mtd->priv;
+
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
+       ndelay(40);
+       omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
+       res = omap_readw(this->IO_ADDR_R);
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
+                              AMS_DELTA_LATCH2_NAND_NRE);
+
+       return res;
+}
+
+static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
+                               int len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               ams_delta_write_byte(mtd, buf[i]);
+}
+
+static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               buf[i] = ams_delta_read_byte(mtd);
+}
+
+static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
+                               int len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               if (buf[i] != ams_delta_read_byte(mtd))
+                       return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * Command control function
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 7
+ * NAND_ALE: bit 2 -> bit 6
+ */
+static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
+                               unsigned int ctrl)
+{
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned long bits;
+
+               bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0;
+               bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0;
+               bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0;
+
+               ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE |
+                               AMS_DELTA_LATCH2_NAND_ALE |
+                               AMS_DELTA_LATCH2_NAND_NCE, bits);
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               ams_delta_write_byte(mtd, cmd);
+}
+
+static int ams_delta_nand_ready(struct mtd_info *mtd)
+{
+       return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init ams_delta_init(void)
+{
+       struct nand_chip *this;
+       int err = 0;
+
+       /* Allocate memory for MTD device structure and private data */
+       ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
+                               sizeof(struct nand_chip), GFP_KERNEL);
+       if (!ams_delta_mtd) {
+               printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       ams_delta_mtd->owner = THIS_MODULE;
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *) (&ams_delta_mtd[1]);
+
+       /* Initialize structures */
+       memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       ams_delta_mtd->priv = this;
+
+       /* Set address of NAND IO lines */
+       this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
+       this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
+       this->read_byte = ams_delta_read_byte;
+       this->write_buf = ams_delta_write_buf;
+       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)) {
+               this->dev_ready = ams_delta_nand_ready;
+       } else {
+               this->dev_ready = NULL;
+               printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
+       }
+       /* 25 us command delay time */
+       this->chip_delay = 30;
+       this->ecc.mode = NAND_ECC_SOFT;
+
+       /* Set chip enabled, but  */
+       ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
+                                         AMS_DELTA_LATCH2_NAND_NWE |
+                                         AMS_DELTA_LATCH2_NAND_NCE |
+                                         AMS_DELTA_LATCH2_NAND_NWP);
+
+       /* Scan to find existance of the device */
+       if (nand_scan(ams_delta_mtd, 1)) {
+               err = -ENXIO;
+               goto out_mtd;
+       }
+
+       /* Register the partitions */
+       add_mtd_partitions(ams_delta_mtd, partition_info,
+                          ARRAY_SIZE(partition_info));
+
+       goto out;
+
+ out_mtd:
+       kfree(ams_delta_mtd);
+ out:
+       return err;
+}
+
+module_init(ams_delta_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit ams_delta_cleanup(void)
+{
+       /* Release resources, unregister device */
+       nand_release(ams_delta_mtd);
+
+       /* Free the MTD device structure */
+       kfree(ams_delta_mtd);
+}
+module_exit(ams_delta_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
+MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
new file mode 100644 (file)
index 0000000..e0a1d38
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * drivers/mtd/nand/cs553x_nand.c
+ *
+ * (C) 2005, 2006 Red Hat Inc.
+ *
+ * Author: David Woodhouse <dwmw2@infradead.org>
+ *        Tom Sylla <tom.sylla@amd.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.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash controller found on 
+ *   the AMD CS5535/CS5536 companion chipsets for the Geode processor.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/msr.h>
+#include <asm/io.h>
+
+#define NR_CS553X_CONTROLLERS  4
+
+#define MSR_DIVIL_GLD_CAP      0x51400000      /* DIVIL capabilitiies */
+#define CAP_CS5535             0x2df000ULL
+#define CAP_CS5536             0x5df500ULL
+
+/* NAND Timing MSRs */
+#define MSR_NANDF_DATA         0x5140001b      /* NAND Flash Data Timing MSR */
+#define MSR_NANDF_CTL          0x5140001c      /* NAND Flash Control Timing */
+#define MSR_NANDF_RSVD         0x5140001d      /* Reserved */
+
+/* NAND BAR MSRs */
+#define MSR_DIVIL_LBAR_FLSH0   0x51400010      /* Flash Chip Select 0 */
+#define MSR_DIVIL_LBAR_FLSH1   0x51400011      /* Flash Chip Select 1 */
+#define MSR_DIVIL_LBAR_FLSH2   0x51400012      /* Flash Chip Select 2 */
+#define MSR_DIVIL_LBAR_FLSH3   0x51400013      /* Flash Chip Select 3 */
+       /* Each made up of... */
+#define FLSH_LBAR_EN           (1ULL<<32)
+#define FLSH_NOR_NAND          (1ULL<<33)      /* 1 for NAND */
+#define FLSH_MEM_IO            (1ULL<<34)      /* 1 for MMIO */
+       /* I/O BARs have BASE_ADDR in bits 15:4, IO_MASK in 47:36 */
+       /* MMIO BARs have BASE_ADDR in bits 31:12, MEM_MASK in 63:44 */
+
+/* Pin function selection MSR (IDE vs. flash on the IDE pins) */
+#define MSR_DIVIL_BALL_OPTS    0x51400015
+#define PIN_OPT_IDE            (1<<0)  /* 0 for flash, 1 for IDE */
+
+/* Registers within the NAND flash controller BAR -- memory mapped */
+#define MM_NAND_DATA           0x00    /* 0 to 0x7ff, in fact */
+#define MM_NAND_CTL            0x800   /* Any even address 0x800-0x80e */
+#define MM_NAND_IO             0x801   /* Any odd address 0x801-0x80f */
+#define MM_NAND_STS            0x810
+#define MM_NAND_ECC_LSB                0x811
+#define MM_NAND_ECC_MSB                0x812
+#define MM_NAND_ECC_COL                0x813
+#define MM_NAND_LAC            0x814
+#define MM_NAND_ECC_CTL                0x815
+
+/* Registers within the NAND flash controller BAR -- I/O mapped */
+#define IO_NAND_DATA           0x00    /* 0 to 3, in fact */
+#define IO_NAND_CTL            0x04
+#define IO_NAND_IO             0x05
+#define IO_NAND_STS            0x06
+#define IO_NAND_ECC_CTL                0x08
+#define IO_NAND_ECC_LSB                0x09
+#define IO_NAND_ECC_MSB                0x0a
+#define IO_NAND_ECC_COL                0x0b
+#define IO_NAND_LAC            0x0c
+
+#define CS_NAND_CTL_DIST_EN    (1<<4)  /* Enable NAND Distract interrupt */
+#define CS_NAND_CTL_RDY_INT_MASK       (1<<3)  /* Enable RDY/BUSY# interrupt */
+#define CS_NAND_CTL_ALE                (1<<2)
+#define CS_NAND_CTL_CLE                (1<<1)
+#define CS_NAND_CTL_CE         (1<<0)  /* Keep low; 1 to reset */
+
+#define CS_NAND_STS_FLASH_RDY  (1<<3)
+#define CS_NAND_CTLR_BUSY      (1<<2)
+#define CS_NAND_CMD_COMP       (1<<1)
+#define CS_NAND_DIST_ST                (1<<0)
+
+#define CS_NAND_ECC_PARITY     (1<<2)
+#define CS_NAND_ECC_CLRECC     (1<<1)
+#define CS_NAND_ECC_ENECC      (1<<0)
+
+static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       while (unlikely(len > 0x800)) {
+               memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
+               buf += 0x800;
+               len -= 0x800;
+       }
+       memcpy_fromio(buf, this->IO_ADDR_R, len);
+}
+
+static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       while (unlikely(len > 0x800)) {
+               memcpy_toio(this->IO_ADDR_R, buf, 0x800);
+               buf += 0x800;
+               len -= 0x800;
+       }
+       memcpy_toio(this->IO_ADDR_R, buf, len);
+}
+
+static unsigned char cs553x_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *this = mtd->priv;
+       return readb(this->IO_ADDR_R);
+}
+
+static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
+{
+       struct nand_chip *this = mtd->priv;
+       int i = 100000;
+
+       while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
+               udelay(1);
+               i--;
+       }
+       writeb(byte, this->IO_ADDR_W + 0x801);
+}
+
+static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
+                            unsigned int ctrl)
+{
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
+               writeb(ctl, mmio_base + MM_NAND_CTL);
+       }
+       if (cmd != NAND_CMD_NONE)
+               cs553x_write_byte(mtd, cmd);
+}
+
+static int cs553x_device_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+       unsigned char foo = readb(mmio_base + MM_NAND_STS);
+
+       return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
+}
+
+static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+
+       writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
+}
+
+static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+       uint32_t ecc;
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+
+       ecc = readl(mmio_base + MM_NAND_STS);
+
+       ecc_code[1] = ecc >> 8;
+       ecc_code[0] = ecc >> 16;
+       ecc_code[2] = ecc >> 24;
+       return 0;
+}
+
+static struct mtd_info *cs553x_mtd[4];
+
+static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
+{
+       int err = 0;
+       struct nand_chip *this;
+       struct mtd_info *new_mtd;
+
+       printk(KERN_NOTICE "Probing CS553x NAND controller CS#%d at %sIO 0x%08lx\n", cs, mmio?"MM":"P", adr);
+
+       if (!mmio) {
+               printk(KERN_NOTICE "PIO mode not yet implemented for CS553X NAND controller\n");
+               return -ENXIO;
+       }
+
+       /* Allocate memory for MTD device structure and private data */
+       new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+       if (!new_mtd) {
+               printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *)(&new_mtd[1]);
+
+       /* Initialize structures */
+       memset(new_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       new_mtd->priv = this;
+       new_mtd->owner = THIS_MODULE;
+
+       /* map physical address */
+       this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096);
+       if (!this->IO_ADDR_R) {
+               printk(KERN_WARNING "ioremap cs553x NAND @0x%08lx failed\n", adr);
+               err = -EIO;
+               goto out_mtd;
+       }
+
+       this->cmd_ctrl = cs553x_hwcontrol;
+       this->dev_ready = cs553x_device_ready;
+       this->read_byte = cs553x_read_byte;
+       this->read_buf = cs553x_read_buf;
+       this->write_buf = cs553x_write_buf;
+
+       this->chip_delay = 0;
+
+       this->ecc.mode = NAND_ECC_HW;
+       this->ecc.size = 256;
+       this->ecc.bytes = 3;
+       this->ecc.hwctl  = cs_enable_hwecc;
+       this->ecc.calculate = cs_calculate_ecc;
+       this->ecc.correct  = nand_correct_data;
+
+       /* Enable the following for a flash based bad block table */
+       this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+
+       /* Scan to find existance of the device */
+       if (nand_scan(new_mtd, 1)) {
+               err = -ENXIO;
+               goto out_ior;
+       }
+
+       cs553x_mtd[cs] = new_mtd;
+       goto out;
+
+out_ior:
+       iounmap((void *)this->IO_ADDR_R);
+out_mtd:
+       kfree(new_mtd);
+out:
+       return err;
+}
+
+static int is_geode(void)
+{
+       /* These are the CPUs which will have a CS553[56] companion chip */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+           boot_cpu_data.x86 == 5 &&
+           boot_cpu_data.x86_model == 10)
+               return 1; /* Geode LX */
+
+       if ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC ||
+            boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX) &&
+           boot_cpu_data.x86 == 5 &&
+           boot_cpu_data.x86_model == 5)
+               return 1; /* Geode GX (née GX2) */
+
+       return 0;
+}
+
+static int __init cs553x_init(void)
+{
+       int err = -ENXIO;
+       int i;
+       uint64_t val;
+
+       /* If the CPU isn't a Geode GX or LX, abort */
+       if (!is_geode())
+               return -ENXIO;
+
+       /* If it doesn't have the CS553[56], abort */
+       rdmsrl(MSR_DIVIL_GLD_CAP, val);
+       val &= ~0xFFULL;
+       if (val != CAP_CS5535 && val != CAP_CS5536)
+               return -ENXIO;
+
+       /* If it doesn't have the NAND controller enabled, abort */
+       rdmsrl(MSR_DIVIL_BALL_OPTS, val);
+       if (val & 1) {
+               printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n");
+               return -ENXIO;
+       }
+
+       for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+               rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val);
+
+               if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND))
+                       err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
+       }
+
+       /* Register all devices together here. This means we can easily hack it to 
+          do mtdconcat etc. if we want to. */
+       for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+               if (cs553x_mtd[i]) {
+                       add_mtd_device(cs553x_mtd[i]);
+
+                       /* If any devices registered, return success. Else the last error. */
+                       err = 0;
+               }
+       }
+
+       return err;
+}
+
+module_init(cs553x_init);
+
+static void __exit cs553x_cleanup(void)
+{
+       int i;
+
+       for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+               struct mtd_info *mtd = cs553x_mtd[i];
+               struct nand_chip *this;
+               void __iomem *mmio_base;
+
+               if (!mtd)
+                       break;
+
+               this = cs553x_mtd[i]->priv;
+               mmio_base = this->IO_ADDR_R;
+
+               /* Release resources, unregister device */
+               nand_release(cs553x_mtd[i]);
+               cs553x_mtd[i] = NULL;
+
+               /* unmap physical adress */
+               iounmap(mmio_base);
+
+               /* Free the MTD device structure */
+               kfree(mtd);
+       }
+}
+
+module_exit(cs553x_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("NAND controller driver for AMD CS5535/CS5536 companion chip");
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
new file mode 100644 (file)
index 0000000..e5bd88f
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ *  drivers/mtd/ndfc.c
+ *
+ *  Overview:
+ *   Platform independend driver for NDFC (NanD Flash Controller)
+ *   integrated into EP440 cores
+ *
+ *  Author: Thomas Gleixner
+ *
+ *  Copyright 2006 IBM
+ *
+ *  This program is free software; you can redistribute         it and/or modify it
+ *  under  the terms of         the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/ndfc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/ibm44x.h>
+
+struct ndfc_nand_mtd {
+       struct mtd_info                 mtd;
+       struct nand_chip                chip;
+       struct platform_nand_chip       *pl_chip;
+};
+
+static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
+
+struct ndfc_controller {
+       void __iomem            *ndfcbase;
+       struct nand_hw_control  ndfc_control;
+       atomic_t                childs_active;
+};
+
+static struct ndfc_controller ndfc_ctrl;
+
+static void ndfc_select_chip(struct mtd_info *mtd, int chip)
+{
+       uint32_t ccr;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       struct nand_chip *nandchip = mtd->priv;
+       struct ndfc_nand_mtd *nandmtd = nandchip->priv;
+       struct platform_nand_chip *pchip = nandmtd->pl_chip;
+
+       ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+       if (chip >= 0) {
+               ccr &= ~NDFC_CCR_BS_MASK;
+               ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+       } else
+               ccr |= NDFC_CCR_RESET_CE;
+       writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+}
+
+static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       if (ctrl & NAND_CLE)
+               writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD);
+       else
+               writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
+}
+
+static int ndfc_ready(struct mtd_info *mtd)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+       return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+}
+
+static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       uint32_t ccr;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+       ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+       ccr |= NDFC_CCR_RESET_ECC;
+       __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+       wmb();
+}
+
+static int ndfc_calculate_ecc(struct mtd_info *mtd,
+                             const u_char *dat, u_char *ecc_code)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t ecc;
+       uint8_t *p = (uint8_t *)&ecc;
+
+       wmb();
+       ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
+       ecc_code[0] = p[1];
+       ecc_code[1] = p[2];
+       ecc_code[2] = p[3];
+
+       return 0;
+}
+
+/*
+ * Speedups for buffer read/write/verify
+ *
+ * NDFC allows 32bit read/write of data. So we can speed up the buffer
+ * functions. No further checking, as nand_base will always read/write
+ * page aligned.
+ */
+static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t *p = (uint32_t *) buf;
+
+       for(;len > 0; len -= 4)
+               *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+}
+
+static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t *p = (uint32_t *) buf;
+
+       for(;len > 0; len -= 4)
+               __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+}
+
+static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t *p = (uint32_t *) buf;
+
+       for(;len > 0; len -= 4)
+               if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+                       return -EFAULT;
+       return 0;
+}
+
+/*
+ * Initialize chip structure
+ */
+static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       struct nand_chip *chip = &mtd->chip;
+
+       chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
+       chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
+       chip->cmd_ctrl = ndfc_hwcontrol;
+       chip->dev_ready = ndfc_ready;
+       chip->select_chip = ndfc_select_chip;
+       chip->chip_delay = 50;
+       chip->priv = mtd;
+       chip->options = mtd->pl_chip->options;
+       chip->controller = &ndfc->ndfc_control;
+       chip->read_buf = ndfc_read_buf;
+       chip->write_buf = ndfc_write_buf;
+       chip->verify_buf = ndfc_verify_buf;
+       chip->ecc.correct = nand_correct_data;
+       chip->ecc.hwctl = ndfc_enable_hwecc;
+       chip->ecc.calculate = ndfc_calculate_ecc;
+       chip->ecc.mode = NAND_ECC_HW;
+       chip->ecc.size = 256;
+       chip->ecc.bytes = 3;
+       chip->ecclayout = mtd->pl_chip->ecclayout;
+       mtd->mtd.priv = chip;
+       mtd->mtd.owner = THIS_MODULE;
+}
+
+static int ndfc_chip_probe(struct platform_device *pdev)
+{
+       struct platform_nand_chip *nc = pdev->dev.platform_data;
+       struct ndfc_chip_settings *settings = nc->priv;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       struct ndfc_nand_mtd *nandmtd;
+
+       if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
+               return -EINVAL;
+
+       /* Set the bank settings */
+       __raw_writel(settings->bank_settings,
+                    ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
+
+       nandmtd = &ndfc_mtd[pdev->id];
+       if (nandmtd->pl_chip)
+               return -EBUSY;
+
+       nandmtd->pl_chip = nc;
+       ndfc_chip_init(nandmtd);
+
+       /* Scan for chips */
+       if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
+               nandmtd->pl_chip = NULL;
+               return -ENODEV;
+       }
+
+#ifdef CONFIG_MTD_PARTITIONS
+       printk("Number of partitions %d\n", nc->nr_partitions);
+       if (nc->nr_partitions) {
+               /* Add the full device, so complete dumps can be made */
+               add_mtd_device(&nandmtd->mtd);
+               add_mtd_partitions(&nandmtd->mtd, nc->partitions,
+                                  nc->nr_partitions);
+
+       } else
+#else
+               add_mtd_device(&nandmtd->mtd);
+#endif
+
+       atomic_inc(&ndfc->childs_active);
+       return 0;
+}
+
+static int ndfc_chip_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int ndfc_nand_probe(struct platform_device *pdev)
+{
+       struct platform_nand_ctrl *nc = pdev->dev.platform_data;
+       struct ndfc_controller_settings *settings = nc->priv;
+       struct resource *res = pdev->resource;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       unsigned long long phys = settings->ndfc_erpn | res->start;
+
+       ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
+       if (!ndfc->ndfcbase) {
+               printk(KERN_ERR "NDFC: ioremap failed\n");
+               return -EIO;
+       }
+
+       __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+
+       spin_lock_init(&ndfc->ndfc_control.lock);
+       init_waitqueue_head(&ndfc->ndfc_control.wq);
+
+       platform_set_drvdata(pdev, ndfc);
+
+       printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
+              __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+
+       return 0;
+}
+
+static int ndfc_nand_remove(struct platform_device *pdev)
+{
+       struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+
+       if (atomic_read(&ndfc->childs_active))
+               return -EBUSY;
+
+       if (ndfc) {
+               platform_set_drvdata(pdev, NULL);
+               iounmap(ndfc_ctrl.ndfcbase);
+               ndfc_ctrl.ndfcbase = NULL;
+       }
+       return 0;
+}
+
+/* driver device registration */
+
+static struct platform_driver ndfc_chip_driver = {
+       .probe          = ndfc_chip_probe,
+       .remove         = ndfc_chip_remove,
+       .driver         = {
+               .name   = "ndfc-chip",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static struct platform_driver ndfc_nand_driver = {
+       .probe          = ndfc_nand_probe,
+       .remove         = ndfc_nand_remove,
+       .driver         = {
+               .name   = "ndfc-nand",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init ndfc_nand_init(void)
+{
+       int ret;
+
+       spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
+       init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
+
+       ret = platform_driver_register(&ndfc_nand_driver);
+       if (!ret)
+               ret = platform_driver_register(&ndfc_chip_driver);
+       return ret;
+}
+
+static void __exit ndfc_nand_exit(void)
+{
+       platform_driver_unregister(&ndfc_chip_driver);
+       platform_driver_unregister(&ndfc_nand_driver);
+}
+
+module_init(ndfc_nand_init);
+module_exit(ndfc_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Platform driver for NDFC");
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
new file mode 100644 (file)
index 0000000..f400810
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * drivers/mtd/nand/ts7250.c
+ *
+ * Copyright (C) 2004 Technologic Systems (support@embeddedARM.com)
+ *
+ * Derived from drivers/mtd/nand/edb7312.c
+ *   Copyright (C) 2004 Marius Gröger (mag@sysgo.de)
+ *
+ * Derived from drivers/mtd/nand/autcpu12.c
+ *   Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   TS-7250 board which utilizes a Samsung 32 Mbyte part.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+/*
+ * MTD structure for TS7250 board
+ */
+static struct mtd_info *ts7250_mtd = NULL;
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+#define NUM_PARTITIONS 3
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info32[] = {
+       {
+               .name           = "TS-BOOTROM",
+               .offset         = 0x00000000,
+               .size           = 0x00004000,
+       }, {
+               .name           = "Linux",
+               .offset         = 0x00004000,
+               .size           = 0x01d00000,
+       }, {
+               .name           = "RedBoot",
+               .offset         = 0x01d04000,
+               .size           = 0x002fc000,
+       },
+};
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info128[] = {
+       {
+               .name           = "TS-BOOTROM",
+               .offset         = 0x00000000,
+               .size           = 0x00004000,
+       }, {
+               .name           = "Linux",
+               .offset         = 0x00004000,
+               .size           = 0x07d00000,
+       }, {
+               .name           = "RedBoot",
+               .offset         = 0x07d04000,
+               .size           = 0x002fc000,
+       },
+};
+#endif
+
+
+/*
+ *     hardware specific access to control-lines
+ *
+ *     ctrl:
+ *     NAND_NCE: bit 0 -> bit 2
+ *     NAND_CLE: bit 1 -> bit 1
+ *     NAND_ALE: bit 2 -> bit 0
+ */
+static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
+               unsigned char bits;
+
+               bits = (ctrl & NAND_NCE) << 2;
+               bits |= ctrl & NAND_CLE;
+               bits |= (ctrl & NAND_ALE) >> 2;
+
+               __raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr);
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
+}
+
+/*
+ *     read device ready pin
+ */
+static int ts7250_device_ready(struct mtd_info *mtd)
+{
+       return __raw_readb(TS72XX_NAND_BUSY_VIRT_BASE) & 0x20;
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init ts7250_init(void)
+{
+       struct nand_chip *this;
+       const char *part_type = 0;
+       int mtd_parts_nb = 0;
+       struct mtd_partition *mtd_parts = 0;
+
+       if (!machine_is_ts72xx() || board_is_ts7200())
+               return -ENXIO;
+
+       /* Allocate memory for MTD device structure and private data */
+       ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+       if (!ts7250_mtd) {
+               printk("Unable to allocate TS7250 NAND MTD device structure.\n");
+               return -ENOMEM;
+       }
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *)(&ts7250_mtd[1]);
+
+       /* Initialize structures */
+       memset(ts7250_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       ts7250_mtd->priv = this;
+       ts7250_mtd->owner = THIS_MODULE;
+
+       /* insert callbacks */
+       this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE;
+       this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE;
+       this->cmd_ctrl = ts7250_hwcontrol;
+       this->dev_ready = ts7250_device_ready;
+       this->chip_delay = 15;
+       this->ecc.mode = NAND_ECC_SOFT;
+
+       printk("Searching for NAND flash...\n");
+       /* Scan to find existence of the device */
+       if (nand_scan(ts7250_mtd, 1)) {
+               kfree(ts7250_mtd);
+               return -ENXIO;
+       }
+#ifdef CONFIG_MTD_PARTITIONS
+       ts7250_mtd->name = "ts7250-nand";
+       mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0);
+       if (mtd_parts_nb > 0)
+               part_type = "command line";
+       else
+               mtd_parts_nb = 0;
+#endif
+       if (mtd_parts_nb == 0) {
+               mtd_parts = partition_info32;
+               if (ts7250_mtd->size >= (128 * 0x100000))
+                       mtd_parts = partition_info128;
+               mtd_parts_nb = NUM_PARTITIONS;
+               part_type = "static";
+       }
+
+       /* Register the partitions */
+       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+       add_mtd_partitions(ts7250_mtd, mtd_parts, mtd_parts_nb);
+
+       /* Return happy */
+       return 0;
+}
+
+module_init(ts7250_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit ts7250_cleanup(void)
+{
+       /* Unregister the device */
+       del_mtd_device(ts7250_mtd);
+
+       /* Free the MTD device structure */
+       kfree(ts7250_mtd);
+}
+
+module_exit(ts7250_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jesse Off <joff@embeddedARM.com>");
+MODULE_DESCRIPTION("MTD map driver for Technologic Systems TS-7250 board");
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h
new file mode 100644 (file)
index 0000000..e980527
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef FS_ENET_FEC_H
+#define FS_ENET_FEC_H
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY   0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS        64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR 0x80000000U     /* Heartbeat error          */
+#define FEC_ENET_BABR  0x40000000U     /* Babbling receiver        */
+#define FEC_ENET_BABT  0x20000000U     /* Babbling transmitter     */
+#define FEC_ENET_GRA   0x10000000U     /* Graceful stop complete   */
+#define FEC_ENET_TXF   0x08000000U     /* Full frame transmitted   */
+#define FEC_ENET_TXB   0x04000000U     /* A buffer was transmitted */
+#define FEC_ENET_RXF   0x02000000U     /* Full frame received      */
+#define FEC_ENET_RXB   0x01000000U     /* A buffer was received    */
+#define FEC_ENET_MII   0x00800000U     /* MII interrupt            */
+#define FEC_ENET_EBERR 0x00400000U     /* SDMA bus error           */
+
+#define FEC_ECNTRL_PINMUX      0x00000004
+#define FEC_ECNTRL_ETHER_EN    0x00000002
+#define FEC_ECNTRL_RESET       0x00000001
+
+#define FEC_RCNTRL_BC_REJ      0x00000010
+#define FEC_RCNTRL_PROM                0x00000008
+#define FEC_RCNTRL_MII_MODE    0x00000004
+#define FEC_RCNTRL_DRT         0x00000002
+#define FEC_RCNTRL_LOOP                0x00000001
+
+#define FEC_TCNTRL_FDEN                0x00000004
+#define FEC_TCNTRL_HBC         0x00000002
+#define FEC_TCNTRL_GTS         0x00000001
+
+
+
+/*
+ * Delay to wait for FEC reset command to complete (in us)
+ */
+#define FEC_RESET_DELAY                50
+#endif
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
new file mode 100644 (file)
index 0000000..1328e10
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+#include "fec.h"
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG)       (0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end             0
+
+#define FEC_MII_LOOPS  10000
+
+static int match_has_phy (struct device *dev, void* data)
+{
+       struct platform_device* pdev = container_of(dev, struct platform_device, dev);
+       struct fs_platform_info* fpi;
+       if(strcmp(pdev->name, (char*)data))
+       {
+           return 0;
+       }
+
+       fpi = pdev->dev.platform_data;
+       if((fpi)&&(fpi->has_phy))
+               return 1;
+       return 0;
+}
+
+static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
+{
+       struct resource *r;
+       fec_t *fecp;
+       char* name = "fsl-cpm-fec";
+
+       /* we need fec in order to be useful */
+       struct platform_device *fec_pdev =
+               container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
+                               struct platform_device, dev);
+
+       if(fec_pdev == NULL) {
+               printk(KERN_ERR"Unable to find PHY for %s", name);
+               return -ENODEV;
+       }
+
+       r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
+
+       fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t));
+       fec->mii_speed = fmpi->mii_speed;
+
+       setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);     /* MII enable */
+       setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+       out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+       out_be32(&fecp->fec_mii_speed, fec->mii_speed);
+
+       return 0;
+}
+
+static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
+{
+       struct fec_info* fec = bus->priv;
+       fec_t *fecp = fec->fecp;
+       int i, ret = -1;
+
+       if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+               BUG();
+
+       /* Add PHY address to register command.  */
+       out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
+
+       for (i = 0; i < FEC_MII_LOOPS; i++)
+               if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+                       break;
+
+       if (i < FEC_MII_LOOPS) {
+               out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+               ret = in_be32(&fecp->fec_mii_data) & 0xffff;
+       }
+
+       return ret;
+
+}
+
+static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+       struct fec_info* fec = bus->priv;
+       fec_t *fecp = fec->fecp;
+       int i;
+
+       /* this must never happen */
+       if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+               BUG();
+
+       /* Add PHY address to register command.  */
+       out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
+
+       for (i = 0; i < FEC_MII_LOOPS; i++)
+               if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+                       break;
+
+       if (i < FEC_MII_LOOPS)
+               out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+
+       return 0;
+
+}
+
+static int fs_enet_fec_mii_reset(struct mii_bus *bus)
+{
+       /* nothing here - for now */
+       return 0;
+}
+
+static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fs_mii_fec_platform_info *pdata;
+       struct mii_bus *new_bus;
+       struct fec_info *fec;
+       int err = 0;
+       if (NULL == dev)
+               return -EINVAL;
+       new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+       if (NULL == new_bus)
+               return -ENOMEM;
+
+       fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
+
+       if (NULL == fec)
+               return -ENOMEM;
+
+       new_bus->name = "FEC MII Bus",
+       new_bus->read = &fs_enet_fec_mii_read,
+       new_bus->write = &fs_enet_fec_mii_write,
+       new_bus->reset = &fs_enet_fec_mii_reset,
+       new_bus->id = pdev->id;
+
+       pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+
+       if (NULL == pdata) {
+               printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
+               return -ENODEV;
+       }
+
+       /*set up workspace*/
+
+       fs_mii_fec_init(fec, pdata);
+       new_bus->priv = fec;
+
+       new_bus->irq = pdata->irq;
+
+       new_bus->dev = dev;
+       dev_set_drvdata(dev, new_bus);
+
+       err = mdiobus_register(new_bus);
+
+       if (0 != err) {
+               printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+                               new_bus->name);
+               goto bus_register_fail;
+       }
+
+       return 0;
+
+bus_register_fail:
+       kfree(new_bus);
+
+       return err;
+}
+
+
+static int fs_enet_fec_mdio_remove(struct device *dev)
+{
+       struct mii_bus *bus = dev_get_drvdata(dev);
+
+       mdiobus_unregister(bus);
+
+       dev_set_drvdata(dev, NULL);
+       kfree(bus->priv);
+
+       bus->priv = NULL;
+       kfree(bus);
+
+       return 0;
+}
+
+static struct device_driver fs_enet_fec_mdio_driver = {
+       .name = "fsl-cpm-fec-mdio",
+       .bus = &platform_bus_type,
+       .probe = fs_enet_fec_mdio_probe,
+       .remove = fs_enet_fec_mdio_remove,
+};
+
+int fs_enet_mdio_fec_init(void)
+{
+       return driver_register(&fs_enet_fec_mdio_driver);
+}
+
+void fs_enet_mdio_fec_exit(void)
+{
+       driver_unregister(&fs_enet_fec_mdio_driver);
+}
+
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
new file mode 100644 (file)
index 0000000..415ba8d
--- /dev/null
@@ -0,0 +1,1008 @@
+/*****************************************************************************
+*
+* Filename:      mcs7780.c
+* Version:       0.4-alpha
+* Description:   Irda MosChip USB Dongle Driver
+* Authors:       Lukasz Stelmach <stlman@poczta.fm>
+*               Brian Pugh <bpugh@cs.pdx.edu>
+*               Judy Fischbach <jfisch@cs.pdx.edu>
+*
+*       Based on stir4200 driver, but some things done differently.
+*       Based on earlier driver by Paul Stewart <stewart@parc.com>
+*
+*       Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+*       Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+*       Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+*       Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+*       Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+*       Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*       Copyright (C) 2005, Judy Fischbach <jfisch@cs.pdx.edu>
+*
+*       This program is free software; you can redistribute it and/or modify
+*       it under the terms of the GNU General Public License as published by
+*       the Free Software Foundation; either version 2 of the License, or
+*       (at your option) any later version.
+*
+*       This program is distributed in the hope that it will be useful,
+*       but WITHOUT ANY WARRANTY; without even the implied warranty of
+*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*       GNU 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.
+*
+*****************************************************************************/
+
+/*
+ * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither
+ * compatibile with irda-usb nor with stir4200. Although it is quite
+ * similar to the later as far as general idea of operation is concerned.
+ * That is it requires the software to do all the framing job at SIR speeds.
+ * The hardware does take care of the framing at MIR and FIR speeds.
+ * It supports all speeds from 2400 through 4Mbps
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+#include "mcs7780.h"
+
+#define MCS_VENDOR_ID 0x9710
+#define MCS_PRODUCT_ID 0x7780
+
+static struct usb_device_id mcs_table[] = {
+       /* MosChip Corp.,  MCS7780 FIR-USB Adapter */
+       {USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)},
+       {},
+};
+
+MODULE_AUTHOR("Brian Pugh <bpugh@cs.pdx.edu>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780");
+MODULE_VERSION("0.3alpha");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(usb, mcs_table);
+
+static int qos_mtt_bits = 0x07 /* > 1ms */ ;
+module_param(qos_mtt_bits, int, 0);
+MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
+
+static int receive_mode = 0x1;
+module_param(receive_mode, int, 0);
+MODULE_PARM_DESC(receive_mode,
+                "Receive mode of the device (1:fast, 0:slow, default:1)");
+
+static int sir_tweak = 1;
+module_param(sir_tweak, int, 0444);
+MODULE_PARM_DESC(sir_tweak,
+                "Default pulse width (1:1.6us, 0:3/16 bit, default:1).");
+
+static int transceiver_type = MCS_TSC_VISHAY;
+module_param(transceiver_type, int, 0444);
+MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h.");
+
+static struct usb_driver mcs_driver = {
+       .name = "mcs7780",
+       .probe = mcs_probe,
+       .disconnect = mcs_disconnect,
+       .id_table = mcs_table,
+};
+
+/* speed flag selection by direct addressing.
+addr = (speed >> 8) & 0x0f
+
+0x1   57600     0x2  115200     0x4 1152000     0x5    9600
+0x6   38400     0x9    2400     0xa  576000     0xb   19200
+
+4Mbps (or 2400) must be checked separately. Since it also has
+to be programmed in a different manner that is not a big problem.
+*/
+static __u16 mcs_speed_set[16] = { 0,
+       MCS_SPEED_57600,
+       MCS_SPEED_115200,
+       0,
+       MCS_SPEED_1152000,
+       MCS_SPEED_9600,
+       MCS_SPEED_38400,
+       0, 0,
+       MCS_SPEED_2400,
+       MCS_SPEED_576000,
+       MCS_SPEED_19200,
+       0, 0, 0,
+};
+
+/* Set given 16 bit register with a 16 bit value. Send control message
+ * to set dongle register. */
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val)
+{
+       struct usb_device *dev = mcs->usbdev;
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+                              MCS_WR_RTYPE, val, reg, NULL, 0,
+                              msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+}
+
+/* Get 16 bit register value. Send contol message to read dongle register. */
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val)
+{
+       struct usb_device *dev = mcs->usbdev;
+       int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+                                 MCS_RD_RTYPE, 0, reg, val, 2,
+                                 msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+
+       return ret;
+}
+
+/* Setup a communication between mcs7780 and TFDU chips.  It is described
+ * in more detail in the data sheet.  The setup sequence puts the the
+ * vishay tranceiver into high speed mode.  It will also receive SIR speed
+ * packets but at reduced sensitivity.
+ */
+
+/* 0: OK 1:ERROR */
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs)
+{
+       int ret = 0;
+       __u16 rval;
+
+       /* mcs_get_reg should read exactly two bytes from the dongle */
+       ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+       if (unlikely(ret != 2)) {
+               ret = -EIO;
+               goto error;
+       }
+
+       /* The MCS_XCVR_CONF bit puts the transceiver into configuration
+        * mode.  The MCS_MODE0 bit must start out high (1) and then
+        * transition to low and the MCS_STFIR and MCS_MODE1 bits must
+        * be low.
+        */
+       rval |= (MCS_MODE0 | MCS_XCVR_CONF);
+       rval &= ~MCS_STFIR;
+       rval &= ~MCS_MODE1;
+       ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       rval &= ~MCS_MODE0;
+       ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       rval &= ~MCS_XCVR_CONF;
+       ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       ret = 0;
+       error:
+               return ret;
+}
+
+/* Setup a communication between mcs7780 and agilent chip. */
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs)
+{
+       IRDA_WARNING("This transceiver type is not supported yet.");
+       return 1;
+}
+
+/* Setup a communication between mcs7780 and sharp chip. */
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs)
+{
+       IRDA_WARNING("This transceiver type is not supported yet.");
+       return 1;
+}
+
+/* Common setup for all transceivers */
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs)
+{
+       int ret = 0;
+       __u16 rval;
+       char *msg;
+
+       msg = "Basic transceiver setup error.";
+
+       /* read value of MODE Register, set the DRIVER and RESET bits
+       * and write value back out to MODE Register
+       */
+       ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       if(unlikely(ret != 2))
+               goto error;
+       rval |= MCS_DRIVER;     /* put the mcs7780 into configuration mode. */
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if(unlikely(ret))
+               goto error;
+
+       rval = 0;               /* set min pulse width to 0 initially. */
+       ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval);
+       if(unlikely(ret))
+               goto error;
+
+       ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       if(unlikely(ret != 2))
+               goto error;
+
+       rval &= ~MCS_FIR;       /* turn off fir mode. */
+       if(mcs->sir_tweak)
+               rval |= MCS_SIR16US;    /* 1.6us pulse width */
+       else
+               rval &= ~MCS_SIR16US;   /* 3/16 bit time pulse width */
+
+       /* make sure ask mode and back to back packets are off. */
+       rval &= ~(MCS_BBTG | MCS_ASK);
+
+       rval &= ~MCS_SPEED_MASK;
+       rval |= MCS_SPEED_9600;         /* make sure initial speed is 9600. */
+       mcs->speed = 9600;
+       mcs->new_speed = 0;             /* new_speed is set to 0 */
+       rval &= ~MCS_PLLPWDN;           /* disable power down. */
+
+       /* make sure device determines direction and that the auto send sip
+        * pulse are on.
+        */
+       rval |= MCS_DTD | MCS_SIPEN;
+
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if(unlikely(ret))
+               goto error;
+
+       msg = "transceiver model specific setup error.";
+       switch (mcs->transceiver_type) {
+       case MCS_TSC_VISHAY:
+               ret = mcs_setup_transceiver_vishay(mcs);
+               break;
+
+       case MCS_TSC_SHARP:
+               ret = mcs_setup_transceiver_sharp(mcs);
+               break;
+
+       case MCS_TSC_AGILENT:
+               ret = mcs_setup_transceiver_agilent(mcs);
+               break;
+
+       default:
+               IRDA_WARNING("Unknown transceiver type: %d",
+                            mcs->transceiver_type);
+               ret = 1;
+       }
+       if (unlikely(ret))
+               goto error;
+
+       /* If transceiver is not SHARP, then if receive mode set
+       * on the RXFAST bit in the XCVR Register otherwise unset it
+       */
+       if (mcs->transceiver_type != MCS_TSC_SHARP) {
+
+               ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+               if (unlikely(ret != 2))
+                       goto error;
+               if (mcs->receive_mode)
+                       rval |= MCS_RXFAST;
+               else
+                       rval &= ~MCS_RXFAST;
+               ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+               if (unlikely(ret))
+                       goto error;
+       }
+
+       msg = "transceiver reset.";
+
+       ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       if (unlikely(ret != 2))
+               goto error;
+
+       /* reset the mcs7780 so all changes take effect. */
+       rval &= ~MCS_RESET;
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if (unlikely(ret))
+               goto error;
+       else
+               return ret;
+
+error:
+       IRDA_ERROR("%s", msg);
+       return ret;
+}
+
+/* Wraps the data in format for SIR */
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf)
+{
+       int wraplen;
+
+       /* 2: full frame length, including "the length" */
+       wraplen = async_wrap_skb(skb, buf + 2, 4094);
+
+       wraplen += 2;
+       buf[0] = wraplen & 0xff;
+       buf[1] = (wraplen >> 8) & 0xff;
+
+       return wraplen;
+}
+
+/* Wraps the data in format for FIR */
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+       unsigned int len = 0;
+       __u32 fcs = ~(crc32_le(~0, skb->data, skb->len));
+
+       /* add 2 bytes for length value and 4 bytes for fcs. */
+       len = skb->len + 6;
+
+       /* The mcs7780 requires that the first two bytes are the packet
+        * length in little endian order.  Note: the length value includes
+        * the two bytes for the length value itself.
+        */
+       buf[0] = len & 0xff;
+       buf[1] = (len >> 8) & 0xff;
+       /* copy the data into the tx buffer. */
+       memcpy(buf+2, skb->data, skb->len);
+       /* put the fcs in the last four bytes in little endian order. */
+       buf[len - 4] = fcs & 0xff;
+       buf[len - 3] = (fcs >> 8) & 0xff;
+       buf[len - 2] = (fcs >> 16) & 0xff;
+       buf[len - 1] = (fcs >> 24) & 0xff;
+
+       return len;
+}
+
+/* Wraps the data in format for MIR */
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+       __u16 fcs = 0;
+       int len = skb->len + 4;
+
+       fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len));
+       /* put the total packet length in first.  Note: packet length
+        * value includes the two bytes that hold the packet length
+        * itself.
+        */
+       buf[0] = len & 0xff;
+       buf[1] = (len >> 8) & 0xff;
+       /* copy the data */
+       memcpy(buf+2, skb->data, skb->len);
+       /* put the fcs in last two bytes in little endian order. */
+       buf[len - 2] = fcs & 0xff;
+       buf[len - 1] = (fcs >> 8) & 0xff;
+
+       return len;
+}
+
+/* Unwrap received packets at MIR speed.  A 16 bit crc_ccitt checksum is
+ * used for the fcs.  When performed over the entire packet the result
+ * should be GOOD_FCS = 0xf0b8.  Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+       __u16 fcs;
+       int new_len;
+       struct sk_buff *skb;
+
+       /* Assume that the frames are going to fill a single packet
+        * rather than span multiple packets.
+        */
+
+       new_len = len - 2;
+       if(unlikely(new_len <= 0)) {
+               IRDA_ERROR("%s short frame length %d\n",
+                            mcs->netdev->name, new_len);
+               ++mcs->stats.rx_errors;
+               ++mcs->stats.rx_length_errors;
+               return;
+       }
+       fcs = 0;
+       fcs = irda_calc_crc16(~fcs, buf, len);
+
+       if(fcs != GOOD_FCS) {
+               IRDA_ERROR("crc error calc 0x%x len %d\n",
+                          fcs, new_len);
+               mcs->stats.rx_errors++;
+               mcs->stats.rx_crc_errors++;
+               return;
+       }
+
+       skb = dev_alloc_skb(new_len + 1);
+       if(unlikely(!skb)) {
+               ++mcs->stats.rx_dropped;
+               return;
+       }
+
+       skb_reserve(skb, 1);
+       memcpy(skb->data, buf, new_len);
+       skb_put(skb, new_len);
+       skb->mac.raw = skb->data;
+       skb->protocol = htons(ETH_P_IRDA);
+       skb->dev = mcs->netdev;
+
+       netif_rx(skb);
+
+       mcs->stats.rx_packets++;
+       mcs->stats.rx_bytes += new_len;
+
+       return;
+}
+
+/* Unwrap received packets at FIR speed.  A 32 bit crc_ccitt checksum is
+ * used for the fcs.  Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+       __u32 fcs;
+       int new_len;
+       struct sk_buff *skb;
+
+       /* Assume that the frames are going to fill a single packet
+        * rather than span multiple packets.  This is most likely a false
+        * assumption.
+        */
+
+       new_len = len - 4;
+       if(unlikely(new_len <= 0)) {
+               IRDA_ERROR("%s short frame length %d\n",
+                          mcs->netdev->name, new_len);
+               ++mcs->stats.rx_errors;
+               ++mcs->stats.rx_length_errors;
+               return;
+       }
+
+       fcs = ~(crc32_le(~0, buf, new_len));
+       if(fcs != le32_to_cpu(get_unaligned((u32 *)(buf+new_len)))) {
+               IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
+               mcs->stats.rx_errors++;
+               mcs->stats.rx_crc_errors++;
+               return;
+       }
+
+       skb = dev_alloc_skb(new_len + 1);
+       if(unlikely(!skb)) {
+               ++mcs->stats.rx_dropped;
+               return;
+       }
+
+       skb_reserve(skb, 1);
+       memcpy(skb->data, buf, new_len);
+       skb_put(skb, new_len);
+       skb->mac.raw = skb->data;
+       skb->protocol = htons(ETH_P_IRDA);
+       skb->dev = mcs->netdev;
+
+       netif_rx(skb);
+
+       mcs->stats.rx_packets++;
+       mcs->stats.rx_bytes += new_len;
+
+       return;
+}
+
+
+/* Allocates urbs for both receive and transmit.
+ * If alloc fails return error code 0 (fail) otherwise
+ * return error code 1 (success).
+ */
+static inline int mcs_setup_urbs(struct mcs_cb *mcs)
+{
+       mcs->rx_urb = NULL;
+
+       mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mcs->tx_urb)
+               return 0;
+
+       mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mcs->rx_urb)
+               return 0;
+
+       return 1;
+}
+
+/* Sets up state to be initially outside frame, gets receive urb,
+ * sets status to successful and then submits the urb to start
+ * receiving the data.
+ */
+static inline int mcs_receive_start(struct mcs_cb *mcs)
+{
+       mcs->rx_buff.in_frame = FALSE;
+       mcs->rx_buff.state = OUTSIDE_FRAME;
+
+       usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev,
+                         usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in),
+                         mcs->in_buf, 4096, mcs_receive_irq, mcs);
+
+       mcs->rx_urb->status = 0;
+       return usb_submit_urb(mcs->rx_urb, GFP_KERNEL);
+}
+
+/* Finds the in and out endpoints for the mcs control block */
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+                                    struct usb_host_endpoint *ep, int epnum)
+{
+       int i;
+       int ret = 0;
+
+       /* If no place to store the endpoints just return */
+       if (!ep)
+               return ret;
+
+       /* cycle through all endpoints, find the first two that are DIR_IN */
+       for (i = 0; i < epnum; i++) {
+               if (ep[i].desc.bEndpointAddress & USB_DIR_IN)
+                       mcs->ep_in = ep[i].desc.bEndpointAddress;
+               else
+                       mcs->ep_out = ep[i].desc.bEndpointAddress;
+
+               /* MosChip says that the chip has only two bulk
+                * endpoints. Find one for each direction and move on.
+                */
+               if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) {
+                       ret = 1;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static void mcs_speed_work(void *arg)
+{
+       struct mcs_cb *mcs = arg;
+       struct net_device *netdev = mcs->netdev;
+
+       mcs_speed_change(mcs);
+       netif_wake_queue(netdev);
+}
+
+/* Function to change the speed of the mcs7780.  Fully supports SIR,
+ * MIR, and FIR speeds.
+ */
+static int mcs_speed_change(struct mcs_cb *mcs)
+{
+       int ret = 0;
+       int rst = 0;
+       int cnt = 0;
+       __u16 nspeed;
+       __u16 rval;
+
+       nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f];
+
+       do {
+               mcs_get_reg(mcs, MCS_RESV_REG, &rval);
+       } while(cnt++ < 100 && (rval & MCS_IRINTX));
+
+       if(cnt >= 100) {
+               IRDA_ERROR("unable to change speed");
+               ret = -EIO;
+               goto error;
+       }
+
+       mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+
+       /* MINRXPW values recomended by MosChip */
+       if (mcs->new_speed <= 115200) {
+               rval &= ~MCS_FIR;
+
+               if ((rst = (mcs->speed > 115200)))
+                       mcs_set_reg(mcs, MCS_MINRXPW_REG, 0);
+
+       } else if (mcs->new_speed <= 1152000) {
+               rval &= ~MCS_FIR;
+
+               if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000)))
+                       mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+       } else {
+               rval |= MCS_FIR;
+
+               if ((rst = (mcs->speed != 4000000)))
+                       mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+       }
+
+       rval &= ~MCS_SPEED_MASK;
+       rval |= nspeed;
+
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       if (rst)
+               switch (mcs->transceiver_type) {
+               case MCS_TSC_VISHAY:
+                       ret = mcs_setup_transceiver_vishay(mcs);
+                       break;
+
+               case MCS_TSC_SHARP:
+                       ret = mcs_setup_transceiver_sharp(mcs);
+                       break;
+
+               case MCS_TSC_AGILENT:
+                       ret = mcs_setup_transceiver_agilent(mcs);
+                       break;
+
+               default:
+                       ret = 1;
+                       IRDA_WARNING("Unknown transceiver type: %d",
+                                    mcs->transceiver_type);
+               }
+       if (unlikely(ret))
+               goto error;
+
+       mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       rval &= ~MCS_RESET;
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+
+       mcs->speed = mcs->new_speed;
+       error:
+               mcs->new_speed = 0;
+               return ret;
+}
+
+/* Ioctl calls not supported at this time.  Can be an area of future work. */
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+       /* struct if_irda_req *irq = (struct if_irda_req *)rq; */
+       /* struct mcs_cb *mcs = netdev_priv(netdev); */
+       int ret = 0;
+
+       switch (cmd) {
+       default:
+               ret = -EOPNOTSUPP;
+       }
+
+       return ret;
+}
+
+/* Network device is taken down, done by "ifconfig irda0 down" */
+static int mcs_net_close(struct net_device *netdev)
+{
+       int ret = 0;
+       struct mcs_cb *mcs = netdev_priv(netdev);
+
+       /* Stop transmit processing */
+       netif_stop_queue(netdev);
+
+       /* kill and free the receive and transmit URBs */
+       usb_kill_urb(mcs->rx_urb);
+       usb_free_urb(mcs->rx_urb);
+       usb_kill_urb(mcs->tx_urb);
+       usb_free_urb(mcs->tx_urb);
+
+       /* Stop and remove instance of IrLAP */
+       if (mcs->irlap)
+               irlap_close(mcs->irlap);
+
+       mcs->irlap = NULL;
+       return ret;
+}
+
+/* Network device is taken up, done by "ifconfig irda0 up" */
+static int mcs_net_open(struct net_device *netdev)
+{
+       struct mcs_cb *mcs = netdev_priv(netdev);
+       char hwname[16];
+       int ret = 0;
+
+       ret = usb_clear_halt(mcs->usbdev,
+                            usb_sndbulkpipe(mcs->usbdev, mcs->ep_in));
+       if (ret)
+               goto error1;
+       ret = usb_clear_halt(mcs->usbdev,
+                            usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out));
+       if (ret)
+               goto error1;
+
+       ret = mcs_setup_transceiver(mcs);
+       if (ret)
+               goto error1;
+
+       ret = -ENOMEM;
+
+       /* Initialize for SIR/FIR to copy data directly into skb.  */
+       mcs->receiving = 0;
+       mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+       mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+       if (!mcs->rx_buff.skb)
+               goto error1;
+
+       skb_reserve(mcs->rx_buff.skb, 1);
+       mcs->rx_buff.head = mcs->rx_buff.skb->data;
+       do_gettimeofday(&mcs->rx_time);
+
+       /*
+        * Now that everything should be initialized properly,
+        * Open new IrLAP layer instance to take care of us...
+        * Note : will send immediately a speed change...
+        */
+       sprintf(hwname, "usb#%d", mcs->usbdev->devnum);
+       mcs->irlap = irlap_open(netdev, &mcs->qos, hwname);
+       if (!mcs->irlap) {
+               IRDA_ERROR("mcs7780: irlap_open failed");
+               goto error2;
+       }
+
+       if (!mcs_setup_urbs(mcs))
+       goto error3;
+
+       ret = mcs_receive_start(mcs);
+       if (ret)
+               goto error3;
+
+       netif_start_queue(netdev);
+       return 0;
+
+       error3:
+               irlap_close(mcs->irlap);
+       error2:
+               kfree_skb(mcs->rx_buff.skb);
+       error1:
+               return ret;
+}
+
+
+/* Get device stats for /proc/net/dev and ifconfig */
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev)
+{
+       struct mcs_cb *mcs = netdev_priv(netdev);
+       return &mcs->stats;
+}
+
+/* Receive callback function.  */
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs)
+{
+       __u8 *bytes;
+       struct mcs_cb *mcs = urb->context;
+       int i;
+       int ret;
+
+       if (!netif_running(mcs->netdev))
+               return;
+
+       if (urb->status)
+               return;
+
+       if (urb->actual_length > 0) {
+               bytes = urb->transfer_buffer;
+
+               /* MCS returns frames without BOF and EOF
+                * I assume it returns whole frames.
+                */
+               /* SIR speed */
+               if(mcs->speed < 576000) {
+                       async_unwrap_char(mcs->netdev, &mcs->stats,
+                                 &mcs->rx_buff, 0xc0);
+
+                       for (i = 0; i < urb->actual_length; i++)
+                               async_unwrap_char(mcs->netdev, &mcs->stats,
+                                         &mcs->rx_buff, bytes[i]);
+
+                       async_unwrap_char(mcs->netdev, &mcs->stats,
+                                 &mcs->rx_buff, 0xc1);
+               }
+               /* MIR speed */
+               else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+                       mcs_unwrap_mir(mcs, urb->transfer_buffer,
+                               urb->actual_length);
+               }
+               /* FIR speed */
+               else {
+                       mcs_unwrap_fir(mcs, urb->transfer_buffer,
+                               urb->actual_length);
+               }
+               mcs->netdev->last_rx = jiffies;
+               do_gettimeofday(&mcs->rx_time);
+       }
+
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/* Transmit callback funtion.  */
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs)
+{
+       struct mcs_cb *mcs = urb->context;
+       struct net_device *ndev = mcs->netdev;
+
+       if (unlikely(mcs->new_speed))
+               schedule_work(&mcs->work);
+       else
+               netif_wake_queue(ndev);
+}
+
+/* Transmit callback funtion.  */
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+       unsigned long flags;
+       struct mcs_cb *mcs;
+       int wraplen;
+       int ret = 0;
+
+
+       if (skb == NULL || ndev == NULL)
+               return -EINVAL;
+
+       netif_stop_queue(ndev);
+       mcs = netdev_priv(ndev);
+
+       spin_lock_irqsave(&mcs->lock, flags);
+
+       mcs->new_speed = irda_get_next_speed(skb);
+       if (likely(mcs->new_speed == mcs->speed))
+               mcs->new_speed = 0;
+
+       /* SIR speed */
+       if(mcs->speed < 576000) {
+               wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf);
+       }
+       /* MIR speed */
+       else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+               wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf);
+       }
+       /* FIR speed */
+       else {
+               wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf);
+       }
+       usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev,
+                         usb_sndbulkpipe(mcs->usbdev, mcs->ep_out),
+                         mcs->out_buf, wraplen, mcs_send_irq, mcs);
+
+       if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) {
+               IRDA_ERROR("failed tx_urb: %d", ret);
+               switch (ret) {
+               case -ENODEV:
+               case -EPIPE:
+                       break;
+               default:
+                       mcs->stats.tx_errors++;
+                       netif_start_queue(ndev);
+               }
+       } else {
+               mcs->stats.tx_packets++;
+               mcs->stats.tx_bytes += skb->len;
+       }
+
+       dev_kfree_skb(skb);
+       spin_unlock_irqrestore(&mcs->lock, flags);
+       return ret;
+}
+
+/*
+ * This function is called by the USB subsystem for each new device in the
+ * system.  Need to verify the device and if it is, then start handling it.
+ */
+static int mcs_probe(struct usb_interface *intf,
+                    const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct net_device *ndev = NULL;
+       struct mcs_cb *mcs;
+       int ret = -ENOMEM;
+
+       ndev = alloc_irdadev(sizeof(*mcs));
+       if (!ndev)
+               goto error1;
+
+       IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.", udev->devnum);
+
+       /* what is it realy for? */
+       SET_MODULE_OWNER(ndev);
+       SET_NETDEV_DEV(ndev, &intf->dev);
+
+       ret = usb_reset_configuration(udev);
+       if (ret != 0) {
+               IRDA_ERROR("mcs7780: usb reset configuration failed");
+               goto error2;
+       }
+
+       mcs = netdev_priv(ndev);
+       mcs->usbdev = udev;
+       mcs->netdev = ndev;
+       spin_lock_init(&mcs->lock);
+
+       /* Initialize QoS for this device */
+       irda_init_max_qos_capabilies(&mcs->qos);
+
+       /* That's the Rx capability. */
+       mcs->qos.baud_rate.bits &=
+           IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200
+               | IR_576000 | IR_1152000 | (IR_4000000 << 8);
+
+
+       mcs->qos.min_turn_time.bits &= qos_mtt_bits;
+       irda_qos_bits_to_value(&mcs->qos);
+
+       /* Speed change work initialisation*/
+       INIT_WORK(&mcs->work, mcs_speed_work, mcs);
+
+       /* Override the network functions we need to use */
+       ndev->hard_start_xmit = mcs_hard_xmit;
+       ndev->open = mcs_net_open;
+       ndev->stop = mcs_net_close;
+       ndev->get_stats = mcs_net_get_stats;
+       ndev->do_ioctl = mcs_net_ioctl;
+
+       if (!intf->cur_altsetting)
+               goto error2;
+
+       ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint,
+                                intf->cur_altsetting->desc.bNumEndpoints);
+       if (!ret) {
+               ret = -ENODEV;
+               goto error2;
+       }
+
+       ret = register_netdev(ndev);
+       if (ret != 0)
+               goto error2;
+
+       IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s",
+                  ndev->name);
+
+       mcs->transceiver_type = transceiver_type;
+       mcs->sir_tweak = sir_tweak;
+       mcs->receive_mode = receive_mode;
+
+       usb_set_intfdata(intf, mcs);
+       return 0;
+
+       error2:
+               free_netdev(ndev);
+
+       error1:
+               return ret;
+}
+
+/* The current device is removed, the USB layer tells us to shut down. */
+static void mcs_disconnect(struct usb_interface *intf)
+{
+       struct mcs_cb *mcs = usb_get_intfdata(intf);
+
+       if (!mcs)
+               return;
+
+       flush_scheduled_work();
+
+       unregister_netdev(mcs->netdev);
+       free_netdev(mcs->netdev);
+
+       usb_set_intfdata(intf, NULL);
+       IRDA_DEBUG(0, "MCS7780 now disconnected.");
+}
+
+/* Module insertion */
+static int __init mcs_init(void)
+{
+       int result;
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&mcs_driver);
+       if (result)
+               IRDA_ERROR("usb_register failed. Error number %d", result);
+
+       return result;
+}
+module_init(mcs_init);
+
+/* Module removal */
+static void __exit mcs_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&mcs_driver);
+}
+module_exit(mcs_exit);
+
diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h
new file mode 100644 (file)
index 0000000..1a723d7
--- /dev/null
@@ -0,0 +1,167 @@
+/*****************************************************************************
+*
+* Filename:      mcs7780.h
+* Version:       0.2-alpha
+* Description:   Irda MosChip USB Dongle
+* Status:        Experimental
+* Authors:       Lukasz Stelmach <stlman@poczta.fm>
+*               Brian Pugh <bpugh@cs.pdx.edu>
+*
+*       Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+*       Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*
+*       This program is free software; you can redistribute it and/or modify
+*       it under the terms of the GNU General Public License as published by
+*       the Free Software Foundation; either version 2 of the License, or
+*       (at your option) any later version.
+*
+*       This program is distributed in the hope that it will be useful,
+*       but WITHOUT ANY WARRANTY; without even the implied warranty of
+*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*       GNU 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 _MCS7780_H
+#define _MCS7780_H
+
+#define MCS_MODE_SIR           0
+#define MCS_MODE_MIR           1
+#define MCS_MODE_FIR           2
+
+#define MCS_CTRL_TIMEOUT       500
+#define MCS_XMIT_TIMEOUT       500
+/* Possible transceiver types */
+#define MCS_TSC_VISHAY         0       /* Vishay TFD, default choice */
+#define MCS_TSC_AGILENT                1       /* Agilent 3602/3600 */
+#define MCS_TSC_SHARP          2       /* Sharp GP2W1000YP */
+
+/* Requests */
+#define MCS_RD_RTYPE 0xC0
+#define MCS_WR_RTYPE 0x40
+#define MCS_RDREQ    0x0F
+#define MCS_WRREQ    0x0E
+
+/* Register 0x00 */
+#define MCS_MODE_REG   0
+#define MCS_FIR                ((__u16)0x0001)
+#define MCS_SIR16US    ((__u16)0x0002)
+#define MCS_BBTG       ((__u16)0x0004)
+#define MCS_ASK                ((__u16)0x0008)
+#define MCS_PARITY     ((__u16)0x0010)
+
+/* SIR/MIR speed constants */
+#define MCS_SPEED_SHIFT            5
+#define MCS_SPEED_MASK     ((__u16)0x00E0)
+#define MCS_SPEED(x)       ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT)
+#define MCS_SPEED_2400     ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_9600     ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_19200            ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_38400            ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_57600            ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_115200    ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_576000    ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_1152000   ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+
+#define MCS_PLLPWDN    ((__u16)0x0100)
+#define MCS_DRIVER     ((__u16)0x0200)
+#define MCS_DTD                ((__u16)0x0400)
+#define MCS_DIR                ((__u16)0x0800)
+#define MCS_SIPEN      ((__u16)0x1000)
+#define MCS_SENDSIP    ((__u16)0x2000)
+#define MCS_CHGDIR     ((__u16)0x4000)
+#define MCS_RESET      ((__u16)0x8000)
+
+/* Register 0x02 */
+#define MCS_XCVR_REG   2
+#define MCS_MODE0      ((__u16)0x0001)
+#define MCS_STFIR      ((__u16)0x0002)
+#define MCS_XCVR_CONF  ((__u16)0x0004)
+#define MCS_RXFAST     ((__u16)0x0008)
+/* TXCUR [6:4] */
+#define MCS_TXCUR_SHIFT        4
+#define MCS_TXCUR_MASK ((__u16)0x0070)
+#define MCS_TXCUR(x)   ((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT)
+#define MCS_SETTXCUR(x,y) \
+       ((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK)
+
+#define MCS_MODE1      ((__u16)0x0080)
+#define MCS_SMODE0     ((__u16)0x0100)
+#define MCS_SMODE1     ((__u16)0x0200)
+#define MCS_INVTX      ((__u16)0x0400)
+#define MCS_INVRX      ((__u16)0x0800)
+
+#define MCS_MINRXPW_REG        4
+
+#define MCS_RESV_REG 7
+#define MCS_IRINTX     ((__u16)0x0001)
+#define MCS_IRINRX     ((__u16)0x0002)
+
+struct mcs_cb {
+       struct usb_device *usbdev;      /* init: probe_irda */
+       struct net_device *netdev;      /* network layer */
+       struct irlap_cb *irlap; /* The link layer we are binded to */
+       struct net_device_stats stats;  /* network statistics */
+       struct qos_info qos;
+       unsigned int speed;     /* Current speed */
+       unsigned int new_speed; /* new speed */
+
+       struct work_struct work; /* Change speed work */
+
+       struct sk_buff *tx_pending;
+       char in_buf[4096];      /* transmit/receive buffer */
+       char out_buf[4096];     /* transmit/receive buffer */
+       __u8 *fifo_status;
+
+       iobuff_t rx_buff;       /* receive unwrap state machine */
+       struct timeval rx_time;
+       spinlock_t lock;
+       int receiving;
+
+       __u8 ep_in;
+       __u8 ep_out;
+
+       struct urb *rx_urb;
+       struct urb *tx_urb;
+
+       int transceiver_type;
+       int sir_tweak;
+       int receive_mode;
+};
+
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val);
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val);
+
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs);
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf);
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf);
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf);
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len);
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len);
+static inline int mcs_setup_urbs(struct mcs_cb *mcs);
+static inline int mcs_receive_start(struct mcs_cb *mcs);
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+                                    struct usb_host_endpoint *ep, int epnum);
+
+static int mcs_speed_change(struct mcs_cb *mcs);
+
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd);
+static int mcs_net_close(struct net_device *netdev);
+static int mcs_net_open(struct net_device *netdev);
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev);
+
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs);
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs);
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev);
+
+static int mcs_probe(struct usb_interface *intf,
+                    const struct usb_device_id *id);
+static void mcs_disconnect(struct usb_interface *intf);
+
+#endif                         /* _MCS7780_H */
diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile
new file mode 100644 (file)
index 0000000..5df8916
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Myricom Myri-10G ethernet driver
+#
+
+obj-$(CONFIG_MYRI10GE) += myri10ge.o
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
new file mode 100644 (file)
index 0000000..9bdd43a
--- /dev/null
@@ -0,0 +1,2866 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005, 2006 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#include <linux/moduleparam.h>
+#include <linux/io.h>
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "myri10ge_mcp.h"
+#include "myri10ge_mcp_gen_header.h"
+
+#define MYRI10GE_VERSION_STR "1.0.0"
+
+MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
+MODULE_AUTHOR("Maintainer: help@myri.com");
+MODULE_VERSION(MYRI10GE_VERSION_STR);
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
+
+#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff
+#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
+
+struct myri10ge_rx_buffer_state {
+       struct sk_buff *skb;
+        DECLARE_PCI_UNMAP_ADDR(bus)
+        DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_tx_buffer_state {
+       struct sk_buff *skb;
+       int last;
+        DECLARE_PCI_UNMAP_ADDR(bus)
+        DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_cmd {
+       u32 data0;
+       u32 data1;
+       u32 data2;
+};
+
+struct myri10ge_rx_buf {
+       struct mcp_kreq_ether_recv __iomem *lanai;      /* lanai ptr for recv ring */
+       u8 __iomem *wc_fifo;    /* w/c rx dma addr fifo address */
+       struct mcp_kreq_ether_recv *shadow;     /* host shadow of recv ring */
+       struct myri10ge_rx_buffer_state *info;
+       int cnt;
+       int alloc_fail;
+       int mask;               /* number of rx slots -1 */
+};
+
+struct myri10ge_tx_buf {
+       struct mcp_kreq_ether_send __iomem *lanai;      /* lanai ptr for sendq */
+       u8 __iomem *wc_fifo;    /* w/c send fifo address */
+       struct mcp_kreq_ether_send *req_list;   /* host shadow of sendq */
+       char *req_bytes;
+       struct myri10ge_tx_buffer_state *info;
+       int mask;               /* number of transmit slots -1  */
+       int boundary;           /* boundary transmits cannot cross */
+       int req ____cacheline_aligned;  /* transmit slots submitted     */
+       int pkt_start;          /* packets started */
+       int done ____cacheline_aligned; /* transmit slots completed     */
+       int pkt_done;           /* packets completed */
+};
+
+struct myri10ge_rx_done {
+       struct mcp_slot *entry;
+       dma_addr_t bus;
+       int cnt;
+       int idx;
+};
+
+struct myri10ge_priv {
+       int running;            /* running?             */
+       int csum_flag;          /* rx_csums?            */
+       struct myri10ge_tx_buf tx;      /* transmit ring        */
+       struct myri10ge_rx_buf rx_small;
+       struct myri10ge_rx_buf rx_big;
+       struct myri10ge_rx_done rx_done;
+       int small_bytes;
+       struct net_device *dev;
+       struct net_device_stats stats;
+       u8 __iomem *sram;
+       int sram_size;
+       unsigned long board_span;
+       unsigned long iomem_base;
+       u32 __iomem *irq_claim;
+       u32 __iomem *irq_deassert;
+       char *mac_addr_string;
+       struct mcp_cmd_response *cmd;
+       dma_addr_t cmd_bus;
+       struct mcp_irq_data *fw_stats;
+       dma_addr_t fw_stats_bus;
+       struct pci_dev *pdev;
+       int msi_enabled;
+       unsigned int link_state;
+       unsigned int rdma_tags_available;
+       int intr_coal_delay;
+       u32 __iomem *intr_coal_delay_ptr;
+       int mtrr;
+       int wake_queue;
+       int stop_queue;
+       int down_cnt;
+       wait_queue_head_t down_wq;
+       struct work_struct watchdog_work;
+       struct timer_list watchdog_timer;
+       int watchdog_tx_done;
+       int watchdog_tx_req;
+       int watchdog_resets;
+       int tx_linearized;
+       int pause;
+       char *fw_name;
+       char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
+       char fw_version[128];
+       u8 mac_addr[6];         /* eeprom mac address */
+       unsigned long serial_number;
+       int vendor_specific_offset;
+       u32 devctl;
+       u16 msi_flags;
+       u32 read_dma;
+       u32 write_dma;
+       u32 read_write_dma;
+};
+
+static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
+static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
+
+static char *myri10ge_fw_name = NULL;
+module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n");
+
+static int myri10ge_ecrc_enable = 1;
+module_param(myri10ge_ecrc_enable, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n");
+
+static int myri10ge_max_intr_slots = 1024;
+module_param(myri10ge_max_intr_slots, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n");
+
+static int myri10ge_small_bytes = -1;  /* -1 == auto */
+module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n");
+
+static int myri10ge_msi = 1;   /* enable msi by default */
+module_param(myri10ge_msi, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");
+
+static int myri10ge_intr_coal_delay = 25;
+module_param(myri10ge_intr_coal_delay, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n");
+
+static int myri10ge_flow_control = 1;
+module_param(myri10ge_flow_control, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n");
+
+static int myri10ge_deassert_wait = 1;
+module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_deassert_wait,
+                "Wait when deasserting legacy interrupts\n");
+
+static int myri10ge_force_firmware = 0;
+module_param(myri10ge_force_firmware, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_force_firmware,
+                "Force firmware to assume aligned completions\n");
+
+static int myri10ge_skb_cross_4k = 0;
+module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_skb_cross_4k,
+                "Can a small skb cross a 4KB boundary?\n");
+
+static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+module_param(myri10ge_initial_mtu, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");
+
+static int myri10ge_napi_weight = 64;
+module_param(myri10ge_napi_weight, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n");
+
+static int myri10ge_watchdog_timeout = 1;
+module_param(myri10ge_watchdog_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n");
+
+static int myri10ge_max_irq_loops = 1048576;
+module_param(myri10ge_max_irq_loops, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_irq_loops,
+                "Set stuck legacy IRQ detection threshold\n");
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))
+
+#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
+
+static int
+myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
+                 struct myri10ge_cmd *data, int atomic)
+{
+       struct mcp_cmd *buf;
+       char buf_bytes[sizeof(*buf) + 8];
+       struct mcp_cmd_response *response = mgp->cmd;
+       char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET;
+       u32 dma_low, dma_high, result, value;
+       int sleep_total = 0;
+
+       /* ensure buf is aligned to 8 bytes */
+       buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8);
+
+       buf->data0 = htonl(data->data0);
+       buf->data1 = htonl(data->data1);
+       buf->data2 = htonl(data->data2);
+       buf->cmd = htonl(cmd);
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf->response_addr.low = htonl(dma_low);
+       buf->response_addr.high = htonl(dma_high);
+       response->result = MYRI10GE_NO_RESPONSE_RESULT;
+       mb();
+       myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));
+
+       /* wait up to 15ms. Longest command is the DMA benchmark,
+        * which is capped at 5ms, but runs from a timeout handler
+        * that runs every 7.8ms. So a 15ms timeout leaves us with
+        * a 2.2ms margin
+        */
+       if (atomic) {
+               /* if atomic is set, do not sleep,
+                * and try to get the completion quickly
+                * (1ms will be enough for those commands) */
+               for (sleep_total = 0;
+                    sleep_total < 1000
+                    && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+                    sleep_total += 10)
+                       udelay(10);
+       } else {
+               /* use msleep for most command */
+               for (sleep_total = 0;
+                    sleep_total < 15
+                    && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+                    sleep_total++)
+                       msleep(1);
+       }
+
+       result = ntohl(response->result);
+       value = ntohl(response->data);
+       if (result != MYRI10GE_NO_RESPONSE_RESULT) {
+               if (result == 0) {
+                       data->data0 = value;
+                       return 0;
+               } else {
+                       dev_err(&mgp->pdev->dev,
+                               "command %d failed, result = %d\n",
+                               cmd, result);
+                       return -ENXIO;
+               }
+       }
+
+       dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n",
+               cmd, result);
+       return -EAGAIN;
+}
+
+/*
+ * The eeprom strings on the lanaiX have the format
+ * SN=x\0
+ * MAC=x:x:x:x:x:x\0
+ * PT:ddd mmm xx xx:xx:xx xx\0
+ * PV:ddd mmm xx xx:xx:xx xx\0
+ */
+static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp)
+{
+       char *ptr, *limit;
+       int i;
+
+       ptr = mgp->eeprom_strings;
+       limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
+
+       while (*ptr != '\0' && ptr < limit) {
+               if (memcmp(ptr, "MAC=", 4) == 0) {
+                       ptr += 4;
+                       mgp->mac_addr_string = ptr;
+                       for (i = 0; i < 6; i++) {
+                               if ((ptr + 2) > limit)
+                                       goto abort;
+                               mgp->mac_addr[i] =
+                                   simple_strtoul(ptr, &ptr, 16);
+                               ptr += 1;
+                       }
+               }
+               if (memcmp((const void *)ptr, "SN=", 3) == 0) {
+                       ptr += 3;
+                       mgp->serial_number = simple_strtoul(ptr, &ptr, 10);
+               }
+               while (ptr < limit && *ptr++) ;
+       }
+
+       return 0;
+
+abort:
+       dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n");
+       return -ENXIO;
+}
+
+/*
+ * Enable or disable periodic RDMAs from the host to make certain
+ * chipsets resend dropped PCIe messages
+ */
+
+static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
+{
+       char __iomem *submit;
+       u32 buf[16];
+       u32 dma_low, dma_high;
+       int i;
+
+       /* clear confirmation addr */
+       mgp->cmd->data = 0;
+       mb();
+
+       /* send a rdma command to the PCIe engine, and wait for the
+        * response in the confirmation address.  The firmware should
+        * write a -1 there to indicate it is alive and well
+        */
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf[0] = htonl(dma_high);       /* confirm addr MSW */
+       buf[1] = htonl(dma_low);        /* confirm addr LSW */
+       buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
+       buf[3] = htonl(dma_high);       /* dummy addr MSW */
+       buf[4] = htonl(dma_low);        /* dummy addr LSW */
+       buf[5] = htonl(enable); /* enable? */
+
+       submit = mgp->sram + 0xfc01c0;
+
+       myri10ge_pio_copy(submit, &buf, sizeof(buf));
+       for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++)
+               msleep(1);
+       if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA)
+               dev_err(&mgp->pdev->dev, "dummy rdma %s failed\n",
+                       (enable ? "enable" : "disable"));
+}
+
+static int
+myri10ge_validate_firmware(struct myri10ge_priv *mgp,
+                          struct mcp_gen_header *hdr)
+{
+       struct device *dev = &mgp->pdev->dev;
+       int major, minor;
+
+       /* check firmware type */
+       if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
+               dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type));
+               return -EINVAL;
+       }
+
+       /* save firmware version for ethtool */
+       strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+
+       sscanf(mgp->fw_version, "%d.%d", &major, &minor);
+
+       if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) {
+               dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
+               dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
+                       MXGEFW_VERSION_MINOR);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
+{
+       unsigned crc, reread_crc;
+       const struct firmware *fw;
+       struct device *dev = &mgp->pdev->dev;
+       struct mcp_gen_header *hdr;
+       size_t hdr_offset;
+       int status;
+       unsigned i;
+
+       if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
+               dev_err(dev, "Unable to load %s firmware image via hotplug\n",
+                       mgp->fw_name);
+               status = -EINVAL;
+               goto abort_with_nothing;
+       }
+
+       /* check size */
+
+       if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET ||
+           fw->size < MCP_HEADER_PTR_OFFSET + 4) {
+               dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size);
+               status = -EINVAL;
+               goto abort_with_fw;
+       }
+
+       /* check id */
+       hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
+       if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
+               dev_err(dev, "Bad firmware file\n");
+               status = -EINVAL;
+               goto abort_with_fw;
+       }
+       hdr = (void *)(fw->data + hdr_offset);
+
+       status = myri10ge_validate_firmware(mgp, hdr);
+       if (status != 0)
+               goto abort_with_fw;
+
+       crc = crc32(~0, fw->data, fw->size);
+       for (i = 0; i < fw->size; i += 256) {
+               myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i,
+                                 fw->data + i,
+                                 min(256U, (unsigned)(fw->size - i)));
+               mb();
+               readb(mgp->sram);
+       }
+       /* corruption checking is good for parity recovery and buggy chipset */
+       memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
+       reread_crc = crc32(~0, fw->data, fw->size);
+       if (crc != reread_crc) {
+               dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
+                       (unsigned)fw->size, reread_crc, crc);
+               status = -EIO;
+               goto abort_with_fw;
+       }
+       *size = (u32) fw->size;
+
+abort_with_fw:
+       release_firmware(fw);
+
+abort_with_nothing:
+       return status;
+}
+
+static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
+{
+       struct mcp_gen_header *hdr;
+       struct device *dev = &mgp->pdev->dev;
+       const size_t bytes = sizeof(struct mcp_gen_header);
+       size_t hdr_offset;
+       int status;
+
+       /* find running firmware header */
+       hdr_offset = ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+
+       if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) {
+               dev_err(dev, "Running firmware has bad header offset (%d)\n",
+                       (int)hdr_offset);
+               return -EIO;
+       }
+
+       /* copy header of running firmware from SRAM to host memory to
+        * validate firmware */
+       hdr = kmalloc(bytes, GFP_KERNEL);
+       if (hdr == NULL) {
+               dev_err(dev, "could not malloc firmware hdr\n");
+               return -ENOMEM;
+       }
+       memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
+       status = myri10ge_validate_firmware(mgp, hdr);
+       kfree(hdr);
+       return status;
+}
+
+static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
+{
+       char __iomem *submit;
+       u32 buf[16];
+       u32 dma_low, dma_high, size;
+       int status, i;
+
+       size = 0;
+       status = myri10ge_load_hotplug_firmware(mgp, &size);
+       if (status) {
+               dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n");
+
+               /* Do not attempt to adopt firmware if there
+                * was a bad crc */
+               if (status == -EIO)
+                       return status;
+
+               status = myri10ge_adopt_running_firmware(mgp);
+               if (status != 0) {
+                       dev_err(&mgp->pdev->dev,
+                               "failed to adopt running firmware\n");
+                       return status;
+               }
+               dev_info(&mgp->pdev->dev,
+                        "Successfully adopted running firmware\n");
+               if (mgp->tx.boundary == 4096) {
+                       dev_warn(&mgp->pdev->dev,
+                                "Using firmware currently running on NIC"
+                                ".  For optimal\n");
+                       dev_warn(&mgp->pdev->dev,
+                                "performance consider loading optimized "
+                                "firmware\n");
+                       dev_warn(&mgp->pdev->dev, "via hotplug\n");
+               }
+
+               mgp->fw_name = "adopted";
+               mgp->tx.boundary = 2048;
+               return status;
+       }
+
+       /* clear confirmation addr */
+       mgp->cmd->data = 0;
+       mb();
+
+       /* send a reload command to the bootstrap MCP, and wait for the
+        *  response in the confirmation address.  The firmware should
+        * write a -1 there to indicate it is alive and well
+        */
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf[0] = htonl(dma_high);       /* confirm addr MSW */
+       buf[1] = htonl(dma_low);        /* confirm addr LSW */
+       buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
+
+       /* FIX: All newest firmware should un-protect the bottom of
+        * the sram before handoff. However, the very first interfaces
+        * do not. Therefore the handoff copy must skip the first 8 bytes
+        */
+       buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */
+       buf[4] = htonl(size - 8);       /* length of code */
+       buf[5] = htonl(8);      /* where to copy to */
+       buf[6] = htonl(0);      /* where to jump to */
+
+       submit = mgp->sram + 0xfc0000;
+
+       myri10ge_pio_copy(submit, &buf, sizeof(buf));
+       mb();
+       msleep(1);
+       mb();
+       i = 0;
+       while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) {
+               msleep(1);
+               i++;
+       }
+       if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) {
+               dev_err(&mgp->pdev->dev, "handoff failed\n");
+               return -ENXIO;
+       }
+       dev_info(&mgp->pdev->dev, "handoff confirmed\n");
+       myri10ge_dummy_rdma(mgp, 1);
+
+       return 0;
+}
+
+static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+
+       cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+                    | (addr[2] << 8) | addr[3]);
+
+       cmd.data1 = ((addr[4] << 8) | (addr[5]));
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0);
+       return status;
+}
+
+static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
+{
+       struct myri10ge_cmd cmd;
+       int status, ctl;
+
+       ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL;
+       status = myri10ge_send_cmd(mgp, ctl, &cmd, 0);
+
+       if (status) {
+               printk(KERN_ERR
+                      "myri10ge: %s: Failed to set flow control mode\n",
+                      mgp->dev->name);
+               return status;
+       }
+       mgp->pause = pause;
+       return 0;
+}
+
+static void
+myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic)
+{
+       struct myri10ge_cmd cmd;
+       int status, ctl;
+
+       ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC;
+       status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic);
+       if (status)
+               printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n",
+                      mgp->dev->name);
+}
+
+static int myri10ge_reset(struct myri10ge_priv *mgp)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+       size_t bytes;
+       u32 len;
+
+       /* try to send a reset command to the card to see if it
+        * is alive */
+       memset(&cmd, 0, sizeof(cmd));
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0);
+       if (status != 0) {
+               dev_err(&mgp->pdev->dev, "failed reset\n");
+               return -ENXIO;
+       }
+
+       /* Now exchange information about interrupts  */
+
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       memset(mgp->rx_done.entry, 0, bytes);
+       cmd.data0 = (u32) bytes;
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0);
+
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
+       mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0);
+       if (!mgp->msi_enabled) {
+               status |= myri10ge_send_cmd
+                   (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0);
+               mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0);
+
+       }
+       status |= myri10ge_send_cmd
+           (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0);
+       mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0);
+       if (status != 0) {
+               dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n");
+               return status;
+       }
+       __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+
+       /* Run a small DMA test.
+        * The magic multipliers to the length tell the firmware
+        * to do DMA read, write, or read+write tests.  The
+        * results are returned in cmd.data0.  The upper 16
+        * bits or the return is the number of transfers completed.
+        * The lower 16 bits is the time in 0.5us ticks that the
+        * transfers took to complete.
+        */
+
+       len = mgp->tx.boundary;
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x10000;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->read_dma = ((cmd.data0 >> 16) * len * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
+                        status);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x1;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->write_dma = ((cmd.data0 >> 16) * len * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
+                        status);
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x10001;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev,
+                        "DMA read/write benchmark failed: %d\n", status);
+
+       memset(mgp->rx_done.entry, 0, bytes);
+
+       /* reset mcp/driver shared state back to 0 */
+       mgp->tx.req = 0;
+       mgp->tx.done = 0;
+       mgp->tx.pkt_start = 0;
+       mgp->tx.pkt_done = 0;
+       mgp->rx_big.cnt = 0;
+       mgp->rx_small.cnt = 0;
+       mgp->rx_done.idx = 0;
+       mgp->rx_done.cnt = 0;
+       status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
+       myri10ge_change_promisc(mgp, 0, 0);
+       myri10ge_change_pause(mgp, mgp->pause);
+       return status;
+}
+
+static inline void
+myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
+                   struct mcp_kreq_ether_recv *src)
+{
+       u32 low;
+
+       low = src->addr_low;
+       src->addr_low = DMA_32BIT_MASK;
+       myri10ge_pio_copy(dst, src, 8 * sizeof(*src));
+       mb();
+       src->addr_low = low;
+       __raw_writel(low, &dst->addr_low);
+       mb();
+}
+
+/*
+ * Set of routines to get a new receive buffer.  Any buffer which
+ * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
+ * wdma restrictions. We also try to align any smaller allocation to
+ * at least a 16 byte boundary for efficiency.  We assume the linux
+ * memory allocator works by powers of 2, and will not return memory
+ * smaller than 2KB which crosses a 4KB boundary.  If it does, we fall
+ * back to allocating 2x as much space as required.
+ *
+ * We intend to replace large (>4KB) skb allocations by using
+ * pages directly and building a fraglist in the near future.
+ */
+
+static inline struct sk_buff *myri10ge_alloc_big(int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long data, roundup;
+
+       skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD);
+       if (skb == NULL)
+               return NULL;
+
+       /* Correct skb->truesize so that socket buffer
+        * accounting is not confused the rounding we must
+        * do to satisfy alignment constraints.
+        */
+       skb->truesize -= 4096;
+
+       data = (unsigned long)(skb->data);
+       roundup = (-data) & (4095);
+       skb_reserve(skb, roundup);
+       return skb;
+}
+
+/* Allocate 2x as much space as required and use whichever portion
+ * does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long data, boundary;
+
+       skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1);
+       if (unlikely(skb == NULL))
+               return NULL;
+
+       /* Correct skb->truesize so that socket buffer
+        * accounting is not confused the rounding we must
+        * do to satisfy alignment constraints.
+        */
+       skb->truesize -= bytes + MXGEFW_PAD;
+
+       data = (unsigned long)(skb->data);
+       boundary = (data + 4095UL) & ~4095UL;
+       if ((boundary - data) >= (bytes + MXGEFW_PAD))
+               return skb;
+
+       skb_reserve(skb, boundary - data);
+       return skb;
+}
+
+/* Allocate just enough space, and verify that the allocated
+ * space does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small(int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long roundup, data, end;
+
+       skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD);
+       if (unlikely(skb == NULL))
+               return NULL;
+
+       /* Round allocated buffer to 16 byte boundary */
+       data = (unsigned long)(skb->data);
+       roundup = (-data) & 15UL;
+       skb_reserve(skb, roundup);
+       /* Verify that the data buffer does not cross a page boundary */
+       data = (unsigned long)(skb->data);
+       end = data + bytes + MXGEFW_PAD - 1;
+       if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) {
+               printk(KERN_NOTICE
+                      "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
+               myri10ge_skb_cross_4k = 1;
+               dev_kfree_skb_any(skb);
+               skb = myri10ge_alloc_small_safe(bytes);
+       }
+       return skb;
+}
+
+static inline int
+myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
+               int idx)
+{
+       struct sk_buff *skb;
+       dma_addr_t bus;
+       int len, retval = 0;
+
+       bytes += VLAN_HLEN;     /* account for 802.1q vlan tag */
+
+       if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
+               skb = myri10ge_alloc_big(bytes);
+       else if (myri10ge_skb_cross_4k)
+               skb = myri10ge_alloc_small_safe(bytes);
+       else
+               skb = myri10ge_alloc_small(bytes);
+
+       if (unlikely(skb == NULL)) {
+               rx->alloc_fail++;
+               retval = -ENOBUFS;
+               goto done;
+       }
+
+       /* set len so that it only covers the area we
+        * need mapped for DMA */
+       len = bytes + MXGEFW_PAD;
+
+       bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
+       rx->info[idx].skb = skb;
+       pci_unmap_addr_set(&rx->info[idx], bus, bus);
+       pci_unmap_len_set(&rx->info[idx], len, len);
+       rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus));
+       rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
+
+done:
+       /* copy 8 descriptors (64-bytes) to the mcp at a time */
+       if ((idx & 7) == 7) {
+               if (rx->wc_fifo == NULL)
+                       myri10ge_submit_8rx(&rx->lanai[idx - 7],
+                                           &rx->shadow[idx - 7]);
+               else {
+                       mb();
+                       myri10ge_pio_copy(rx->wc_fifo,
+                                         &rx->shadow[idx - 7], 64);
+               }
+       }
+       return retval;
+}
+
+static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
+{
+       struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
+
+       if ((skb->protocol == ntohs(ETH_P_8021Q)) &&
+           (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
+            vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
+               skb->csum = hw_csum;
+               skb->ip_summed = CHECKSUM_HW;
+       }
+}
+
+static inline unsigned long
+myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+                int bytes, int len, int csum)
+{
+       dma_addr_t bus;
+       struct sk_buff *skb;
+       int idx, unmap_len;
+
+       idx = rx->cnt & rx->mask;
+       rx->cnt++;
+
+       /* save a pointer to the received skb */
+       skb = rx->info[idx].skb;
+       bus = pci_unmap_addr(&rx->info[idx], bus);
+       unmap_len = pci_unmap_len(&rx->info[idx], len);
+
+       /* try to replace the received skb */
+       if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) {
+               /* drop the frame -- the old skbuf is re-cycled */
+               mgp->stats.rx_dropped += 1;
+               return 0;
+       }
+
+       /* unmap the recvd skb */
+       pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE);
+
+       /* mcp implicitly skips 1st bytes so that packet is properly
+        * aligned */
+       skb_reserve(skb, MXGEFW_PAD);
+
+       /* set the length of the frame */
+       skb_put(skb, len);
+
+       skb->protocol = eth_type_trans(skb, mgp->dev);
+       skb->dev = mgp->dev;
+       if (mgp->csum_flag) {
+               if ((skb->protocol == ntohs(ETH_P_IP)) ||
+                   (skb->protocol == ntohs(ETH_P_IPV6))) {
+                       skb->csum = ntohs((u16) csum);
+                       skb->ip_summed = CHECKSUM_HW;
+               } else
+                       myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
+       }
+
+       netif_receive_skb(skb);
+       mgp->dev->last_rx = jiffies;
+       return 1;
+}
+
+static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       struct sk_buff *skb;
+       int idx, len;
+       int limit = 0;
+
+       while (tx->pkt_done != mcp_index) {
+               idx = tx->done & tx->mask;
+               skb = tx->info[idx].skb;
+
+               /* Mark as free */
+               tx->info[idx].skb = NULL;
+               if (tx->info[idx].last) {
+                       tx->pkt_done++;
+                       tx->info[idx].last = 0;
+               }
+               tx->done++;
+               len = pci_unmap_len(&tx->info[idx], len);
+               pci_unmap_len_set(&tx->info[idx], len, 0);
+               if (skb) {
+                       mgp->stats.tx_bytes += skb->len;
+                       mgp->stats.tx_packets++;
+                       dev_kfree_skb_irq(skb);
+                       if (len)
+                               pci_unmap_single(pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+               } else {
+                       if (len)
+                               pci_unmap_page(pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+               }
+
+               /* limit potential for livelock by only handling
+                * 2 full tx rings per call */
+               if (unlikely(++limit > 2 * tx->mask))
+                       break;
+       }
+       /* start the queue if we've stopped it */
+       if (netif_queue_stopped(mgp->dev)
+           && tx->req - tx->done < (tx->mask >> 1)) {
+               mgp->wake_queue++;
+               netif_wake_queue(mgp->dev);
+       }
+}
+
+static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
+{
+       struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+       unsigned long rx_bytes = 0;
+       unsigned long rx_packets = 0;
+       unsigned long rx_ok;
+
+       int idx = rx_done->idx;
+       int cnt = rx_done->cnt;
+       u16 length;
+       u16 checksum;
+
+       while (rx_done->entry[idx].length != 0 && *limit != 0) {
+               length = ntohs(rx_done->entry[idx].length);
+               rx_done->entry[idx].length = 0;
+               checksum = ntohs(rx_done->entry[idx].checksum);
+               if (length <= mgp->small_bytes)
+                       rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small,
+                                                mgp->small_bytes,
+                                                length, checksum);
+               else
+                       rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big,
+                                                mgp->dev->mtu + ETH_HLEN,
+                                                length, checksum);
+               rx_packets += rx_ok;
+               rx_bytes += rx_ok * (unsigned long)length;
+               cnt++;
+               idx = cnt & (myri10ge_max_intr_slots - 1);
+
+               /* limit potential for livelock by only handling a
+                * limited number of frames. */
+               (*limit)--;
+       }
+       rx_done->idx = idx;
+       rx_done->cnt = cnt;
+       mgp->stats.rx_packets += rx_packets;
+       mgp->stats.rx_bytes += rx_bytes;
+}
+
+static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
+{
+       struct mcp_irq_data *stats = mgp->fw_stats;
+
+       if (unlikely(stats->stats_updated)) {
+               if (mgp->link_state != stats->link_up) {
+                       mgp->link_state = stats->link_up;
+                       if (mgp->link_state) {
+                               printk(KERN_INFO "myri10ge: %s: link up\n",
+                                      mgp->dev->name);
+                               netif_carrier_on(mgp->dev);
+                       } else {
+                               printk(KERN_INFO "myri10ge: %s: link down\n",
+                                      mgp->dev->name);
+                               netif_carrier_off(mgp->dev);
+                       }
+               }
+               if (mgp->rdma_tags_available !=
+                   ntohl(mgp->fw_stats->rdma_tags_available)) {
+                       mgp->rdma_tags_available =
+                           ntohl(mgp->fw_stats->rdma_tags_available);
+                       printk(KERN_WARNING "myri10ge: %s: RDMA timed out! "
+                              "%d tags left\n", mgp->dev->name,
+                              mgp->rdma_tags_available);
+               }
+               mgp->down_cnt += stats->link_down;
+               if (stats->link_down)
+                       wake_up(&mgp->down_wq);
+       }
+}
+
+static int myri10ge_poll(struct net_device *netdev, int *budget)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+       int limit, orig_limit, work_done;
+
+       /* process as many rx events as NAPI will allow */
+       limit = min(*budget, netdev->quota);
+       orig_limit = limit;
+       myri10ge_clean_rx_done(mgp, &limit);
+       work_done = orig_limit - limit;
+       *budget -= work_done;
+       netdev->quota -= work_done;
+
+       if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
+               netif_rx_complete(netdev);
+               __raw_writel(htonl(3), mgp->irq_claim);
+               return 0;
+       }
+       return 1;
+}
+
+static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs)
+{
+       struct myri10ge_priv *mgp = arg;
+       struct mcp_irq_data *stats = mgp->fw_stats;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       u32 send_done_count;
+       int i;
+
+       /* make sure it is our IRQ, and that the DMA has finished */
+       if (unlikely(!stats->valid))
+               return (IRQ_NONE);
+
+       /* low bit indicates receives are present, so schedule
+        * napi poll handler */
+       if (stats->valid & 1)
+               netif_rx_schedule(mgp->dev);
+
+       if (!mgp->msi_enabled) {
+               __raw_writel(0, mgp->irq_deassert);
+               if (!myri10ge_deassert_wait)
+                       stats->valid = 0;
+               mb();
+       } else
+               stats->valid = 0;
+
+       /* Wait for IRQ line to go low, if using INTx */
+       i = 0;
+       while (1) {
+               i++;
+               /* check for transmit completes and receives */
+               send_done_count = ntohl(stats->send_done_count);
+               if (send_done_count != tx->pkt_done)
+                       myri10ge_tx_done(mgp, (int)send_done_count);
+               if (unlikely(i > myri10ge_max_irq_loops)) {
+                       printk(KERN_WARNING "myri10ge: %s: irq stuck?\n",
+                              mgp->dev->name);
+                       stats->valid = 0;
+                       schedule_work(&mgp->watchdog_work);
+               }
+               if (likely(stats->valid == 0))
+                       break;
+               cpu_relax();
+               barrier();
+       }
+
+       myri10ge_check_statblock(mgp);
+
+       __raw_writel(htonl(3), mgp->irq_claim + 1);
+       return (IRQ_HANDLED);
+}
+
+static int
+myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+       cmd->autoneg = AUTONEG_DISABLE;
+       cmd->speed = SPEED_10000;
+       cmd->duplex = DUPLEX_FULL;
+       return 0;
+}
+
+static void
+myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       strlcpy(info->driver, "myri10ge", sizeof(info->driver));
+       strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
+       strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
+       strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
+}
+
+static int
+myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       coal->rx_coalesce_usecs = mgp->intr_coal_delay;
+       return 0;
+}
+
+static int
+myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       mgp->intr_coal_delay = coal->rx_coalesce_usecs;
+       __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+       return 0;
+}
+
+static void
+myri10ge_get_pauseparam(struct net_device *netdev,
+                       struct ethtool_pauseparam *pause)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       pause->autoneg = 0;
+       pause->rx_pause = mgp->pause;
+       pause->tx_pause = mgp->pause;
+}
+
+static int
+myri10ge_set_pauseparam(struct net_device *netdev,
+                       struct ethtool_pauseparam *pause)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       if (pause->tx_pause != mgp->pause)
+               return myri10ge_change_pause(mgp, pause->tx_pause);
+       if (pause->rx_pause != mgp->pause)
+               return myri10ge_change_pause(mgp, pause->tx_pause);
+       if (pause->autoneg != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static void
+myri10ge_get_ringparam(struct net_device *netdev,
+                      struct ethtool_ringparam *ring)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       ring->rx_mini_max_pending = mgp->rx_small.mask + 1;
+       ring->rx_max_pending = mgp->rx_big.mask + 1;
+       ring->rx_jumbo_max_pending = 0;
+       ring->tx_max_pending = mgp->rx_small.mask + 1;
+       ring->rx_mini_pending = ring->rx_mini_max_pending;
+       ring->rx_pending = ring->rx_max_pending;
+       ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
+       ring->tx_pending = ring->tx_max_pending;
+}
+
+static u32 myri10ge_get_rx_csum(struct net_device *netdev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       if (mgp->csum_flag)
+               return 1;
+       else
+               return 0;
+}
+
+static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       if (csum_enabled)
+               mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+       else
+               mgp->csum_flag = 0;
+       return 0;
+}
+
+static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
+       "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+       "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+       "rx_length_errors", "rx_over_errors", "rx_crc_errors",
+       "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+       "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+       "tx_heartbeat_errors", "tx_window_errors",
+       /* device-specific stats */
+       "tx_boundary", "WC", "irq", "MSI",
+       "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
+       "serial_number", "tx_pkt_start", "tx_pkt_done",
+       "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
+       "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
+       "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered",
+       "dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
+       "dropped_no_big_buffer"
+};
+
+#define MYRI10GE_NET_STATS_LEN      21
+#define MYRI10GE_STATS_LEN  sizeof(myri10ge_gstrings_stats) / ETH_GSTRING_LEN
+
+static void
+myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data)
+{
+       switch (stringset) {
+       case ETH_SS_STATS:
+               memcpy(data, *myri10ge_gstrings_stats,
+                      sizeof(myri10ge_gstrings_stats));
+               break;
+       }
+}
+
+static int myri10ge_get_stats_count(struct net_device *netdev)
+{
+       return MYRI10GE_STATS_LEN;
+}
+
+static void
+myri10ge_get_ethtool_stats(struct net_device *netdev,
+                          struct ethtool_stats *stats, u64 * data)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       int i;
+
+       for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
+               data[i] = ((unsigned long *)&mgp->stats)[i];
+
+       data[i++] = (unsigned int)mgp->tx.boundary;
+       data[i++] = (unsigned int)(mgp->mtrr >= 0);
+       data[i++] = (unsigned int)mgp->pdev->irq;
+       data[i++] = (unsigned int)mgp->msi_enabled;
+       data[i++] = (unsigned int)mgp->read_dma;
+       data[i++] = (unsigned int)mgp->write_dma;
+       data[i++] = (unsigned int)mgp->read_write_dma;
+       data[i++] = (unsigned int)mgp->serial_number;
+       data[i++] = (unsigned int)mgp->tx.pkt_start;
+       data[i++] = (unsigned int)mgp->tx.pkt_done;
+       data[i++] = (unsigned int)mgp->tx.req;
+       data[i++] = (unsigned int)mgp->tx.done;
+       data[i++] = (unsigned int)mgp->rx_small.cnt;
+       data[i++] = (unsigned int)mgp->rx_big.cnt;
+       data[i++] = (unsigned int)mgp->wake_queue;
+       data[i++] = (unsigned int)mgp->stop_queue;
+       data[i++] = (unsigned int)mgp->watchdog_resets;
+       data[i++] = (unsigned int)mgp->tx_linearized;
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
+       data[i++] =
+           (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
+}
+
+static struct ethtool_ops myri10ge_ethtool_ops = {
+       .get_settings = myri10ge_get_settings,
+       .get_drvinfo = myri10ge_get_drvinfo,
+       .get_coalesce = myri10ge_get_coalesce,
+       .set_coalesce = myri10ge_set_coalesce,
+       .get_pauseparam = myri10ge_get_pauseparam,
+       .set_pauseparam = myri10ge_set_pauseparam,
+       .get_ringparam = myri10ge_get_ringparam,
+       .get_rx_csum = myri10ge_get_rx_csum,
+       .set_rx_csum = myri10ge_set_rx_csum,
+       .get_tx_csum = ethtool_op_get_tx_csum,
+       .set_tx_csum = ethtool_op_set_tx_hw_csum,
+       .get_sg = ethtool_op_get_sg,
+       .set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = ethtool_op_set_tso,
+#endif
+       .get_strings = myri10ge_get_strings,
+       .get_stats_count = myri10ge_get_stats_count,
+       .get_ethtool_stats = myri10ge_get_ethtool_stats
+};
+
+static int myri10ge_allocate_rings(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int tx_ring_size, rx_ring_size;
+       int tx_ring_entries, rx_ring_entries;
+       int i, status;
+       size_t bytes;
+
+       mgp = netdev_priv(dev);
+
+       /* get ring sizes */
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
+       tx_ring_size = cmd.data0;
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
+       rx_ring_size = cmd.data0;
+
+       tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send);
+       rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr);
+       mgp->tx.mask = tx_ring_entries - 1;
+       mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1;
+
+       /* allocate the host shadow rings */
+
+       bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4)
+           * sizeof(*mgp->tx.req_list);
+       mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->tx.req_bytes == NULL)
+               goto abort_with_nothing;
+
+       /* ensure req_list entries are aligned to 8 bytes */
+       mgp->tx.req_list = (struct mcp_kreq_ether_send *)
+           ALIGN((unsigned long)mgp->tx.req_bytes, 8);
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow);
+       mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_small.shadow == NULL)
+               goto abort_with_tx_req_bytes;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow);
+       mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_big.shadow == NULL)
+               goto abort_with_rx_small_shadow;
+
+       /* allocate the host info rings */
+
+       bytes = tx_ring_entries * sizeof(*mgp->tx.info);
+       mgp->tx.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->tx.info == NULL)
+               goto abort_with_rx_big_shadow;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_small.info);
+       mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_small.info == NULL)
+               goto abort_with_tx_info;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_big.info);
+       mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_big.info == NULL)
+               goto abort_with_rx_small_info;
+
+       /* Fill the receive rings */
+
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev,
+                                        mgp->small_bytes, i);
+               if (status) {
+                       printk(KERN_ERR
+                              "myri10ge: %s: alloced only %d small bufs\n",
+                              dev->name, i);
+                       goto abort_with_rx_small_ring;
+               }
+       }
+
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               status =
+                   myri10ge_getbuf(&mgp->rx_big, mgp->pdev,
+                                   dev->mtu + ETH_HLEN, i);
+               if (status) {
+                       printk(KERN_ERR
+                              "myri10ge: %s: alloced only %d big bufs\n",
+                              dev->name, i);
+                       goto abort_with_rx_big_ring;
+               }
+       }
+
+       return 0;
+
+abort_with_rx_big_ring:
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               if (mgp->rx_big.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_big.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_big.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_big.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_big.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+
+abort_with_rx_small_ring:
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               if (mgp->rx_small.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_small.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_small.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_small.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_small.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+       kfree(mgp->rx_big.info);
+
+abort_with_rx_small_info:
+       kfree(mgp->rx_small.info);
+
+abort_with_tx_info:
+       kfree(mgp->tx.info);
+
+abort_with_rx_big_shadow:
+       kfree(mgp->rx_big.shadow);
+
+abort_with_rx_small_shadow:
+       kfree(mgp->rx_small.shadow);
+
+abort_with_tx_req_bytes:
+       kfree(mgp->tx.req_bytes);
+       mgp->tx.req_bytes = NULL;
+       mgp->tx.req_list = NULL;
+
+abort_with_nothing:
+       return status;
+}
+
+static void myri10ge_free_rings(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct sk_buff *skb;
+       struct myri10ge_tx_buf *tx;
+       int i, len, idx;
+
+       mgp = netdev_priv(dev);
+
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               if (mgp->rx_big.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_big.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_big.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_big.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_big.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               if (mgp->rx_small.info[i].skb != NULL)
+                       dev_kfree_skb_any(mgp->rx_small.info[i].skb);
+               if (pci_unmap_len(&mgp->rx_small.info[i], len))
+                       pci_unmap_single(mgp->pdev,
+                                        pci_unmap_addr(&mgp->rx_small.info[i],
+                                                       bus),
+                                        pci_unmap_len(&mgp->rx_small.info[i],
+                                                      len),
+                                        PCI_DMA_FROMDEVICE);
+       }
+
+       tx = &mgp->tx;
+       while (tx->done != tx->req) {
+               idx = tx->done & tx->mask;
+               skb = tx->info[idx].skb;
+
+               /* Mark as free */
+               tx->info[idx].skb = NULL;
+               tx->done++;
+               len = pci_unmap_len(&tx->info[idx], len);
+               pci_unmap_len_set(&tx->info[idx], len, 0);
+               if (skb) {
+                       mgp->stats.tx_dropped++;
+                       dev_kfree_skb_any(skb);
+                       if (len)
+                               pci_unmap_single(mgp->pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+               } else {
+                       if (len)
+                               pci_unmap_page(mgp->pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+               }
+       }
+       kfree(mgp->rx_big.info);
+
+       kfree(mgp->rx_small.info);
+
+       kfree(mgp->tx.info);
+
+       kfree(mgp->rx_big.shadow);
+
+       kfree(mgp->rx_small.shadow);
+
+       kfree(mgp->tx.req_bytes);
+       mgp->tx.req_bytes = NULL;
+       mgp->tx.req_list = NULL;
+}
+
+static int myri10ge_open(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int status, big_pow2;
+
+       mgp = netdev_priv(dev);
+
+       if (mgp->running != MYRI10GE_ETH_STOPPED)
+               return -EBUSY;
+
+       mgp->running = MYRI10GE_ETH_STARTING;
+       status = myri10ge_reset(mgp);
+       if (status != 0) {
+               printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name);
+               mgp->running = MYRI10GE_ETH_STOPPED;
+               return -ENXIO;
+       }
+
+       /* decide what small buffer size to use.  For good TCP rx
+        * performance, it is important to not receive 1514 byte
+        * frames into jumbo buffers, as it confuses the socket buffer
+        * accounting code, leading to drops and erratic performance.
+        */
+
+       if (dev->mtu <= ETH_DATA_LEN)
+               mgp->small_bytes = 128; /* enough for a TCP header */
+       else
+               mgp->small_bytes = ETH_FRAME_LEN;       /* enough for an ETH_DATA_LEN frame */
+
+       /* Override the small buffer size? */
+       if (myri10ge_small_bytes > 0)
+               mgp->small_bytes = myri10ge_small_bytes;
+
+       /* If the user sets an obscenely small MTU, adjust the small
+        * bytes down to nearly nothing */
+       if (mgp->small_bytes >= (dev->mtu + ETH_HLEN))
+               mgp->small_bytes = 64;
+
+       /* get the lanai pointers to the send and receive rings */
+
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
+       mgp->tx.lanai =
+           (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0);
+
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0);
+       mgp->rx_small.lanai =
+           (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0);
+       mgp->rx_big.lanai =
+           (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+       if (status != 0) {
+               printk(KERN_ERR
+                      "myri10ge: %s: failed to get ring sizes or locations\n",
+                      dev->name);
+               mgp->running = MYRI10GE_ETH_STOPPED;
+               return -ENXIO;
+       }
+
+       if (mgp->mtrr >= 0) {
+               mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000;
+               mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000;
+               mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000;
+       } else {
+               mgp->tx.wc_fifo = NULL;
+               mgp->rx_small.wc_fifo = NULL;
+               mgp->rx_big.wc_fifo = NULL;
+       }
+
+       status = myri10ge_allocate_rings(dev);
+       if (status != 0)
+               goto abort_with_nothing;
+
+       /* Firmware needs the big buff size as a power of 2.  Lie and
+        * tell him the buffer is larger, because we only use 1
+        * buffer/pkt, and the mtu will prevent overruns.
+        */
+       big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD;
+       while ((big_pow2 & (big_pow2 - 1)) != 0)
+               big_pow2++;
+
+       /* now give firmware buffers sizes, and MTU */
+       cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0);
+       cmd.data0 = mgp->small_bytes;
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd, 0);
+       cmd.data0 = big_pow2;
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus);
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       mgp->link_state = -1;
+       mgp->rdma_tags_available = 15;
+
+       netif_poll_enable(mgp->dev);    /* must happen prior to any irq */
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       mgp->wake_queue = 0;
+       mgp->stop_queue = 0;
+       mgp->running = MYRI10GE_ETH_RUNNING;
+       mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
+       add_timer(&mgp->watchdog_timer);
+       netif_wake_queue(dev);
+       return 0;
+
+abort_with_rings:
+       myri10ge_free_rings(dev);
+
+abort_with_nothing:
+       mgp->running = MYRI10GE_ETH_STOPPED;
+       return -ENOMEM;
+}
+
+static int myri10ge_close(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int status, old_down_cnt;
+
+       mgp = netdev_priv(dev);
+
+       if (mgp->running != MYRI10GE_ETH_RUNNING)
+               return 0;
+
+       if (mgp->tx.req_bytes == NULL)
+               return 0;
+
+       del_timer_sync(&mgp->watchdog_timer);
+       mgp->running = MYRI10GE_ETH_STOPPING;
+       netif_poll_disable(mgp->dev);
+       netif_carrier_off(dev);
+       netif_stop_queue(dev);
+       old_down_cnt = mgp->down_cnt;
+       mb();
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+       if (status)
+               printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
+                      dev->name);
+
+       wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
+       if (old_down_cnt == mgp->down_cnt)
+               printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+
+       netif_tx_disable(dev);
+
+       myri10ge_free_rings(dev);
+
+       mgp->running = MYRI10GE_ETH_STOPPED;
+       return 0;
+}
+
+/* copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * backwards one at a time and handle ring wraps */
+
+static inline void
+myri10ge_submit_req_backwards(struct myri10ge_tx_buf *tx,
+                             struct mcp_kreq_ether_send *src, int cnt)
+{
+       int idx, starting_slot;
+       starting_slot = tx->req;
+       while (cnt > 1) {
+               cnt--;
+               idx = (starting_slot + cnt) & tx->mask;
+               myri10ge_pio_copy(&tx->lanai[idx], &src[cnt], sizeof(*src));
+               mb();
+       }
+}
+
+/*
+ * copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * at most 32 bytes at a time, so as to avoid involving the software
+ * pio handler in the nic.   We re-write the first segment's flags
+ * to mark them valid only after writing the entire chain.
+ */
+
+static inline void
+myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
+                   int cnt)
+{
+       int idx, i;
+       struct mcp_kreq_ether_send __iomem *dstp, *dst;
+       struct mcp_kreq_ether_send *srcp;
+       u8 last_flags;
+
+       idx = tx->req & tx->mask;
+
+       last_flags = src->flags;
+       src->flags = 0;
+       mb();
+       dst = dstp = &tx->lanai[idx];
+       srcp = src;
+
+       if ((idx + cnt) < tx->mask) {
+               for (i = 0; i < (cnt - 1); i += 2) {
+                       myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+                       mb();   /* force write every 32 bytes */
+                       srcp += 2;
+                       dstp += 2;
+               }
+       } else {
+               /* submit all but the first request, and ensure
+                * that it is submitted below */
+               myri10ge_submit_req_backwards(tx, src, cnt);
+               i = 0;
+       }
+       if (i < cnt) {
+               /* submit the first request */
+               myri10ge_pio_copy(dstp, srcp, sizeof(*src));
+               mb();           /* barrier before setting valid flag */
+       }
+
+       /* re-write the last 32-bits with the valid flags */
+       src->flags = last_flags;
+       __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3);
+       tx->req += cnt;
+       mb();
+}
+
+static inline void
+myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
+                      struct mcp_kreq_ether_send *src, int cnt)
+{
+       tx->req += cnt;
+       mb();
+       while (cnt >= 4) {
+               myri10ge_pio_copy(tx->wc_fifo, src, 64);
+               mb();
+               src += 4;
+               cnt -= 4;
+       }
+       if (cnt > 0) {
+               /* pad it to 64 bytes.  The src is 64 bytes bigger than it
+                * needs to be so that we don't overrun it */
+               myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64);
+               mb();
+       }
+}
+
+/*
+ * Transmit a packet.  We need to split the packet so that a single
+ * segment does not cross myri10ge->tx.boundary, so this makes segment
+ * counting tricky.  So rather than try to count segments up front, we
+ * just give up if there are too few segments to hold a reasonably
+ * fragmented packet currently available.  If we run
+ * out of segments while preparing a packet for DMA, we just linearize
+ * it and try again.
+ */
+
+static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       struct mcp_kreq_ether_send *req;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       struct skb_frag_struct *frag;
+       dma_addr_t bus;
+       u32 low, high_swapped;
+       unsigned int len;
+       int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
+       u16 pseudo_hdr_offset, cksum_offset;
+       int cum_len, seglen, boundary, rdma_count;
+       u8 flags, odd_flag;
+
+again:
+       req = tx->req_list;
+       avail = tx->mask - 1 - (tx->req - tx->done);
+
+       mss = 0;
+       max_segments = MXGEFW_MAX_SEND_DESC;
+
+#ifdef NETIF_F_TSO
+       if (skb->len > (dev->mtu + ETH_HLEN)) {
+               mss = skb_shinfo(skb)->gso_size;
+               if (mss != 0)
+                       max_segments = MYRI10GE_MAX_SEND_DESC_TSO;
+       }
+#endif                         /*NETIF_F_TSO */
+
+       if ((unlikely(avail < max_segments))) {
+               /* we are out of transmit resources */
+               mgp->stop_queue++;
+               netif_stop_queue(dev);
+               return 1;
+       }
+
+       /* Setup checksum offloading, if needed */
+       cksum_offset = 0;
+       pseudo_hdr_offset = 0;
+       odd_flag = 0;
+       flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
+       if (likely(skb->ip_summed == CHECKSUM_HW)) {
+               cksum_offset = (skb->h.raw - skb->data);
+               pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data;
+               /* If the headers are excessively large, then we must
+                * fall back to a software checksum */
+               if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
+                       if (skb_checksum_help(skb, 0))
+                               goto drop;
+                       cksum_offset = 0;
+                       pseudo_hdr_offset = 0;
+               } else {
+                       pseudo_hdr_offset = htons(pseudo_hdr_offset);
+                       odd_flag = MXGEFW_FLAGS_ALIGN_ODD;
+                       flags |= MXGEFW_FLAGS_CKSUM;
+               }
+       }
+
+       cum_len = 0;
+
+#ifdef NETIF_F_TSO
+       if (mss) {              /* TSO */
+               /* this removes any CKSUM flag from before */
+               flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST);
+
+               /* negative cum_len signifies to the
+                * send loop that we are still in the
+                * header portion of the TSO packet.
+                * TSO header must be at most 134 bytes long */
+               cum_len = -((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+
+               /* for TSO, pseudo_hdr_offset holds mss.
+                * The firmware figures out where to put
+                * the checksum by parsing the header. */
+               pseudo_hdr_offset = htons(mss);
+       } else
+#endif                         /*NETIF_F_TSO */
+               /* Mark small packets, and pad out tiny packets */
+       if (skb->len <= MXGEFW_SEND_SMALL_SIZE) {
+               flags |= MXGEFW_FLAGS_SMALL;
+
+               /* pad frames to at least ETH_ZLEN bytes */
+               if (unlikely(skb->len < ETH_ZLEN)) {
+                       if (skb_padto(skb, ETH_ZLEN)) {
+                               /* The packet is gone, so we must
+                                * return 0 */
+                               mgp->stats.tx_dropped += 1;
+                               return 0;
+                       }
+                       /* adjust the len to account for the zero pad
+                        * so that the nic can know how long it is */
+                       skb->len = ETH_ZLEN;
+               }
+       }
+
+       /* map the skb for DMA */
+       len = skb->len - skb->data_len;
+       idx = tx->req & tx->mask;
+       tx->info[idx].skb = skb;
+       bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+       pci_unmap_addr_set(&tx->info[idx], bus, bus);
+       pci_unmap_len_set(&tx->info[idx], len, len);
+
+       frag_cnt = skb_shinfo(skb)->nr_frags;
+       frag_idx = 0;
+       count = 0;
+       rdma_count = 0;
+
+       /* "rdma_count" is the number of RDMAs belonging to the
+        * current packet BEFORE the current send request. For
+        * non-TSO packets, this is equal to "count".
+        * For TSO packets, rdma_count needs to be reset
+        * to 0 after a segment cut.
+        *
+        * The rdma_count field of the send request is
+        * the number of RDMAs of the packet starting at
+        * that request. For TSO send requests with one ore more cuts
+        * in the middle, this is the number of RDMAs starting
+        * after the last cut in the request. All previous
+        * segments before the last cut implicitly have 1 RDMA.
+        *
+        * Since the number of RDMAs is not known beforehand,
+        * it must be filled-in retroactively - after each
+        * segmentation cut or at the end of the entire packet.
+        */
+
+       while (1) {
+               /* Break the SKB or Fragment up into pieces which
+                * do not cross mgp->tx.boundary */
+               low = MYRI10GE_LOWPART_TO_U32(bus);
+               high_swapped = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
+               while (len) {
+                       u8 flags_next;
+                       int cum_len_next;
+
+                       if (unlikely(count == max_segments))
+                               goto abort_linearize;
+
+                       boundary = (low + tx->boundary) & ~(tx->boundary - 1);
+                       seglen = boundary - low;
+                       if (seglen > len)
+                               seglen = len;
+                       flags_next = flags & ~MXGEFW_FLAGS_FIRST;
+                       cum_len_next = cum_len + seglen;
+#ifdef NETIF_F_TSO
+                       if (mss) {      /* TSO */
+                               (req - rdma_count)->rdma_count = rdma_count + 1;
+
+                               if (likely(cum_len >= 0)) {     /* payload */
+                                       int next_is_first, chop;
+
+                                       chop = (cum_len_next > mss);
+                                       cum_len_next = cum_len_next % mss;
+                                       next_is_first = (cum_len_next == 0);
+                                       flags |= chop * MXGEFW_FLAGS_TSO_CHOP;
+                                       flags_next |= next_is_first *
+                                           MXGEFW_FLAGS_FIRST;
+                                       rdma_count |= -(chop | next_is_first);
+                                       rdma_count += chop & !next_is_first;
+                               } else if (likely(cum_len_next >= 0)) { /* header ends */
+                                       int small;
+
+                                       rdma_count = -1;
+                                       cum_len_next = 0;
+                                       seglen = -cum_len;
+                                       small = (mss <= MXGEFW_SEND_SMALL_SIZE);
+                                       flags_next = MXGEFW_FLAGS_TSO_PLD |
+                                           MXGEFW_FLAGS_FIRST |
+                                           (small * MXGEFW_FLAGS_SMALL);
+                               }
+                       }
+#endif                         /* NETIF_F_TSO */
+                       req->addr_high = high_swapped;
+                       req->addr_low = htonl(low);
+                       req->pseudo_hdr_offset = pseudo_hdr_offset;
+                       req->pad = 0;   /* complete solid 16-byte block; does this matter? */
+                       req->rdma_count = 1;
+                       req->length = htons(seglen);
+                       req->cksum_offset = cksum_offset;
+                       req->flags = flags | ((cum_len & 1) * odd_flag);
+
+                       low += seglen;
+                       len -= seglen;
+                       cum_len = cum_len_next;
+                       flags = flags_next;
+                       req++;
+                       count++;
+                       rdma_count++;
+                       if (unlikely(cksum_offset > seglen))
+                               cksum_offset -= seglen;
+                       else
+                               cksum_offset = 0;
+               }
+               if (frag_idx == frag_cnt)
+                       break;
+
+               /* map next fragment for DMA */
+               idx = (count + tx->req) & tx->mask;
+               frag = &skb_shinfo(skb)->frags[frag_idx];
+               frag_idx++;
+               len = frag->size;
+               bus = pci_map_page(mgp->pdev, frag->page, frag->page_offset,
+                                  len, PCI_DMA_TODEVICE);
+               pci_unmap_addr_set(&tx->info[idx], bus, bus);
+               pci_unmap_len_set(&tx->info[idx], len, len);
+       }
+
+       (req - rdma_count)->rdma_count = rdma_count;
+#ifdef NETIF_F_TSO
+       if (mss)
+               do {
+                       req--;
+                       req->flags |= MXGEFW_FLAGS_TSO_LAST;
+               } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP |
+                                        MXGEFW_FLAGS_FIRST)));
+#endif
+       idx = ((count - 1) + tx->req) & tx->mask;
+       tx->info[idx].last = 1;
+       if (tx->wc_fifo == NULL)
+               myri10ge_submit_req(tx, tx->req_list, count);
+       else
+               myri10ge_submit_req_wc(tx, tx->req_list, count);
+       tx->pkt_start++;
+       if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
+               mgp->stop_queue++;
+               netif_stop_queue(dev);
+       }
+       dev->trans_start = jiffies;
+       return 0;
+
+abort_linearize:
+       /* Free any DMA resources we've alloced and clear out the skb
+        * slot so as to not trip up assertions, and to avoid a
+        * double-free if linearizing fails */
+
+       last_idx = (idx + 1) & tx->mask;
+       idx = tx->req & tx->mask;
+       tx->info[idx].skb = NULL;
+       do {
+               len = pci_unmap_len(&tx->info[idx], len);
+               if (len) {
+                       if (tx->info[idx].skb != NULL)
+                               pci_unmap_single(mgp->pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+                       else
+                               pci_unmap_page(mgp->pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+                       pci_unmap_len_set(&tx->info[idx], len, 0);
+                       tx->info[idx].skb = NULL;
+               }
+               idx = (idx + 1) & tx->mask;
+       } while (idx != last_idx);
+       if (skb_is_gso(skb)) {
+               printk(KERN_ERR
+                      "myri10ge: %s: TSO but wanted to linearize?!?!?\n",
+                      mgp->dev->name);
+               goto drop;
+       }
+
+       if (skb_linearize(skb))
+               goto drop;
+
+       mgp->tx_linearized++;
+       goto again;
+
+drop:
+       dev_kfree_skb_any(skb);
+       mgp->stats.tx_dropped += 1;
+       return 0;
+
+}
+
+static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       return &mgp->stats;
+}
+
+static void myri10ge_set_multicast_list(struct net_device *dev)
+{
+       /* can be called from atomic contexts,
+        * pass 1 to force atomicity in myri10ge_send_cmd() */
+       myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1);
+}
+
+static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *sa = addr;
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       int status;
+
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EADDRNOTAVAIL;
+
+       status = myri10ge_update_mac_address(mgp, sa->sa_data);
+       if (status != 0) {
+               printk(KERN_ERR
+                      "myri10ge: %s: changing mac address failed with %d\n",
+                      dev->name, status);
+               return status;
+       }
+
+       /* change the dev structure */
+       memcpy(dev->dev_addr, sa->sa_data, 6);
+       return 0;
+}
+
+static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       int error = 0;
+
+       if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) {
+               printk(KERN_ERR "myri10ge: %s: new mtu (%d) is not valid\n",
+                      dev->name, new_mtu);
+               return -EINVAL;
+       }
+       printk(KERN_INFO "%s: changing mtu from %d to %d\n",
+              dev->name, dev->mtu, new_mtu);
+       if (mgp->running) {
+               /* if we change the mtu on an active device, we must
+                * reset the device so the firmware sees the change */
+               myri10ge_close(dev);
+               dev->mtu = new_mtu;
+               myri10ge_open(dev);
+       } else
+               dev->mtu = new_mtu;
+
+       return error;
+}
+
+/*
+ * Enable ECRC to align PCI-E Completion packets on an 8-byte boundary.
+ * Only do it if the bridge is a root port since we don't want to disturb
+ * any other device, except if forced with myri10ge_ecrc_enable > 1.
+ */
+
+static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *bridge = mgp->pdev->bus->self;
+       struct device *dev = &mgp->pdev->dev;
+       unsigned cap;
+       unsigned err_cap;
+       u16 val;
+       u8 ext_type;
+       int ret;
+
+       if (!myri10ge_ecrc_enable || !bridge)
+               return;
+
+       /* check that the bridge is a root port */
+       cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+       pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
+       ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
+       if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
+               if (myri10ge_ecrc_enable > 1) {
+                       struct pci_dev *old_bridge = bridge;
+
+                       /* Walk the hierarchy up to the root port
+                        * where ECRC has to be enabled */
+                       do {
+                               bridge = bridge->bus->self;
+                               if (!bridge) {
+                                       dev_err(dev,
+                                               "Failed to find root port"
+                                               " to force ECRC\n");
+                                       return;
+                               }
+                               cap =
+                                   pci_find_capability(bridge, PCI_CAP_ID_EXP);
+                               pci_read_config_word(bridge,
+                                                    cap + PCI_CAP_FLAGS, &val);
+                               ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
+                       } while (ext_type != PCI_EXP_TYPE_ROOT_PORT);
+
+                       dev_info(dev,
+                                "Forcing ECRC on non-root port %s"
+                                " (enabling on root port %s)\n",
+                                pci_name(old_bridge), pci_name(bridge));
+               } else {
+                       dev_err(dev,
+                               "Not enabling ECRC on non-root port %s\n",
+                               pci_name(bridge));
+                       return;
+               }
+       }
+
+       cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
+       if (!cap)
+               return;
+
+       ret = pci_read_config_dword(bridge, cap + PCI_ERR_CAP, &err_cap);
+       if (ret) {
+               dev_err(dev, "failed reading ext-conf-space of %s\n",
+                       pci_name(bridge));
+               dev_err(dev, "\t pci=nommconf in use? "
+                       "or buggy/incomplete/absent ACPI MCFG attr?\n");
+               return;
+       }
+       if (!(err_cap & PCI_ERR_CAP_ECRC_GENC))
+               return;
+
+       err_cap |= PCI_ERR_CAP_ECRC_GENE;
+       pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap);
+       dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge));
+       mgp->tx.boundary = 4096;
+       mgp->fw_name = myri10ge_fw_aligned;
+}
+
+/*
+ * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput
+ * when the PCI-E Completion packets are aligned on an 8-byte
+ * boundary.  Some PCI-E chip sets always align Completion packets; on
+ * the ones that do not, the alignment can be enforced by enabling
+ * ECRC generation (if supported).
+ *
+ * When PCI-E Completion packets are not aligned, it is actually more
+ * efficient to limit Read-DMA transactions to 2KB, rather than 4KB.
+ *
+ * If the driver can neither enable ECRC nor verify that it has
+ * already been enabled, then it must use a firmware image which works
+ * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it
+ * should also ensure that it never gives the device a Read-DMA which is
+ * larger than 2KB by setting the tx.boundary to 2KB.  If ECRC is
+ * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat)
+ * firmware image, and set tx.boundary to 4KB.
+ */
+
+#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE  0x0132
+
+static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *bridge = mgp->pdev->bus->self;
+
+       mgp->tx.boundary = 2048;
+       mgp->fw_name = myri10ge_fw_unaligned;
+
+       if (myri10ge_force_firmware == 0) {
+               myri10ge_enable_ecrc(mgp);
+
+               /* Check to see if the upstream bridge is known to
+                * provide aligned completions */
+               if (bridge
+                   /* ServerWorks HT2000/HT1000 */
+                   && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
+                   && bridge->device ==
+                   PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) {
+                       dev_info(&mgp->pdev->dev,
+                                "Assuming aligned completions (0x%x:0x%x)\n",
+                                bridge->vendor, bridge->device);
+                       mgp->tx.boundary = 4096;
+                       mgp->fw_name = myri10ge_fw_aligned;
+               }
+       } else {
+               if (myri10ge_force_firmware == 1) {
+                       dev_info(&mgp->pdev->dev,
+                                "Assuming aligned completions (forced)\n");
+                       mgp->tx.boundary = 4096;
+                       mgp->fw_name = myri10ge_fw_aligned;
+               } else {
+                       dev_info(&mgp->pdev->dev,
+                                "Assuming unaligned completions (forced)\n");
+                       mgp->tx.boundary = 2048;
+                       mgp->fw_name = myri10ge_fw_unaligned;
+               }
+       }
+       if (myri10ge_fw_name != NULL) {
+               dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
+                        myri10ge_fw_name);
+               mgp->fw_name = myri10ge_fw_name;
+       }
+}
+
+static void myri10ge_save_state(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       int cap;
+
+       pci_save_state(pdev);
+       /* now save PCIe and MSI state that Linux will not
+        * save for us */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &mgp->devctl);
+       cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       pci_read_config_word(pdev, cap + PCI_MSI_FLAGS, &mgp->msi_flags);
+}
+
+static void myri10ge_restore_state(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       int cap;
+
+       /* restore PCIe and MSI state that linux will not */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pci_write_config_dword(pdev, cap + PCI_CAP_ID_EXP, mgp->devctl);
+       cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       pci_write_config_word(pdev, cap + PCI_MSI_FLAGS, mgp->msi_flags);
+
+       pci_restore_state(pdev);
+}
+
+#ifdef CONFIG_PM
+
+static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct myri10ge_priv *mgp;
+       struct net_device *netdev;
+
+       mgp = pci_get_drvdata(pdev);
+       if (mgp == NULL)
+               return -EINVAL;
+       netdev = mgp->dev;
+
+       netif_device_detach(netdev);
+       if (netif_running(netdev)) {
+               printk(KERN_INFO "myri10ge: closing %s\n", netdev->name);
+               rtnl_lock();
+               myri10ge_close(netdev);
+               rtnl_unlock();
+       }
+       myri10ge_dummy_rdma(mgp, 0);
+       free_irq(pdev->irq, mgp);
+       myri10ge_save_state(mgp);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return 0;
+}
+
+static int myri10ge_resume(struct pci_dev *pdev)
+{
+       struct myri10ge_priv *mgp;
+       struct net_device *netdev;
+       int status;
+       u16 vendor;
+
+       mgp = pci_get_drvdata(pdev);
+       if (mgp == NULL)
+               return -EINVAL;
+       netdev = mgp->dev;
+       pci_set_power_state(pdev, 0);   /* zeros conf space as a side effect */
+       msleep(5);              /* give card time to respond */
+       pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor);
+       if (vendor == 0xffff) {
+               printk(KERN_ERR "myri10ge: %s: device disappeared!\n",
+                      mgp->dev->name);
+               return -EIO;
+       }
+       myri10ge_restore_state(mgp);
+
+       status = pci_enable_device(pdev);
+       if (status < 0) {
+               dev_err(&pdev->dev, "failed to enable device\n");
+               return -EIO;
+       }
+
+       pci_set_master(pdev);
+
+       status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
+                            netdev->name, mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to allocate IRQ\n");
+               goto abort_with_enabled;
+       }
+
+       myri10ge_reset(mgp);
+       myri10ge_dummy_rdma(mgp, 1);
+
+       /* Save configuration space to be restored if the
+        * nic resets due to a parity error */
+       myri10ge_save_state(mgp);
+
+       if (netif_running(netdev)) {
+               rtnl_lock();
+               myri10ge_open(netdev);
+               rtnl_unlock();
+       }
+       netif_device_attach(netdev);
+
+       return 0;
+
+abort_with_enabled:
+       pci_disable_device(pdev);
+       return -EIO;
+
+}
+
+#endif                         /* CONFIG_PM */
+
+static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       int vs = mgp->vendor_specific_offset;
+       u32 reboot;
+
+       /*enter read32 mode */
+       pci_write_config_byte(pdev, vs + 0x10, 0x3);
+
+       /*read REBOOT_STATUS (0xfffffff0) */
+       pci_write_config_dword(pdev, vs + 0x18, 0xfffffff0);
+       pci_read_config_dword(pdev, vs + 0x14, &reboot);
+       return reboot;
+}
+
+/*
+ * This watchdog is used to check whether the board has suffered
+ * from a parity error and needs to be recovered.
+ */
+static void myri10ge_watchdog(void *arg)
+{
+       struct myri10ge_priv *mgp = arg;
+       u32 reboot;
+       int status;
+       u16 cmd, vendor;
+
+       mgp->watchdog_resets++;
+       pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+       if ((cmd & PCI_COMMAND_MASTER) == 0) {
+               /* Bus master DMA disabled?  Check to see
+                * if the card rebooted due to a parity error
+                * For now, just report it */
+               reboot = myri10ge_read_reboot(mgp);
+               printk(KERN_ERR
+                      "myri10ge: %s: NIC rebooted (0x%x), resetting\n",
+                      mgp->dev->name, reboot);
+               /*
+                * A rebooted nic will come back with config space as
+                * it was after power was applied to PCIe bus.
+                * Attempt to restore config space which was saved
+                * when the driver was loaded, or the last time the
+                * nic was resumed from power saving mode.
+                */
+               myri10ge_restore_state(mgp);
+       } else {
+               /* if we get back -1's from our slot, perhaps somebody
+                * powered off our card.  Don't try to reset it in
+                * this case */
+               if (cmd == 0xffff) {
+                       pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor);
+                       if (vendor == 0xffff) {
+                               printk(KERN_ERR
+                                      "myri10ge: %s: device disappeared!\n",
+                                      mgp->dev->name);
+                               return;
+                       }
+               }
+               /* Perhaps it is a software error.  Try to reset */
+
+               printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n",
+                      mgp->dev->name);
+               printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
+                      mgp->dev->name, mgp->tx.req, mgp->tx.done,
+                      mgp->tx.pkt_start, mgp->tx.pkt_done,
+                      (int)ntohl(mgp->fw_stats->send_done_count));
+               msleep(2000);
+               printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
+                      mgp->dev->name, mgp->tx.req, mgp->tx.done,
+                      mgp->tx.pkt_start, mgp->tx.pkt_done,
+                      (int)ntohl(mgp->fw_stats->send_done_count));
+       }
+       rtnl_lock();
+       myri10ge_close(mgp->dev);
+       status = myri10ge_load_firmware(mgp);
+       if (status != 0)
+               printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
+                      mgp->dev->name);
+       else
+               myri10ge_open(mgp->dev);
+       rtnl_unlock();
+}
+
+/*
+ * We use our own timer routine rather than relying upon
+ * netdev->tx_timeout because we have a very large hardware transmit
+ * queue.  Due to the large queue, the netdev->tx_timeout function
+ * cannot detect a NIC with a parity error in a timely fashion if the
+ * NIC is lightly loaded.
+ */
+static void myri10ge_watchdog_timer(unsigned long arg)
+{
+       struct myri10ge_priv *mgp;
+
+       mgp = (struct myri10ge_priv *)arg;
+       if (mgp->tx.req != mgp->tx.done &&
+           mgp->tx.done == mgp->watchdog_tx_done &&
+           mgp->watchdog_tx_req != mgp->watchdog_tx_done)
+               /* nic seems like it might be stuck.. */
+               schedule_work(&mgp->watchdog_work);
+       else
+               /* rearm timer */
+               mod_timer(&mgp->watchdog_timer,
+                         jiffies + myri10ge_watchdog_timeout * HZ);
+
+       mgp->watchdog_tx_done = mgp->tx.done;
+       mgp->watchdog_tx_req = mgp->tx.req;
+}
+
+static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct net_device *netdev;
+       struct myri10ge_priv *mgp;
+       struct device *dev = &pdev->dev;
+       size_t bytes;
+       int i;
+       int status = -ENXIO;
+       int cap;
+       int dac_enabled;
+       u16 val;
+
+       netdev = alloc_etherdev(sizeof(*mgp));
+       if (netdev == NULL) {
+               dev_err(dev, "Could not allocate ethernet device\n");
+               return -ENOMEM;
+       }
+
+       mgp = netdev_priv(netdev);
+       memset(mgp, 0, sizeof(*mgp));
+       mgp->dev = netdev;
+       mgp->pdev = pdev;
+       mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+       mgp->pause = myri10ge_flow_control;
+       mgp->intr_coal_delay = myri10ge_intr_coal_delay;
+       init_waitqueue_head(&mgp->down_wq);
+
+       if (pci_enable_device(pdev)) {
+               dev_err(&pdev->dev, "pci_enable_device call failed\n");
+               status = -ENODEV;
+               goto abort_with_netdev;
+       }
+       myri10ge_select_firmware(mgp);
+
+       /* Find the vendor-specific cap so we can check
+        * the reboot register later on */
+       mgp->vendor_specific_offset
+           = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
+
+       /* Set our max read request to 4KB */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (cap < 64) {
+               dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
+               goto abort_with_netdev;
+       }
+       status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
+       if (status != 0) {
+               dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n",
+                       status);
+               goto abort_with_netdev;
+       }
+       val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12);
+       status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val);
+       if (status != 0) {
+               dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
+                       status);
+               goto abort_with_netdev;
+       }
+
+       pci_set_master(pdev);
+       dac_enabled = 1;
+       status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+       if (status != 0) {
+               dac_enabled = 0;
+               dev_err(&pdev->dev,
+                       "64-bit pci address mask was refused, trying 32-bit");
+               status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       }
+       if (status != 0) {
+               dev_err(&pdev->dev, "Error %d setting DMA mask\n", status);
+               goto abort_with_netdev;
+       }
+       mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),
+                                     &mgp->cmd_bus, GFP_KERNEL);
+       if (mgp->cmd == NULL)
+               goto abort_with_netdev;
+
+       mgp->fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+                                          &mgp->fw_stats_bus, GFP_KERNEL);
+       if (mgp->fw_stats == NULL)
+               goto abort_with_cmd;
+
+       mgp->board_span = pci_resource_len(pdev, 0);
+       mgp->iomem_base = pci_resource_start(pdev, 0);
+       mgp->mtrr = -1;
+#ifdef CONFIG_MTRR
+       mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
+                            MTRR_TYPE_WRCOMB, 1);
+#endif
+       /* Hack.  need to get rid of these magic numbers */
+       mgp->sram_size =
+           2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100;
+       if (mgp->sram_size > mgp->board_span) {
+               dev_err(&pdev->dev, "board span %ld bytes too small\n",
+                       mgp->board_span);
+               goto abort_with_wc;
+       }
+       mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
+       if (mgp->sram == NULL) {
+               dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
+                       mgp->board_span, mgp->iomem_base);
+               status = -ENXIO;
+               goto abort_with_wc;
+       }
+       memcpy_fromio(mgp->eeprom_strings,
+                     mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
+                     MYRI10GE_EEPROM_STRINGS_SIZE);
+       memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2);
+       status = myri10ge_read_mac_addr(mgp);
+       if (status)
+               goto abort_with_ioremap;
+
+       for (i = 0; i < ETH_ALEN; i++)
+               netdev->dev_addr[i] = mgp->mac_addr[i];
+
+       /* allocate rx done ring */
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       mgp->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
+                                               &mgp->rx_done.bus, GFP_KERNEL);
+       if (mgp->rx_done.entry == NULL)
+               goto abort_with_ioremap;
+       memset(mgp->rx_done.entry, 0, bytes);
+
+       status = myri10ge_load_firmware(mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to load firmware\n");
+               goto abort_with_rx_done;
+       }
+
+       status = myri10ge_reset(mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed reset\n");
+               goto abort_with_firmware;
+       }
+
+       if (myri10ge_msi) {
+               status = pci_enable_msi(pdev);
+               if (status != 0)
+                       dev_err(&pdev->dev,
+                               "Error %d setting up MSI; falling back to xPIC\n",
+                               status);
+               else
+                       mgp->msi_enabled = 1;
+       }
+
+       status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED,
+                            netdev->name, mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to allocate IRQ\n");
+               goto abort_with_firmware;
+       }
+
+       pci_set_drvdata(pdev, mgp);
+       if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
+               myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+       if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
+               myri10ge_initial_mtu = 68;
+       netdev->mtu = myri10ge_initial_mtu;
+       netdev->open = myri10ge_open;
+       netdev->stop = myri10ge_close;
+       netdev->hard_start_xmit = myri10ge_xmit;
+       netdev->get_stats = myri10ge_get_stats;
+       netdev->base_addr = mgp->iomem_base;
+       netdev->irq = pdev->irq;
+       netdev->change_mtu = myri10ge_change_mtu;
+       netdev->set_multicast_list = myri10ge_set_multicast_list;
+       netdev->set_mac_address = myri10ge_set_mac_address;
+       netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
+       if (dac_enabled)
+               netdev->features |= NETIF_F_HIGHDMA;
+       netdev->poll = myri10ge_poll;
+       netdev->weight = myri10ge_napi_weight;
+
+       /* Save configuration space to be restored if the
+        * nic resets due to a parity error */
+       myri10ge_save_state(mgp);
+
+       /* Setup the watchdog timer */
+       setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
+                   (unsigned long)mgp);
+
+       SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
+       INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp);
+       status = register_netdev(netdev);
+       if (status != 0) {
+               dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
+               goto abort_with_irq;
+       }
+       dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
+                (mgp->msi_enabled ? "MSI" : "xPIC"),
+                pdev->irq, mgp->tx.boundary, mgp->fw_name,
+                (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
+
+       return 0;
+
+abort_with_irq:
+       free_irq(pdev->irq, mgp);
+       if (mgp->msi_enabled)
+               pci_disable_msi(pdev);
+
+abort_with_firmware:
+       myri10ge_dummy_rdma(mgp, 0);
+
+abort_with_rx_done:
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       dma_free_coherent(&pdev->dev, bytes,
+                         mgp->rx_done.entry, mgp->rx_done.bus);
+
+abort_with_ioremap:
+       iounmap(mgp->sram);
+
+abort_with_wc:
+#ifdef CONFIG_MTRR
+       if (mgp->mtrr >= 0)
+               mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
+#endif
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+                         mgp->fw_stats, mgp->fw_stats_bus);
+
+abort_with_cmd:
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
+                         mgp->cmd, mgp->cmd_bus);
+
+abort_with_netdev:
+
+       free_netdev(netdev);
+       return status;
+}
+
+/*
+ * myri10ge_remove
+ *
+ * Does what is necessary to shutdown one Myrinet device. Called
+ *   once for each Myrinet card by the kernel when a module is
+ *   unloaded.
+ */
+static void myri10ge_remove(struct pci_dev *pdev)
+{
+       struct myri10ge_priv *mgp;
+       struct net_device *netdev;
+       size_t bytes;
+
+       mgp = pci_get_drvdata(pdev);
+       if (mgp == NULL)
+               return;
+
+       flush_scheduled_work();
+       netdev = mgp->dev;
+       unregister_netdev(netdev);
+       free_irq(pdev->irq, mgp);
+       if (mgp->msi_enabled)
+               pci_disable_msi(pdev);
+
+       myri10ge_dummy_rdma(mgp, 0);
+
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       dma_free_coherent(&pdev->dev, bytes,
+                         mgp->rx_done.entry, mgp->rx_done.bus);
+
+       iounmap(mgp->sram);
+
+#ifdef CONFIG_MTRR
+       if (mgp->mtrr >= 0)
+               mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
+#endif
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+                         mgp->fw_stats, mgp->fw_stats_bus);
+
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
+                         mgp->cmd, mgp->cmd_bus);
+
+       free_netdev(netdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E     0x0008
+
+static struct pci_device_id myri10ge_pci_tbl[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)},
+       {0},
+};
+
+static struct pci_driver myri10ge_driver = {
+       .name = "myri10ge",
+       .probe = myri10ge_probe,
+       .remove = myri10ge_remove,
+       .id_table = myri10ge_pci_tbl,
+#ifdef CONFIG_PM
+       .suspend = myri10ge_suspend,
+       .resume = myri10ge_resume,
+#endif
+};
+
+static __init int myri10ge_init_module(void)
+{
+       printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
+              MYRI10GE_VERSION_STR);
+       return pci_register_driver(&myri10ge_driver);
+}
+
+module_init(myri10ge_init_module);
+
+static __exit void myri10ge_cleanup_module(void)
+{
+       pci_unregister_driver(&myri10ge_driver);
+}
+
+module_exit(myri10ge_cleanup_module);
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h
new file mode 100644 (file)
index 0000000..0a6cae6
--- /dev/null
@@ -0,0 +1,205 @@
+#ifndef __MYRI10GE_MCP_H__
+#define __MYRI10GE_MCP_H__
+
+#define MXGEFW_VERSION_MAJOR   1
+#define MXGEFW_VERSION_MINOR   4
+
+/* 8 Bytes */
+struct mcp_dma_addr {
+       u32 high;
+       u32 low;
+};
+
+/* 4 Bytes */
+struct mcp_slot {
+       u16 checksum;
+       u16 length;
+};
+
+/* 64 Bytes */
+struct mcp_cmd {
+       u32 cmd;
+       u32 data0;              /* will be low portion if data > 32 bits */
+       /* 8 */
+       u32 data1;              /* will be high portion if data > 32 bits */
+       u32 data2;              /* currently unused.. */
+       /* 16 */
+       struct mcp_dma_addr response_addr;
+       /* 24 */
+       u8 pad[40];
+};
+
+/* 8 Bytes */
+struct mcp_cmd_response {
+       u32 data;
+       u32 result;
+};
+
+/*
+ * flags used in mcp_kreq_ether_send_t:
+ *
+ * The SMALL flag is only needed in the first segment. It is raised
+ * for packets that are total less or equal 512 bytes.
+ *
+ * The CKSUM flag must be set in all segments.
+ *
+ * The PADDED flags is set if the packet needs to be padded, and it
+ * must be set for all segments.
+ *
+ * The  MXGEFW_FLAGS_ALIGN_ODD must be set if the cumulative
+ * length of all previous segments was odd.
+ */
+
+#define MXGEFW_FLAGS_SMALL      0x1
+#define MXGEFW_FLAGS_TSO_HDR    0x1
+#define MXGEFW_FLAGS_FIRST      0x2
+#define MXGEFW_FLAGS_ALIGN_ODD  0x4
+#define MXGEFW_FLAGS_CKSUM      0x8
+#define MXGEFW_FLAGS_TSO_LAST   0x8
+#define MXGEFW_FLAGS_NO_TSO     0x10
+#define MXGEFW_FLAGS_TSO_CHOP   0x10
+#define MXGEFW_FLAGS_TSO_PLD    0x20
+
+#define MXGEFW_SEND_SMALL_SIZE  1520
+#define MXGEFW_MAX_MTU          9400
+
+union mcp_pso_or_cumlen {
+       u16 pseudo_hdr_offset;
+       u16 cum_len;
+};
+
+#define        MXGEFW_MAX_SEND_DESC 12
+#define MXGEFW_PAD         2
+
+/* 16 Bytes */
+struct mcp_kreq_ether_send {
+       u32 addr_high;
+       u32 addr_low;
+       u16 pseudo_hdr_offset;
+       u16 length;
+       u8 pad;
+       u8 rdma_count;
+       u8 cksum_offset;        /* where to start computing cksum */
+       u8 flags;               /* as defined above */
+};
+
+/* 8 Bytes */
+struct mcp_kreq_ether_recv {
+       u32 addr_high;
+       u32 addr_low;
+};
+
+/* Commands */
+
+#define MXGEFW_CMD_OFFSET 0xf80000
+
+enum myri10ge_mcp_cmd_type {
+       MXGEFW_CMD_NONE = 0,
+       /* Reset the mcp, it is left in a safe state, waiting
+        * for the driver to set all its parameters */
+       MXGEFW_CMD_RESET,
+
+       /* get the version number of the current firmware..
+        * (may be available in the eeprom strings..? */
+       MXGEFW_GET_MCP_VERSION,
+
+       /* Parameters which must be set by the driver before it can
+        * issue MXGEFW_CMD_ETHERNET_UP. They persist until the next
+        * MXGEFW_CMD_RESET is issued */
+
+       MXGEFW_CMD_SET_INTRQ_DMA,
+       MXGEFW_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */
+       MXGEFW_CMD_SET_SMALL_BUFFER_SIZE,       /* in bytes */
+
+       /* Parameters which refer to lanai SRAM addresses where the
+        * driver must issue PIO writes for various things */
+
+       MXGEFW_CMD_GET_SEND_OFFSET,
+       MXGEFW_CMD_GET_SMALL_RX_OFFSET,
+       MXGEFW_CMD_GET_BIG_RX_OFFSET,
+       MXGEFW_CMD_GET_IRQ_ACK_OFFSET,
+       MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
+
+       /* Parameters which refer to rings stored on the MCP,
+        * and whose size is controlled by the mcp */
+
+       MXGEFW_CMD_GET_SEND_RING_SIZE,  /* in bytes */
+       MXGEFW_CMD_GET_RX_RING_SIZE,    /* in bytes */
+
+       /* Parameters which refer to rings stored in the host,
+        * and whose size is controlled by the host.  Note that
+        * all must be physically contiguous and must contain
+        * a power of 2 number of entries.  */
+
+       MXGEFW_CMD_SET_INTRQ_SIZE,      /* in bytes */
+
+       /* command to bring ethernet interface up.  Above parameters
+        * (plus mtu & mac address) must have been exchanged prior
+        * to issuing this command  */
+       MXGEFW_CMD_ETHERNET_UP,
+
+       /* command to bring ethernet interface down.  No further sends
+        * or receives may be processed until an MXGEFW_CMD_ETHERNET_UP
+        * is issued, and all interrupt queues must be flushed prior
+        * to ack'ing this command */
+
+       MXGEFW_CMD_ETHERNET_DOWN,
+
+       /* commands the driver may issue live, without resetting
+        * the nic.  Note that increasing the mtu "live" should
+        * only be done if the driver has already supplied buffers
+        * sufficiently large to handle the new mtu.  Decreasing
+        * the mtu live is safe */
+
+       MXGEFW_CMD_SET_MTU,
+       MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET,  /* in microseconds */
+       MXGEFW_CMD_SET_STATS_INTERVAL,  /* in microseconds */
+       MXGEFW_CMD_SET_STATS_DMA,
+
+       MXGEFW_ENABLE_PROMISC,
+       MXGEFW_DISABLE_PROMISC,
+       MXGEFW_SET_MAC_ADDRESS,
+
+       MXGEFW_ENABLE_FLOW_CONTROL,
+       MXGEFW_DISABLE_FLOW_CONTROL,
+
+       /* do a DMA test
+        * data0,data1 = DMA address
+        * data2       = RDMA length (MSH), WDMA length (LSH)
+        * command return data = repetitions (MSH), 0.5-ms ticks (LSH)
+        */
+       MXGEFW_DMA_TEST
+};
+
+enum myri10ge_mcp_cmd_status {
+       MXGEFW_CMD_OK = 0,
+       MXGEFW_CMD_UNKNOWN,
+       MXGEFW_CMD_ERROR_RANGE,
+       MXGEFW_CMD_ERROR_BUSY,
+       MXGEFW_CMD_ERROR_EMPTY,
+       MXGEFW_CMD_ERROR_CLOSED,
+       MXGEFW_CMD_ERROR_HASH_ERROR,
+       MXGEFW_CMD_ERROR_BAD_PORT,
+       MXGEFW_CMD_ERROR_RESOURCES
+};
+
+/* 40 Bytes */
+struct mcp_irq_data {
+       u32 send_done_count;
+
+       u32 link_up;
+       u32 dropped_link_overflow;
+       u32 dropped_link_error_or_filtered;
+       u32 dropped_runt;
+       u32 dropped_overrun;
+       u32 dropped_no_small_buffer;
+       u32 dropped_no_big_buffer;
+       u32 rdma_tags_available;
+
+       u8 tx_stopped;
+       u8 link_down;
+       u8 stats_updated;
+       u8 valid;
+};
+
+#endif                         /* __MYRI10GE_MCP_H__ */
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
new file mode 100644 (file)
index 0000000..487f779
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __MYRI10GE_MCP_GEN_HEADER_H__
+#define __MYRI10GE_MCP_GEN_HEADER_H__
+
+/* this file define a standard header used as a first entry point to
+ * exchange information between firmware/driver and driver.  The
+ * header structure can be anywhere in the mcp. It will usually be in
+ * the .data section, because some fields needs to be initialized at
+ * compile time.
+ * The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must
+ * contains the location of the header.
+ *
+ * Typically a MCP will start with the following:
+ * .text
+ * .space 52    ! to help catch MEMORY_INT errors
+ * bt start     ! jump to real code
+ * nop
+ * .long _gen_mcp_header
+ *
+ * The source will have a definition like:
+ *
+ * mcp_gen_header_t gen_mcp_header = {
+ * .header_length = sizeof(mcp_gen_header_t),
+ * .mcp_type = MCP_TYPE_XXX,
+ * .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $",
+ * .mcp_globals = (unsigned)&Globals
+ * };
+ */
+
+#define MCP_HEADER_PTR_OFFSET  0x3c
+
+#define MCP_TYPE_MX 0x4d582020 /* "MX  " */
+#define MCP_TYPE_PCIE 0x70636965       /* "PCIE" pcie-only MCP */
+#define MCP_TYPE_ETH 0x45544820        /* "ETH " */
+#define MCP_TYPE_MCP0 0x4d435030       /* "MCP0" */
+
+struct mcp_gen_header {
+       /* the first 4 fields are filled at compile time */
+       unsigned header_length;
+       unsigned mcp_type;
+       char version[128];
+       unsigned mcp_globals;   /* pointer to mcp-type specific structure */
+
+       /* filled by the MCP at run-time */
+       unsigned sram_size;
+       unsigned string_specs;  /* either the original STRING_SPECS or a superset */
+       unsigned string_specs_len;
+
+       /* Fields above this comment are guaranteed to be present.
+        *
+        * Fields below this comment are extensions added in later versions
+        * of this struct, drivers should compare the header_length against
+        * offsetof(field) to check wether a given MCP implements them.
+        *
+        * Never remove any field.  Keep everything naturally align.
+        */
+};
+
+#endif                         /* __MYRI10GE_MCP_GEN_HEADER_H__ */
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
new file mode 100644 (file)
index 0000000..30ed9a5
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * drivers/net/netx-eth.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/mii.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/pfifo.h>
+#include <asm/arch/xc.h>
+#include <asm/arch/eth.h>
+
+/* XC Fifo Offsets */
+#define EMPTY_PTR_FIFO(xcno)    (0 + ((xcno) << 3))    /* Index of the empty pointer FIFO */
+#define IND_FIFO_PORT_HI(xcno)  (1 + ((xcno) << 3))    /* Index of the FIFO where received */
+                                                       /* Data packages are indicated by XC */
+#define IND_FIFO_PORT_LO(xcno)  (2 + ((xcno) << 3))    /* Index of the FIFO where received */
+                                                       /* Data packages are indicated by XC */
+#define REQ_FIFO_PORT_HI(xcno)  (3 + ((xcno) << 3))    /* Index of the FIFO where Data packages */
+                                                       /* have to be indicated by ARM which */
+                                                       /* shall be sent */
+#define REQ_FIFO_PORT_LO(xcno)  (4 + ((xcno) << 3))    /* Index of the FIFO where Data packages */
+                                                       /* have to be indicated by ARM which shall */
+                                                       /* be sent */
+#define CON_FIFO_PORT_HI(xcno)  (5 + ((xcno) << 3))    /* Index of the FIFO where sent Data packages */
+                                                       /* are confirmed */
+#define CON_FIFO_PORT_LO(xcno)  (6 + ((xcno) << 3))    /* Index of the FIFO where sent Data */
+                                                       /* packages are confirmed */
+#define PFIFO_MASK(xcno)        (0x7f << (xcno*8))
+
+#define FIFO_PTR_FRAMELEN_SHIFT 0
+#define FIFO_PTR_FRAMELEN_MASK  (0x7ff << 0)
+#define FIFO_PTR_FRAMELEN(len)  (((len) << 0) & FIFO_PTR_FRAMELEN_MASK)
+#define FIFO_PTR_TIMETRIG       (1<<11)
+#define FIFO_PTR_MULTI_REQ
+#define FIFO_PTR_ORIGIN         (1<<14)
+#define FIFO_PTR_VLAN           (1<<15)
+#define FIFO_PTR_FRAMENO_SHIFT  16
+#define FIFO_PTR_FRAMENO_MASK   (0x3f << 16)
+#define FIFO_PTR_FRAMENO(no)    (((no) << 16) & FIFO_PTR_FRAMENO_MASK)
+#define FIFO_PTR_SEGMENT_SHIFT  22
+#define FIFO_PTR_SEGMENT_MASK   (0xf << 22)
+#define FIFO_PTR_SEGMENT(seg)   (((seg) & 0xf) << 22)
+#define FIFO_PTR_ERROR_SHIFT    28
+#define FIFO_PTR_ERROR_MASK     (0xf << 28)
+
+#define ISR_LINK_STATUS_CHANGE (1<<4)
+#define ISR_IND_LO             (1<<3)
+#define ISR_CON_LO             (1<<2)
+#define ISR_IND_HI             (1<<1)
+#define ISR_CON_HI             (1<<0)
+
+#define ETH_MAC_LOCAL_CONFIG 0x1560
+#define ETH_MAC_4321         0x1564
+#define ETH_MAC_65           0x1568
+
+#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16
+#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT)
+#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK)
+#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24)
+#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23)
+#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22)
+#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21)
+#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20)
+
+#define CARDNAME "netx-eth"
+
+/* LSB must be zero */
+#define INTERNAL_PHY_ADR 0x1c
+
+struct netx_eth_priv {
+       void                    __iomem *sram_base, *xpec_base, *xmac_base;
+       int                     id;
+       struct net_device_stats stats;
+       struct mii_if_info      mii;
+       u32                     msg_enable;
+       struct xc               *xc;
+       spinlock_t              lock;
+};
+
+static void netx_eth_set_multicast_list(struct net_device *ndev)
+{
+       /* implement me */
+}
+
+static int
+netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+       unsigned char *buf = skb->data;
+       unsigned int len = skb->len;
+
+       spin_lock_irq(&priv->lock);
+       memcpy_toio(priv->sram_base + 1560, (void *)buf, len);
+       if (len < 60) {
+               memset_io(priv->sram_base + 1560 + len, 0, 60 - len);
+               len = 60;
+       }
+
+       pfifo_push(REQ_FIFO_PORT_LO(priv->id),
+                  FIFO_PTR_SEGMENT(priv->id) |
+                  FIFO_PTR_FRAMENO(1) |
+                  FIFO_PTR_FRAMELEN(len));
+
+       ndev->trans_start = jiffies;
+       priv->stats.tx_packets++;
+       priv->stats.tx_bytes += skb->len;
+
+       netif_stop_queue(ndev);
+       spin_unlock_irq(&priv->lock);
+       dev_kfree_skb(skb);
+
+       return 0;
+}
+
+static void netx_eth_receive(struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+       unsigned int val, frameno, seg, len;
+       unsigned char *data;
+       struct sk_buff *skb;
+
+       val = pfifo_pop(IND_FIFO_PORT_LO(priv->id));
+
+       frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT;
+       seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT;
+       len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT;
+
+       skb = dev_alloc_skb(len);
+       if (unlikely(skb == NULL)) {
+               printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
+                       ndev->name);
+               priv->stats.rx_dropped++;
+               return;
+       }
+
+       data = skb_put(skb, len);
+
+       memcpy_fromio(data, priv->sram_base + frameno * 1560, len);
+
+       pfifo_push(EMPTY_PTR_FIFO(priv->id),
+               FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno));
+
+       ndev->last_rx = jiffies;
+       skb->dev = ndev;
+       skb->protocol = eth_type_trans(skb, ndev);
+       netif_rx(skb);
+       priv->stats.rx_packets++;
+       priv->stats.rx_bytes += len;
+}
+
+static irqreturn_t
+netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *ndev = dev_id;
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+       int status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
+       while (status) {
+               int fill_level;
+               writel(status, NETX_PFIFO_XPEC_ISR(priv->id));
+
+               if ((status & ISR_CON_HI) || (status & ISR_IND_HI))
+                       printk("%s: unexpected status: 0x%08x\n",
+                           __FUNCTION__, status);
+
+               fill_level =
+                   readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id)));
+               while (fill_level--)
+                       netx_eth_receive(ndev);
+
+               if (status & ISR_CON_LO)
+                       netif_wake_queue(ndev);
+
+               if (status & ISR_LINK_STATUS_CHANGE)
+                       mii_check_media(&priv->mii, netif_msg_link(priv), 1);
+
+               status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static struct net_device_stats *netx_eth_query_statistics(struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+       return &priv->stats;
+}
+
+static int netx_eth_open(struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+
+       if (request_irq
+           (ndev->irq, &netx_eth_interrupt, IRQF_SHARED, ndev->name, ndev))
+               return -EAGAIN;
+
+       writel(ndev->dev_addr[0] |
+              ndev->dev_addr[1]<<8 |
+              ndev->dev_addr[2]<<16 |
+              ndev->dev_addr[3]<<24,
+              priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
+       writel(ndev->dev_addr[4] |
+              ndev->dev_addr[5]<<8,
+              priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
+
+       writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN |
+               LOCAL_CONFIG_CON_LO_IRQ_EN |
+               LOCAL_CONFIG_CON_HI_IRQ_EN |
+               LOCAL_CONFIG_IND_LO_IRQ_EN |
+               LOCAL_CONFIG_IND_HI_IRQ_EN,
+               priv->xpec_base + NETX_XPEC_RAM_START_OFS +
+               ETH_MAC_LOCAL_CONFIG);
+
+       mii_check_media(&priv->mii, netif_msg_link(priv), 1);
+       netif_start_queue(ndev);
+
+       return 0;
+}
+
+static int netx_eth_close(struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+
+       netif_stop_queue(ndev);
+
+       writel(0,
+           priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG);
+
+       free_irq(ndev->irq, ndev);
+
+       return 0;
+}
+
+static void netx_eth_timeout(struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+       int i;
+
+       printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name);
+
+       spin_lock_irq(&priv->lock);
+
+       xc_reset(priv->xc);
+       xc_start(priv->xc);
+
+       for (i=2; i<=18; i++)
+               pfifo_push(EMPTY_PTR_FIFO(priv->id),
+                       FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
+
+       spin_unlock_irq(&priv->lock);
+
+       netif_wake_queue(ndev);
+}
+
+static int
+netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg)
+{
+       unsigned int val;
+
+       val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
+             MIIMU_REGADDR(reg) | MIIMU_PHY_NRES;
+
+       writel(val, NETX_MIIMU);
+       while (readl(NETX_MIIMU) & MIIMU_SNRDY);
+
+       return readl(NETX_MIIMU) >> 16;
+
+}
+
+static void
+netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value)
+{
+       unsigned int val;
+
+       val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
+             MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE |
+             MIIMU_DATA(value);
+
+       writel(val, NETX_MIIMU);
+       while (readl(NETX_MIIMU) & MIIMU_SNRDY);
+}
+
+static int netx_eth_enable(struct net_device *ndev)
+{
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+       unsigned int mac4321, mac65;
+       int running, i;
+
+       ether_setup(ndev);
+
+       ndev->open = netx_eth_open;
+       ndev->stop = netx_eth_close;
+       ndev->hard_start_xmit = netx_eth_hard_start_xmit;
+       ndev->tx_timeout = netx_eth_timeout;
+       ndev->watchdog_timeo = msecs_to_jiffies(5000);
+       ndev->get_stats = netx_eth_query_statistics;
+       ndev->set_multicast_list = netx_eth_set_multicast_list;
+
+       priv->msg_enable       = NETIF_MSG_LINK;
+       priv->mii.phy_id_mask  = 0x1f;
+       priv->mii.reg_num_mask = 0x1f;
+       priv->mii.force_media  = 0;
+       priv->mii.full_duplex  = 0;
+       priv->mii.dev        = ndev;
+       priv->mii.mdio_read    = netx_eth_phy_read;
+       priv->mii.mdio_write   = netx_eth_phy_write;
+       priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id;
+
+       running = xc_running(priv->xc);
+       xc_stop(priv->xc);
+
+       /* if the xc engine is already running, assume the bootloader has
+        * loaded the firmware for us
+        */
+       if (running) {
+               /* get Node Address from hardware */
+               mac4321 = readl(priv->xpec_base +
+                       NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
+               mac65 = readl(priv->xpec_base +
+                       NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
+
+               ndev->dev_addr[0] = mac4321 & 0xff;
+               ndev->dev_addr[1] = (mac4321 >> 8) & 0xff;
+               ndev->dev_addr[2] = (mac4321 >> 16) & 0xff;
+               ndev->dev_addr[3] = (mac4321 >> 24) & 0xff;
+               ndev->dev_addr[4] = mac65 & 0xff;
+               ndev->dev_addr[5] = (mac65 >> 8) & 0xff;
+       } else {
+               if (xc_request_firmware(priv->xc)) {
+                       printk(CARDNAME ": requesting firmware failed\n");
+                       return -ENODEV;
+               }
+       }
+
+       xc_reset(priv->xc);
+       xc_start(priv->xc);
+
+       if (!is_valid_ether_addr(ndev->dev_addr))
+               printk("%s: Invalid ethernet MAC address.  Please "
+                      "set using ifconfig\n", ndev->name);
+
+       for (i=2; i<=18; i++)
+               pfifo_push(EMPTY_PTR_FIFO(priv->id),
+                       FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
+
+       return register_netdev(ndev);
+
+}
+
+static int netx_eth_drv_probe(struct platform_device *pdev)
+{
+       struct netx_eth_priv *priv;
+       struct net_device *ndev;
+       struct netxeth_platform_data *pdata;
+       int ret;
+
+       ndev = alloc_etherdev(sizeof (struct netx_eth_priv));
+       if (!ndev) {
+               printk("%s: could not allocate device.\n", CARDNAME);
+               ret = -ENOMEM;
+               goto exit;
+       }
+       SET_MODULE_OWNER(ndev);
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       platform_set_drvdata(pdev, ndev);
+
+       priv = netdev_priv(ndev);
+
+       pdata = (struct netxeth_platform_data *)pdev->dev.platform_data;
+       priv->xc = request_xc(pdata->xcno, &pdev->dev);
+       if (!priv->xc) {
+               dev_err(&pdev->dev, "unable to request xc engine\n");
+               ret = -ENODEV;
+               goto exit_free_netdev;
+       }
+
+       ndev->irq = priv->xc->irq;
+       priv->id = pdev->id;
+       priv->xpec_base = priv->xc->xpec_base;
+       priv->xmac_base = priv->xc->xmac_base;
+       priv->sram_base = priv->xc->sram_base;
+
+       ret = pfifo_request(PFIFO_MASK(priv->id));
+       if (ret) {
+               printk("unable to request PFIFO\n");
+               goto exit_free_xc;
+       }
+
+       ret = netx_eth_enable(ndev);
+       if (ret)
+               goto exit_free_pfifo;
+
+       return 0;
+exit_free_pfifo:
+       pfifo_free(PFIFO_MASK(priv->id));
+exit_free_xc:
+       free_xc(priv->xc);
+exit_free_netdev:
+       platform_set_drvdata(pdev, NULL);
+       free_netdev(ndev);
+exit:
+       return ret;
+}
+
+static int netx_eth_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *ndev = dev_get_drvdata(&pdev->dev);
+       struct netx_eth_priv *priv = netdev_priv(ndev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       unregister_netdev(ndev);
+       xc_stop(priv->xc);
+       free_xc(priv->xc);
+       free_netdev(ndev);
+       pfifo_free(PFIFO_MASK(priv->id));
+
+       return 0;
+}
+
+static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       dev_err(&pdev->dev, "suspend not implemented\n");
+       return 0;
+}
+
+static int netx_eth_drv_resume(struct platform_device *pdev)
+{
+       dev_err(&pdev->dev, "resume not implemented\n");
+       return 0;
+}
+
+static struct platform_driver netx_eth_driver = {
+       .probe          = netx_eth_drv_probe,
+       .remove         = netx_eth_drv_remove,
+       .suspend        = netx_eth_drv_suspend,
+       .resume         = netx_eth_drv_resume,
+       .driver         = {
+               .name   = CARDNAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init netx_eth_init(void)
+{
+       unsigned int phy_control, val;
+
+       printk("NetX Ethernet driver\n");
+
+       phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) |
+                     PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) |
+                     PHY_CONTROL_PHY1_AUTOMDIX |
+                     PHY_CONTROL_PHY1_EN |
+                     PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) |
+                     PHY_CONTROL_PHY0_AUTOMDIX |
+                     PHY_CONTROL_PHY0_EN |
+                     PHY_CONTROL_CLK_XLATIN;
+
+       val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+       writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+       writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL);
+       udelay(100);
+
+       val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+       writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+       writel(phy_control, NETX_SYSTEM_PHY_CONTROL);
+
+       return platform_driver_register(&netx_eth_driver);
+}
+
+static void __exit netx_eth_cleanup(void)
+{
+       platform_driver_unregister(&netx_eth_driver);
+}
+
+module_init(netx_eth_init);
+module_exit(netx_eth_cleanup);
+
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
new file mode 100644 (file)
index 0000000..7e3364f
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * drivers/net/phy/fixed.c
+ *
+ * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
+ *
+ * Author: Vitaly Bordug
+ *
+ * Copyright (c) 2006 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_REGS_NUM   7
+
+/*
+    The idea is to emulate normal phy behavior by responding with
+    pre-defined values to mii BMCR read, so that read_status hook could
+    take all the needed info.
+*/
+
+struct fixed_phy_status {
+       u8      link;
+       u16     speed;
+       u8      duplex;
+};
+
+/*-----------------------------------------------------------------------------
+ *  Private information hoder for mii_bus
+ *-----------------------------------------------------------------------------*/
+struct fixed_info {
+       u16 *regs;
+       u8 regs_num;
+       struct fixed_phy_status phy_status;
+       struct phy_device *phydev; /* pointer to the container */
+       /* link & speed cb */
+       int(*link_update)(struct net_device*, struct fixed_phy_status*);
+
+};
+
+/*-----------------------------------------------------------------------------
+ *  If something weird is required to be done with link/speed,
+ * network driver is able to assign a function to implement this.
+ * May be useful for PHY's that need to be software-driven.
+ *-----------------------------------------------------------------------------*/
+int fixed_mdio_set_link_update(struct phy_device* phydev,
+               int(*link_update)(struct net_device*, struct fixed_phy_status*))
+{
+       struct fixed_info *fixed;
+
+       if(link_update == NULL)
+               return -EINVAL;
+
+       if(phydev) {
+               if(phydev->bus) {
+                       fixed = phydev->bus->priv;
+                       fixed->link_update = link_update;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(fixed_mdio_set_link_update);
+
+/*-----------------------------------------------------------------------------
+ *  This is used for updating internal mii regs from the status
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_update_regs(struct fixed_info *fixed)
+{
+       u16 *regs = fixed->regs;
+       u16 bmsr = 0;
+       u16 bmcr = 0;
+
+       if(!regs) {
+               printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       if(fixed->phy_status.link)
+               bmsr |= BMSR_LSTATUS;
+
+       if(fixed->phy_status.duplex) {
+               bmcr |= BMCR_FULLDPLX;
+
+               switch ( fixed->phy_status.speed ) {
+               case 100:
+                       bmsr |= BMSR_100FULL;
+                       bmcr |= BMCR_SPEED100;
+               break;
+
+               case 10:
+                       bmsr |= BMSR_10FULL;
+               break;
+               }
+       } else {
+               switch ( fixed->phy_status.speed ) {
+               case 100:
+                       bmsr |= BMSR_100HALF;
+                       bmcr |= BMCR_SPEED100;
+               break;
+
+               case 10:
+                       bmsr |= BMSR_100HALF;
+               break;
+               }
+       }
+
+       regs[MII_BMCR] =  bmcr;
+       regs[MII_BMSR] =  bmsr | 0x800; /*we are always capable of 10 hdx*/
+
+       return 0;
+}
+
+static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
+{
+       struct fixed_info *fixed = bus->priv;
+
+       /* if user has registered link update callback, use it */
+       if(fixed->phydev)
+               if(fixed->phydev->attached_dev) {
+                       if(fixed->link_update) {
+                               fixed->link_update(fixed->phydev->attached_dev,
+                                               &fixed->phy_status);
+                               fixed_mdio_update_regs(fixed);
+                       }
+       }
+
+       if ((unsigned int)location >= fixed->regs_num)
+               return -1;
+       return fixed->regs[location];
+}
+
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+       /* do nothing for now*/
+       return 0;
+}
+
+static int fixed_mii_reset(struct mii_bus *bus)
+{
+       /*nothing here - no way/need to reset it*/
+       return 0;
+}
+
+static int fixed_config_aneg(struct phy_device *phydev)
+{
+       /* :TODO:03/13/2006 09:45:37 PM::
+        The full autoneg funcionality can be emulated,
+        but no need to have anything here for now
+        */
+       return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * the manual bind will do the magic - with phy_id_mask == 0
+ * match will never return true...
+ *-----------------------------------------------------------------------------*/
+static struct phy_driver fixed_mdio_driver = {
+       .name           = "Fixed PHY",
+       .features       = PHY_BASIC_FEATURES,
+       .config_aneg    = fixed_config_aneg,
+       .read_status    = genphy_read_status,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+/*-----------------------------------------------------------------------------
+ *  This func is used to create all the necessary stuff, bind
+ * the fixed phy driver and register all it on the mdio_bus_type.
+ * speed is either 10 or 100, duplex is boolean.
+ * number is used to create multiple fixed PHYs, so that several devices can
+ * utilize them simultaneously.
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_register_device(int number, int speed, int duplex)
+{
+       struct mii_bus *new_bus;
+       struct fixed_info *fixed;
+       struct phy_device *phydev;
+       int err = 0;
+
+       struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+
+       if (NULL == dev)
+               return -ENOMEM;
+
+       new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+       if (NULL == new_bus) {
+               kfree(dev);
+               return -ENOMEM;
+       }
+       fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
+
+       if (NULL == fixed) {
+               kfree(dev);
+               kfree(new_bus);
+               return -ENOMEM;
+       }
+
+       fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
+       fixed->regs_num = MII_REGS_NUM;
+       fixed->phy_status.speed = speed;
+       fixed->phy_status.duplex = duplex;
+       fixed->phy_status.link = 1;
+
+       new_bus->name = "Fixed MII Bus",
+       new_bus->read = &fixed_mii_read,
+       new_bus->write = &fixed_mii_write,
+       new_bus->reset = &fixed_mii_reset,
+
+       /*set up workspace*/
+       fixed_mdio_update_regs(fixed);
+       new_bus->priv = fixed;
+
+       new_bus->dev = dev;
+       dev_set_drvdata(dev, new_bus);
+
+       /* create phy_device and register it on the mdio bus */
+       phydev = phy_device_create(new_bus, 0, 0);
+
+       /*
+        Put the phydev pointer into the fixed pack so that bus read/write code could
+        be able to access for instance attached netdev. Well it doesn't have to do
+        so, only in case of utilizing user-specified link-update...
+        */
+       fixed->phydev = phydev;
+
+       if(NULL == phydev) {
+               err = -ENOMEM;
+               goto device_create_fail;
+       }
+
+       phydev->irq = -1;
+       phydev->dev.bus = &mdio_bus_type;
+
+       if(number)
+               snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+                               "fixed_%d@%d:%d", number, speed, duplex);
+       else
+               snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+                               "fixed@%d:%d", speed, duplex);
+       phydev->bus = new_bus;
+
+       err = device_register(&phydev->dev);
+       if(err) {
+               printk(KERN_ERR "Phy %s failed to register\n",
+                               phydev->dev.bus_id);
+               goto bus_register_fail;
+       }
+
+       /*
+          the mdio bus has phy_id match... In order not to do it
+          artificially, we are binding the driver here by hand;
+          it will be the same for all the fixed phys anyway.
+        */
+       down_write(&phydev->dev.bus->subsys.rwsem);
+
+       phydev->dev.driver = &fixed_mdio_driver.driver;
+
+       err = phydev->dev.driver->probe(&phydev->dev);
+       if(err < 0) {
+               printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
+               up_write(&phydev->dev.bus->subsys.rwsem);
+               goto probe_fail;
+       }
+
+       device_bind_driver(&phydev->dev);
+       up_write(&phydev->dev.bus->subsys.rwsem);
+
+       return 0;
+
+probe_fail:
+       device_unregister(&phydev->dev);
+bus_register_fail:
+       kfree(phydev);
+device_create_fail:
+       kfree(dev);
+       kfree(new_bus);
+       kfree(fixed);
+
+       return err;
+}
+
+
+MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
+MODULE_AUTHOR("Vitaly Bordug");
+MODULE_LICENSE("GPL");
+
+static int __init fixed_init(void)
+{
+       int ret;
+       int duplex = 0;
+
+       /* register on the bus... Not expected to be matched with anything there... */
+       phy_driver_register(&fixed_mdio_driver);
+
+       /* So let the fun begin...
+          We will create several mdio devices here, and will bound the upper
+          driver to them.
+
+          Then the external software can lookup the phy bus by searching
+          fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
+          virtual 100M Fdx phy.
+
+          In case several virtual PHYs required, the bus_id will be in form
+          fixed_<num>@<speed>:<duplex>, which make it able even to define
+          driver-specific link control callback, if for instance PHY is completely
+          SW-driven.
+
+       */
+
+#ifdef CONFIG_FIXED_MII_DUPLEX
+       duplex = 1;
+#endif
+
+#ifdef CONFIG_FIXED_MII_100_FDX
+       fixed_mdio_register_device(0, 100, 1);
+#endif
+
+#ifdef CONFIX_FIXED_MII_10_FDX
+       fixed_mdio_register_device(0, 10, 1);
+#endif
+       return 0;
+}
+
+static void __exit fixed_exit(void)
+{
+       phy_driver_unregister(&fixed_mdio_driver);
+       /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
+}
+
+module_init(fixed_init);
+module_exit(fixed_exit);
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644 (file)
index 0000000..b1d8ed4
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM  30 /* Interrupt Mask */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+       (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+
+static int lan83c185_config_intr(struct phy_device *phydev)
+{
+       int rc = phy_write (phydev, MII_LAN83C185_IM,
+                       ((PHY_INTERRUPT_ENABLED == phydev->interrupts)
+                       ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
+                       : 0));
+
+       return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_ack_interrupt(struct phy_device *phydev)
+{
+       int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+       return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_config_init(struct phy_device *phydev)
+{
+       return lan83c185_ack_interrupt (phydev);
+}
+
+
+static struct phy_driver lan83c185_driver = {
+       .phy_id         = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "SMSC LAN83C185",
+
+       .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+                               | SUPPORTED_Asym_Pause),
+       .flags          = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+       /* basic functions */
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .config_init    = lan83c185_config_init,
+
+       /* IRQ related */
+       .ack_interrupt  = lan83c185_ack_interrupt,
+       .config_intr    = lan83c185_config_intr,
+
+       .driver         = { .owner = THIS_MODULE, }
+};
+
+static int __init smsc_init(void)
+{
+       return phy_driver_register (&lan83c185_driver);
+}
+
+static void __exit smsc_exit(void)
+{
+       phy_driver_unregister (&lan83c185_driver);
+}
+
+MODULE_DESCRIPTION("SMSC PHY driver");
+MODULE_AUTHOR("Herbert Valerio Riedel");
+MODULE_LICENSE("GPL");
+
+module_init(smsc_init);
+module_exit(smsc_exit);
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
new file mode 100644 (file)
index 0000000..792716b
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Driver for Vitesse PHYs
+ *
+ * Author: Kriston Carson
+ *
+ * Copyright (c) 2005 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+/* Vitesse Extended Control Register 1 */
+#define MII_VSC8244_EXT_CON1           0x17
+#define MII_VSC8244_EXTCON1_INIT       0x0000
+
+/* Vitesse Interrupt Mask Register */
+#define MII_VSC8244_IMASK              0x19
+#define MII_VSC8244_IMASK_IEN          0x8000
+#define MII_VSC8244_IMASK_SPEED                0x4000
+#define MII_VSC8244_IMASK_LINK         0x2000
+#define MII_VSC8244_IMASK_DUPLEX       0x1000
+#define MII_VSC8244_IMASK_MASK         0xf000
+
+/* Vitesse Interrupt Status Register */
+#define MII_VSC8244_ISTAT              0x1a
+#define MII_VSC8244_ISTAT_STATUS       0x8000
+#define MII_VSC8244_ISTAT_SPEED                0x4000
+#define MII_VSC8244_ISTAT_LINK         0x2000
+#define MII_VSC8244_ISTAT_DUPLEX       0x1000
+
+/* Vitesse Auxiliary Control/Status Register */
+#define MII_VSC8244_AUX_CONSTAT                0x1c
+#define MII_VSC8244_AUXCONSTAT_INIT            0x0004
+#define MII_VSC8244_AUXCONSTAT_DUPLEX          0x0020
+#define MII_VSC8244_AUXCONSTAT_SPEED           0x0018
+#define MII_VSC8244_AUXCONSTAT_GBIT            0x0010
+#define MII_VSC8244_AUXCONSTAT_100             0x0008
+
+MODULE_DESCRIPTION("Vitesse PHY driver");
+MODULE_AUTHOR("Kriston Carson");
+MODULE_LICENSE("GPL");
+
+static int vsc824x_config_init(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
+                       MII_VSC8244_AUXCONSTAT_INIT);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, MII_VSC8244_EXT_CON1,
+                       MII_VSC8244_EXTCON1_INIT);
+       return err;
+}
+
+static int vsc824x_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, MII_VSC8244_ISTAT);
+
+       return (err < 0) ? err : 0;
+}
+
+static int vsc824x_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               err = phy_write(phydev, MII_VSC8244_IMASK,
+                               MII_VSC8244_IMASK_MASK);
+       else
+               err = phy_write(phydev, MII_VSC8244_IMASK, 0);
+       return err;
+}
+
+/* Vitesse 824x */
+static struct phy_driver vsc8244_driver = {
+       .phy_id         = 0x000fc6c2,
+       .name           = "Vitesse VSC8244",
+       .phy_id_mask    = 0x000fffc0,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &vsc824x_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc824x_ack_interrupt,
+       .config_intr    = &vsc824x_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
+static int __init vsc8244_init(void)
+{
+       return phy_driver_register(&vsc8244_driver);
+}
+
+static void __exit vsc8244_exit(void)
+{
+       phy_driver_unregister(&vsc8244_driver);
+}
+
+module_init(vsc8244_init);
+module_exit(vsc8244_exit);
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
new file mode 100644 (file)
index 0000000..4438fe8
--- /dev/null
@@ -0,0 +1,2306 @@
+/*
+ * smc911x.c
+ * This is a driver for SMSC's LAN911{5,6,7,8} single-chip Ethernet devices.
+ *
+ * Copyright (C) 2005 Sensoria Corp
+ *        Derived from the unified SMC91x driver by Nicolas Pitre
+ *        and the smsc911x.c reference driver by SMSC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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
+ *
+ * Arguments:
+ *      watchdog  = TX watchdog timeout
+ *      tx_fifo_kb = Size of TX FIFO in KB
+ *
+ * History:
+ *       04/16/05      Dustin McIntire          Initial version
+ */
+static const char version[] =
+        "smc911x.c: v1.0 04-16-2005 by Dustin McIntire <dustin@sensoria.com>\n";
+
+/* Debugging options */
+#define ENABLE_SMC_DEBUG_RX            0
+#define ENABLE_SMC_DEBUG_TX            0
+#define ENABLE_SMC_DEBUG_DMA           0
+#define ENABLE_SMC_DEBUG_PKTS          0
+#define ENABLE_SMC_DEBUG_MISC          0
+#define ENABLE_SMC_DEBUG_FUNC          0
+
+#define SMC_DEBUG_RX           ((ENABLE_SMC_DEBUG_RX   ? 1 : 0) << 0)
+#define SMC_DEBUG_TX           ((ENABLE_SMC_DEBUG_TX   ? 1 : 0) << 1)
+#define SMC_DEBUG_DMA          ((ENABLE_SMC_DEBUG_DMA  ? 1 : 0) << 2)
+#define SMC_DEBUG_PKTS         ((ENABLE_SMC_DEBUG_PKTS ? 1 : 0) << 3)
+#define SMC_DEBUG_MISC         ((ENABLE_SMC_DEBUG_MISC ? 1 : 0) << 4)
+#define SMC_DEBUG_FUNC         ((ENABLE_SMC_DEBUG_FUNC ? 1 : 0) << 5)
+
+#ifndef SMC_DEBUG
+#define SMC_DEBUG       ( SMC_DEBUG_RX   | \
+                          SMC_DEBUG_TX   | \
+                          SMC_DEBUG_DMA  | \
+                          SMC_DEBUG_PKTS | \
+                          SMC_DEBUG_MISC | \
+                          SMC_DEBUG_FUNC   \
+                        )
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/workqueue.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "smc911x.h"
+
+/*
+ * Transmit timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+static int tx_fifo_kb=8;
+module_param(tx_fifo_kb, int, 0400);
+MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
+
+MODULE_LICENSE("GPL");
+
+/*
+ * The internal workings of the driver.  If you are changing anything
+ * here with the SMC stuff, you should have the datasheet and know
+ * what you are doing.
+ */
+#define CARDNAME "smc911x"
+
+/*
+ * Use power-down feature of the chip
+ */
+#define POWER_DOWN              1
+
+
+/* store this information for the driver.. */
+struct smc911x_local {
+       /*
+        * If I have to wait until the DMA is finished and ready to reload a
+        * packet, I will store the skbuff here. Then, the DMA will send it
+        * out and free it.
+        */
+       struct sk_buff *pending_tx_skb;
+
+       /*
+        * these are things that the kernel wants me to keep, so users
+        * can find out semi-useless statistics of how well the card is
+        * performing
+        */
+       struct net_device_stats stats;
+
+       /* version/revision of the SMC911x chip */
+       u16 version;
+       u16 revision;
+
+       /* FIFO sizes */
+       int tx_fifo_kb;
+       int tx_fifo_size;
+       int rx_fifo_size;
+       int afc_cfg;
+
+       /* Contains the current active receive/phy mode */
+       int ctl_rfduplx;
+       int ctl_rspeed;
+
+       u32 msg_enable;
+       u32 phy_type;
+       struct mii_if_info mii;
+
+       /* work queue */
+       struct work_struct phy_configure;
+       int work_pending;
+
+       int tx_throttle;
+       spinlock_t lock;
+
+#ifdef SMC_USE_DMA
+       /* DMA needs the physical address of the chip */
+       u_long physaddr;
+       int rxdma;
+       int txdma;
+       int rxdma_active;
+       int txdma_active;
+       struct sk_buff *current_rx_skb;
+       struct sk_buff *current_tx_skb;
+       struct device *dev;
+#endif
+};
+
+#if SMC_DEBUG > 0
+#define DBG(n, args...)                                 \
+       do {                                     \
+               if (SMC_DEBUG & (n))             \
+                       printk(args);            \
+       } while (0)
+
+#define PRINTK(args...)   printk(args)
+#else
+#define DBG(n, args...)   do { } while (0)
+#define PRINTK(args...)   printk(KERN_DEBUG args)
+#endif
+
+#if SMC_DEBUG_PKTS > 0
+static void PRINT_PKT(u_char *buf, int length)
+{
+       int i;
+       int remainder;
+       int lines;
+
+       lines = length / 16;
+       remainder = length % 16;
+
+       for (i = 0; i < lines ; i ++) {
+               int cur;
+               for (cur = 0; cur < 8; cur++) {
+                       u_char a, b;
+                       a = *buf++;
+                       b = *buf++;
+                       printk("%02x%02x ", a, b);
+               }
+               printk("\n");
+       }
+       for (i = 0; i < remainder/2 ; i++) {
+               u_char a, b;
+               a = *buf++;
+               b = *buf++;
+               printk("%02x%02x ", a, b);
+       }
+       printk("\n");
+}
+#else
+#define PRINT_PKT(x...)  do { } while (0)
+#endif
+
+
+/* this enables an interrupt in the interrupt mask register */
+#define SMC_ENABLE_INT(x) do {                         \
+       unsigned int  __mask;                           \
+       unsigned long __flags;                          \
+       spin_lock_irqsave(&lp->lock, __flags);          \
+       __mask = SMC_GET_INT_EN();                      \
+       __mask |= (x);                                  \
+       SMC_SET_INT_EN(__mask);                         \
+       spin_unlock_irqrestore(&lp->lock, __flags);     \
+} while (0)
+
+/* this disables an interrupt from the interrupt mask register */
+#define SMC_DISABLE_INT(x) do {                                \
+       unsigned int  __mask;                           \
+       unsigned long __flags;                          \
+       spin_lock_irqsave(&lp->lock, __flags);          \
+       __mask = SMC_GET_INT_EN();                      \
+       __mask &= ~(x);                                 \
+       SMC_SET_INT_EN(__mask);                         \
+       spin_unlock_irqrestore(&lp->lock, __flags);     \
+} while (0)
+
+/*
+ * this does a soft reset on the device
+ */
+static void smc911x_reset(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned int reg, timeout=0, resets=1;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /*       Take out of PM setting first */
+       if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) {
+               /* Write to the bytetest will take out of powerdown */
+               SMC_SET_BYTE_TEST(0);
+               timeout=10;
+               do {
+                       udelay(10);
+                       reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
+               } while ( timeout-- && !reg);
+               if (timeout == 0) {
+                       PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
+                       return;
+               }
+       }
+
+       /* Disable all interrupts */
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_SET_INT_EN(0);
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       while (resets--) {
+               SMC_SET_HW_CFG(HW_CFG_SRST_);
+               timeout=10;
+               do {
+                       udelay(10);
+                       reg = SMC_GET_HW_CFG();
+                       /* If chip indicates reset timeout then try again */
+                       if (reg & HW_CFG_SRST_TO_) {
+                               PRINTK("%s: chip reset timeout, retrying...\n", dev->name);
+                               resets++;
+                               break;
+                       }
+               } while ( timeout-- && (reg & HW_CFG_SRST_));
+       }
+       if (timeout == 0) {
+               PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
+               return;
+       }
+
+       /* make sure EEPROM has finished loading before setting GPIO_CFG */
+       timeout=1000;
+       while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) {
+               udelay(10);
+       }
+       if (timeout == 0){
+               PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name);
+               return;
+       }
+
+       /* Initialize interrupts */
+       SMC_SET_INT_EN(0);
+       SMC_ACK_INT(-1);
+
+       /* Reset the FIFO level and flow control settings */
+       SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16);
+//TODO: Figure out what appropriate pause time is
+       SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_);
+       SMC_SET_AFC_CFG(lp->afc_cfg);
+
+
+       /* Set to LED outputs */
+       SMC_SET_GPIO_CFG(0x70070000);
+
+       /*
+        * Deassert IRQ for 1*10us for edge type interrupts
+        * and drive IRQ pin push-pull
+        */
+       SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ );
+
+       /* clear anything saved */
+       if (lp->pending_tx_skb != NULL) {
+               dev_kfree_skb (lp->pending_tx_skb);
+               lp->pending_tx_skb = NULL;
+               lp->stats.tx_errors++;
+               lp->stats.tx_aborted_errors++;
+       }
+}
+
+/*
+ * Enable Interrupts, Receive, and Transmit
+ */
+static void smc911x_enable(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned mask, cfg, cr;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       SMC_SET_MAC_ADDR(dev->dev_addr);
+
+       /* Enable TX */
+       cfg = SMC_GET_HW_CFG();
+       cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF;
+       cfg |= HW_CFG_SF_;
+       SMC_SET_HW_CFG(cfg);
+       SMC_SET_FIFO_TDA(0xFF);
+       /* Update TX stats on every 64 packets received or every 1 sec */
+       SMC_SET_FIFO_TSL(64);
+       SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_GET_MAC_CR(cr);
+       cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_;
+       SMC_SET_MAC_CR(cr);
+       SMC_SET_TX_CFG(TX_CFG_TX_ON_);
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       /* Add 2 byte padding to start of packets */
+       SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_);
+
+       /* Turn on receiver and enable RX */
+       if (cr & MAC_CR_RXEN_)
+               DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ );
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       /* Interrupt on every received packet */
+       SMC_SET_FIFO_RSA(0x01);
+       SMC_SET_FIFO_RSL(0x00);
+
+       /* now, enable interrupts */
+       mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ |
+               INT_EN_GPT_INT_EN_ | INT_EN_RXDFH_INT_EN_ | INT_EN_RXE_EN_ |
+               INT_EN_PHY_INT_EN_;
+       if (IS_REV_A(lp->revision))
+               mask|=INT_EN_RDFL_EN_;
+       else {
+               mask|=INT_EN_RDFO_EN_;
+       }
+       SMC_ENABLE_INT(mask);
+}
+
+/*
+ * this puts the device in an inactive state
+ */
+static void smc911x_shutdown(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned cr;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+
+       /* Disable IRQ's */
+       SMC_SET_INT_EN(0);
+
+       /* Turn of Rx and TX */
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_GET_MAC_CR(cr);
+       cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_);
+       SMC_SET_MAC_CR(cr);
+       SMC_SET_TX_CFG(TX_CFG_STOP_TX_);
+       spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static inline void smc911x_drop_pkt(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int fifo_count, timeout, reg;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+       fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF;
+       if (fifo_count <= 4) {
+               /* Manually dump the packet data */
+               while (fifo_count--)
+                       SMC_GET_RX_FIFO();
+       } else   {
+               /* Fast forward through the bad packet */
+               SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_);
+               timeout=50;
+               do {
+                       udelay(10);
+                       reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
+               } while ( timeout-- && reg);
+               if (timeout == 0) {
+                       PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
+               }
+       }
+}
+
+/*
+ * This is the procedure to handle the receipt of a packet.
+ * It should be called after checking for packet presence in
+ * the RX status FIFO.  It must be called with the spin lock
+ * already held.
+ */
+static inline void      smc911x_rcv(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int pkt_len, status;
+       struct sk_buff *skb;
+       unsigned char *data;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n",
+               dev->name, __FUNCTION__);
+       status = SMC_GET_RX_STS_FIFO();
+       DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n",
+               dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff);
+       pkt_len = (status & RX_STS_PKT_LEN_) >> 16;
+       if (status & RX_STS_ES_) {
+               /* Deal with a bad packet */
+               lp->stats.rx_errors++;
+               if (status & RX_STS_CRC_ERR_)
+                       lp->stats.rx_crc_errors++;
+               else {
+                       if (status & RX_STS_LEN_ERR_)
+                               lp->stats.rx_length_errors++;
+                       if (status & RX_STS_MCAST_)
+                               lp->stats.multicast++;
+               }
+               /* Remove the bad packet data from the RX FIFO */
+               smc911x_drop_pkt(dev);
+       } else {
+               /* Receive a valid packet */
+               /* Alloc a buffer with extra room for DMA alignment */
+               skb=dev_alloc_skb(pkt_len+32);
+               if (unlikely(skb == NULL)) {
+                       PRINTK( "%s: Low memory, rcvd packet dropped.\n",
+                               dev->name);
+                       lp->stats.rx_dropped++;
+                       smc911x_drop_pkt(dev);
+                       return;
+               }
+               /* Align IP header to 32 bits
+                * Note that the device is configured to add a 2
+                * byte padding to the packet start, so we really
+                * want to write to the orignal data pointer */
+               data = skb->data;
+               skb_reserve(skb, 2);
+               skb_put(skb,pkt_len-4);
+#ifdef SMC_USE_DMA
+               {
+               unsigned int fifo;
+               /* Lower the FIFO threshold if possible */
+               fifo = SMC_GET_FIFO_INT();
+               if (fifo & 0xFF) fifo--;
+               DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n",
+                       dev->name, fifo & 0xff);
+               SMC_SET_FIFO_INT(fifo);
+               /* Setup RX DMA */
+               SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_));
+               lp->rxdma_active = 1;
+               lp->current_rx_skb = skb;
+               SMC_PULL_DATA(data, (pkt_len+2+15) & ~15);
+               /* Packet processing deferred to DMA RX interrupt */
+               }
+#else
+               SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_));
+               SMC_PULL_DATA(data, pkt_len+2+3);
+
+               DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,);
+               PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
+               dev->last_rx = jiffies;
+               skb->dev = dev;
+               skb->protocol = eth_type_trans(skb, dev);
+               netif_rx(skb);
+               lp->stats.rx_packets++;
+               lp->stats.rx_bytes += pkt_len-4;
+#endif
+       }
+}
+
+/*
+ * This is called to actually send a packet to the chip.
+ */
+static void smc911x_hardware_send_pkt(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       struct sk_buff *skb;
+       unsigned int cmdA, cmdB, len;
+       unsigned char *buf;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__);
+       BUG_ON(lp->pending_tx_skb == NULL);
+
+       skb = lp->pending_tx_skb;
+       lp->pending_tx_skb = NULL;
+
+       /* cmdA {25:24] data alignment [20:16] start offset [10:0] buffer length */
+       /* cmdB {31:16] pkt tag [10:0] length */
+#ifdef SMC_USE_DMA
+       /* 16 byte buffer alignment mode */
+       buf = (char*)((u32)(skb->data) & ~0xF);
+       len = (skb->len + 0xF + ((u32)skb->data & 0xF)) & ~0xF;
+       cmdA = (1<<24) | (((u32)skb->data & 0xF)<<16) |
+                       TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
+                       skb->len;
+#else
+       buf = (char*)((u32)skb->data & ~0x3);
+       len = (skb->len + 3 + ((u32)skb->data & 3)) & ~0x3;
+       cmdA = (((u32)skb->data & 0x3) << 16) |
+                       TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
+                       skb->len;
+#endif
+       /* tag is packet length so we can use this in stats update later */
+       cmdB = (skb->len  << 16) | (skb->len & 0x7FF);
+
+       DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n",
+                dev->name, len, len, buf, cmdA, cmdB);
+       SMC_SET_TX_FIFO(cmdA);
+       SMC_SET_TX_FIFO(cmdB);
+
+       DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name);
+       PRINT_PKT(buf, len <= 64 ? len : 64);
+
+       /* Send pkt via PIO or DMA */
+#ifdef SMC_USE_DMA
+       lp->current_tx_skb = skb;
+       SMC_PUSH_DATA(buf, len);
+       /* DMA complete IRQ will free buffer and set jiffies */
+#else
+       SMC_PUSH_DATA(buf, len);
+       dev->trans_start = jiffies;
+       dev_kfree_skb(skb);
+#endif
+       spin_lock_irqsave(&lp->lock, flags);
+       if (!lp->tx_throttle) {
+               netif_wake_queue(dev);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+       SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_);
+}
+
+/*
+ * Since I am not sure if I will have enough room in the chip's ram
+ * to store the packet, I call this routine which either sends it
+ * now, or set the card to generates an interrupt when ready
+ * for the packet.
+ */
+static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int free;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
+               dev->name, __FUNCTION__);
+
+       BUG_ON(lp->pending_tx_skb != NULL);
+
+       free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_;
+       DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free);
+
+       /* Turn off the flow when running out of space in FIFO */
+       if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) {
+               DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n",
+                       dev->name, free);
+               spin_lock_irqsave(&lp->lock, flags);
+               /* Reenable when at least 1 packet of size MTU present */
+               SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64);
+               lp->tx_throttle = 1;
+               netif_stop_queue(dev);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+
+       /* Drop packets when we run out of space in TX FIFO
+        * Account for overhead required for:
+        *
+        *        Tx command words                       8 bytes
+        *        Start offset                           15 bytes
+        *        End padding                            15 bytes
+        */
+       if (unlikely(free < (skb->len + 8 + 15 + 15))) {
+               printk("%s: No Tx free space %d < %d\n",
+                       dev->name, free, skb->len);
+               lp->pending_tx_skb = NULL;
+               lp->stats.tx_errors++;
+               lp->stats.tx_dropped++;
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
+#ifdef SMC_USE_DMA
+       {
+               /* If the DMA is already running then defer this packet Tx until
+                * the DMA IRQ starts it
+                */
+               spin_lock_irqsave(&lp->lock, flags);
+               if (lp->txdma_active) {
+                       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name);
+                       lp->pending_tx_skb = skb;
+                       netif_stop_queue(dev);
+                       spin_unlock_irqrestore(&lp->lock, flags);
+                       return 0;
+               } else {
+                       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name);
+                       lp->txdma_active = 1;
+               }
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+#endif
+       lp->pending_tx_skb = skb;
+       smc911x_hardware_send_pkt(dev);
+
+       return 0;
+}
+
+/*
+ * This handles a TX status interrupt, which is only called when:
+ * - a TX error occurred, or
+ * - TX of a packet completed.
+ */
+static void smc911x_tx(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned int tx_status;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
+               dev->name, __FUNCTION__);
+
+       /* Collect the TX status */
+       while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) {
+               DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n",
+                       dev->name,
+                       (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16);
+               tx_status = SMC_GET_TX_STS_FIFO();
+               lp->stats.tx_packets++;
+               lp->stats.tx_bytes+=tx_status>>16;
+               DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n",
+                       dev->name, (tx_status & 0xffff0000) >> 16,
+                       tx_status & 0x0000ffff);
+               /* count Tx errors, but ignore lost carrier errors when in
+                * full-duplex mode */
+               if ((tx_status & TX_STS_ES_) && !(lp->ctl_rfduplx &&
+                   !(tx_status & 0x00000306))) {
+                       lp->stats.tx_errors++;
+               }
+               if (tx_status & TX_STS_MANY_COLL_) {
+                       lp->stats.collisions+=16;
+                       lp->stats.tx_aborted_errors++;
+               } else {
+                       lp->stats.collisions+=(tx_status & TX_STS_COLL_CNT_) >> 3;
+               }
+               /* carrier error only has meaning for half-duplex communication */
+               if ((tx_status & (TX_STS_LOC_ | TX_STS_NO_CARR_)) &&
+                   !lp->ctl_rfduplx) {
+                       lp->stats.tx_carrier_errors++;
+               }
+               if (tx_status & TX_STS_LATE_COLL_) {
+                       lp->stats.collisions++;
+                       lp->stats.tx_aborted_errors++;
+               }
+       }
+}
+
+
+/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
+/*
+ * Reads a register from the MII Management serial interface
+ */
+
+static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int phydata;
+
+       SMC_GET_MII(phyreg, phyaddr, phydata);
+
+       DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n",
+               __FUNCTION__, phyaddr, phyreg, phydata);
+       return phydata;
+}
+
+
+/*
+ * Writes a register to the MII Management serial interface
+ */
+static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+                       int phydata)
+{
+       unsigned long ioaddr = dev->base_addr;
+
+       DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+               __FUNCTION__, phyaddr, phyreg, phydata);
+
+       SMC_SET_MII(phyreg, phyaddr, phydata);
+}
+
+/*
+ * Finds and reports the PHY address (115 and 117 have external
+ * PHY interface 118 has internal only
+ */
+static void smc911x_phy_detect(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       int phyaddr;
+       unsigned int cfg, id1, id2;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       lp->phy_type = 0;
+
+       /*
+        * Scan all 32 PHY addresses if necessary, starting at
+        * PHY#1 to PHY#31, and then PHY#0 last.
+        */
+       switch(lp->version) {
+               case 0x115:
+               case 0x117:
+                       cfg = SMC_GET_HW_CFG();
+                       if (cfg & HW_CFG_EXT_PHY_DET_) {
+                               cfg &= ~HW_CFG_PHY_CLK_SEL_;
+                               cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
+                               SMC_SET_HW_CFG(cfg);
+                               udelay(10); /* Wait for clocks to stop */
+
+                               cfg |= HW_CFG_EXT_PHY_EN_;
+                               SMC_SET_HW_CFG(cfg);
+                               udelay(10); /* Wait for clocks to stop */
+
+                               cfg &= ~HW_CFG_PHY_CLK_SEL_;
+                               cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
+                               SMC_SET_HW_CFG(cfg);
+                               udelay(10); /* Wait for clocks to stop */
+
+                               cfg |= HW_CFG_SMI_SEL_;
+                               SMC_SET_HW_CFG(cfg);
+
+                               for (phyaddr = 1; phyaddr < 32; ++phyaddr) {
+
+                                       /* Read the PHY identifiers */
+                                       SMC_GET_PHY_ID1(phyaddr & 31, id1);
+                                       SMC_GET_PHY_ID2(phyaddr & 31, id2);
+
+                                       /* Make sure it is a valid identifier */
+                                       if (id1 != 0x0000 && id1 != 0xffff &&
+                                           id1 != 0x8000 && id2 != 0x0000 &&
+                                           id2 != 0xffff && id2 != 0x8000) {
+                                               /* Save the PHY's address */
+                                               lp->mii.phy_id = phyaddr & 31;
+                                               lp->phy_type = id1 << 16 | id2;
+                                               break;
+                                       }
+                               }
+                       }
+               default:
+                       /* Internal media only */
+                       SMC_GET_PHY_ID1(1, id1);
+                       SMC_GET_PHY_ID2(1, id2);
+                       /* Save the PHY's address */
+                       lp->mii.phy_id = 1;
+                       lp->phy_type = id1 << 16 | id2;
+       }
+
+       DBG(SMC_DEBUG_MISC, "%s: phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n",
+               dev->name, id1, id2, lp->mii.phy_id);
+}
+
+/*
+ * Sets the PHY to a configuration as determined by the user.
+ * Called with spin_lock held.
+ */
+static int smc911x_phy_fixed(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       int bmcr;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /* Enter Link Disable state */
+       SMC_GET_PHY_BMCR(phyaddr, bmcr);
+       bmcr |= BMCR_PDOWN;
+       SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+       /*
+        * Set our fixed capabilities
+        * Disable auto-negotiation
+        */
+       bmcr &= ~BMCR_ANENABLE;
+       if (lp->ctl_rfduplx)
+               bmcr |= BMCR_FULLDPLX;
+
+       if (lp->ctl_rspeed == 100)
+               bmcr |= BMCR_SPEED100;
+
+       /* Write our capabilities to the phy control register */
+       SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+       /* Re-Configure the Receive/Phy Control register */
+       bmcr &= ~BMCR_PDOWN;
+       SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+       return 1;
+}
+
+/*
+ * smc911x_phy_reset - reset the phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Issue a software reset for the specified PHY and
+ * wait up to 100ms for the reset to complete.  We should
+ * not access the PHY for 50ms after issuing the reset.
+ *
+ * The time to wait appears to be dependent on the PHY.
+ *
+ */
+static int smc911x_phy_reset(struct net_device *dev, int phy)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int timeout;
+       unsigned long flags;
+       unsigned int reg;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       reg = SMC_GET_PMT_CTRL();
+       reg &= ~0xfffff030;
+       reg |= PMT_CTRL_PHY_RST_;
+       SMC_SET_PMT_CTRL(reg);
+       spin_unlock_irqrestore(&lp->lock, flags);
+       for (timeout = 2; timeout; timeout--) {
+               msleep(50);
+               spin_lock_irqsave(&lp->lock, flags);
+               reg = SMC_GET_PMT_CTRL();
+               spin_unlock_irqrestore(&lp->lock, flags);
+               if (!(reg & PMT_CTRL_PHY_RST_)) {
+                       /* extra delay required because the phy may
+                        * not be completed with its reset
+                        * when PHY_BCR_RESET_ is cleared. 256us
+                        * should suffice, but use 500us to be safe
+                        */
+                       udelay(500);
+               break;
+               }
+       }
+
+       return reg & PMT_CTRL_PHY_RST_;
+}
+
+/*
+ * smc911x_phy_powerdown - powerdown phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Power down the specified PHY
+ */
+static void smc911x_phy_powerdown(struct net_device *dev, int phy)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int bmcr;
+
+       /* Enter Link Disable state */
+       SMC_GET_PHY_BMCR(phy, bmcr);
+       bmcr |= BMCR_PDOWN;
+       SMC_SET_PHY_BMCR(phy, bmcr);
+}
+
+/*
+ * smc911x_phy_check_media - check the media status and adjust BMCR
+ * @dev: net device
+ * @init: set true for initialisation
+ *
+ * Select duplex mode depending on negotiation state.  This
+ * also updates our carrier state.
+ */
+static void smc911x_phy_check_media(struct net_device *dev, int init)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       unsigned int bmcr, cr;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
+               /* duplex state has changed */
+               SMC_GET_PHY_BMCR(phyaddr, bmcr);
+               SMC_GET_MAC_CR(cr);
+               if (lp->mii.full_duplex) {
+                       DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name);
+                       bmcr |= BMCR_FULLDPLX;
+                       cr |= MAC_CR_RCVOWN_;
+               } else {
+                       DBG(SMC_DEBUG_MISC, "%s: Configuring for half-duplex mode\n", dev->name);
+                       bmcr &= ~BMCR_FULLDPLX;
+                       cr &= ~MAC_CR_RCVOWN_;
+               }
+               SMC_SET_PHY_BMCR(phyaddr, bmcr);
+               SMC_SET_MAC_CR(cr);
+       }
+}
+
+/*
+ * Configures the specified PHY through the MII management interface
+ * using Autonegotiation.
+ * Calls smc911x_phy_fixed() if the user has requested a certain config.
+ * If RPC ANEG bit is set, the media selection is dependent purely on
+ * the selection by the MII (either in the MII BMCR reg or the result
+ * of autonegotiation.)  If the RPC ANEG bit is cleared, the selection
+ * is controlled by the RPC SPEED and RPC DPLX bits.
+ */
+static void smc911x_phy_configure(void *data)
+{
+       struct net_device *dev = data;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       int my_phy_caps; /* My PHY capabilities */
+       int my_ad_caps; /* My Advertised capabilities */
+       int status;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+
+       /*
+        * We should not be called if phy_type is zero.
+        */
+       if (lp->phy_type == 0)
+                goto smc911x_phy_configure_exit;
+
+       if (smc911x_phy_reset(dev, phyaddr)) {
+               printk("%s: PHY reset timed out\n", dev->name);
+               goto smc911x_phy_configure_exit;
+       }
+       spin_lock_irqsave(&lp->lock, flags);
+
+       /*
+        * Enable PHY Interrupts (for register 18)
+        * Interrupts listed here are enabled
+        */
+       SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ |
+                PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ |
+                PHY_INT_MASK_LINK_DOWN_);
+
+       /* If the user requested no auto neg, then go set his request */
+       if (lp->mii.force_media) {
+               smc911x_phy_fixed(dev);
+               goto smc911x_phy_configure_exit;
+       }
+
+       /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */
+       SMC_GET_PHY_BMSR(phyaddr, my_phy_caps);
+       if (!(my_phy_caps & BMSR_ANEGCAPABLE)) {
+               printk(KERN_INFO "Auto negotiation NOT supported\n");
+               smc911x_phy_fixed(dev);
+               goto smc911x_phy_configure_exit;
+       }
+
+       /* CSMA capable w/ both pauses */
+       my_ad_caps = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+
+       if (my_phy_caps & BMSR_100BASE4)
+               my_ad_caps |= ADVERTISE_100BASE4;
+       if (my_phy_caps & BMSR_100FULL)
+               my_ad_caps |= ADVERTISE_100FULL;
+       if (my_phy_caps & BMSR_100HALF)
+               my_ad_caps |= ADVERTISE_100HALF;
+       if (my_phy_caps & BMSR_10FULL)
+               my_ad_caps |= ADVERTISE_10FULL;
+       if (my_phy_caps & BMSR_10HALF)
+               my_ad_caps |= ADVERTISE_10HALF;
+
+       /* Disable capabilities not selected by our user */
+       if (lp->ctl_rspeed != 100)
+               my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF);
+
+        if (!lp->ctl_rfduplx)
+               my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
+
+       /* Update our Auto-Neg Advertisement Register */
+       SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps);
+       lp->mii.advertising = my_ad_caps;
+
+       /*
+        * Read the register back.       Without this, it appears that when
+        * auto-negotiation is restarted, sometimes it isn't ready and
+        * the link does not come up.
+        */
+       udelay(10);
+       SMC_GET_PHY_MII_ADV(phyaddr, status);
+
+       DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps);
+       DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps);
+
+       /* Restart auto-negotiation process in order to advertise my caps */
+       SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART);
+
+       smc911x_phy_check_media(dev, 1);
+
+smc911x_phy_configure_exit:
+       spin_unlock_irqrestore(&lp->lock, flags);
+       lp->work_pending = 0;
+}
+
+/*
+ * smc911x_phy_interrupt
+ *
+ * Purpose:  Handle interrupts relating to PHY register 18. This is
+ *      called from the "hard" interrupt handler under our private spinlock.
+ */
+static void smc911x_phy_interrupt(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       int status;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       if (lp->phy_type == 0)
+               return;
+
+       smc911x_phy_check_media(dev, 0);
+       /* read to clear status bits */
+       SMC_GET_PHY_INT_SRC(phyaddr,status);
+       DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n",
+               dev->name, status & 0xffff);
+       DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n",
+               dev->name, SMC_GET_AFC_CFG());
+}
+
+/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/
+
+/*
+ * This is the main routine of the driver, to handle the device when
+ * it needs some attention.
+ */
+static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned int status, mask, timeout;
+       unsigned int rx_overrun=0, cr, pkts;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+
+       /* Spurious interrupt check */
+       if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
+               (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
+               spin_unlock_irqrestore(&lp->lock, flags);
+               return IRQ_NONE;
+       }
+
+       mask = SMC_GET_INT_EN();
+       SMC_SET_INT_EN(0);
+
+       /* set a timeout value, so I don't stay here forever */
+       timeout = 8;
+
+
+       do {
+               status = SMC_GET_INT();
+
+               DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n",
+                       dev->name, status, mask, status & ~mask);
+
+               status &= mask;
+               if (!status)
+                       break;
+
+               /* Handle SW interrupt condition */
+               if (status & INT_STS_SW_INT_) {
+                       SMC_ACK_INT(INT_STS_SW_INT_);
+                       mask &= ~INT_EN_SW_INT_EN_;
+               }
+               /* Handle various error conditions */
+               if (status & INT_STS_RXE_) {
+                       SMC_ACK_INT(INT_STS_RXE_);
+                       lp->stats.rx_errors++;
+               }
+               if (status & INT_STS_RXDFH_INT_) {
+                       SMC_ACK_INT(INT_STS_RXDFH_INT_);
+                       lp->stats.rx_dropped+=SMC_GET_RX_DROP();
+                }
+               /* Undocumented interrupt-what is the right thing to do here? */
+               if (status & INT_STS_RXDF_INT_) {
+                       SMC_ACK_INT(INT_STS_RXDF_INT_);
+               }
+
+               /* Rx Data FIFO exceeds set level */
+               if (status & INT_STS_RDFL_) {
+                       if (IS_REV_A(lp->revision)) {
+                               rx_overrun=1;
+                               SMC_GET_MAC_CR(cr);
+                               cr &= ~MAC_CR_RXEN_;
+                               SMC_SET_MAC_CR(cr);
+                               DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
+                               lp->stats.rx_errors++;
+                               lp->stats.rx_fifo_errors++;
+                       }
+                       SMC_ACK_INT(INT_STS_RDFL_);
+               }
+               if (status & INT_STS_RDFO_) {
+                       if (!IS_REV_A(lp->revision)) {
+                               SMC_GET_MAC_CR(cr);
+                               cr &= ~MAC_CR_RXEN_;
+                               SMC_SET_MAC_CR(cr);
+                               rx_overrun=1;
+                               DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
+                               lp->stats.rx_errors++;
+                               lp->stats.rx_fifo_errors++;
+                       }
+                       SMC_ACK_INT(INT_STS_RDFO_);
+               }
+               /* Handle receive condition */
+               if ((status & INT_STS_RSFL_) || rx_overrun) {
+                       unsigned int fifo;
+                       DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name);
+                       fifo = SMC_GET_RX_FIFO_INF();
+                       pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16;
+                       DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n",
+                               dev->name, pkts, fifo & 0xFFFF );
+                       if (pkts != 0) {
+#ifdef SMC_USE_DMA
+                               unsigned int fifo;
+                               if (lp->rxdma_active){
+                                       DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
+                                               "%s: RX DMA active\n", dev->name);
+                                       /* The DMA is already running so up the IRQ threshold */
+                                       fifo = SMC_GET_FIFO_INT() & ~0xFF;
+                                       fifo |= pkts & 0xFF;
+                                       DBG(SMC_DEBUG_RX,
+                                               "%s: Setting RX stat FIFO threshold to %d\n",
+                                               dev->name, fifo & 0xff);
+                                       SMC_SET_FIFO_INT(fifo);
+                               } else
+#endif
+                               smc911x_rcv(dev);
+                       }
+                       SMC_ACK_INT(INT_STS_RSFL_);
+               }
+               /* Handle transmit FIFO available */
+               if (status & INT_STS_TDFA_) {
+                       DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name);
+                       SMC_SET_FIFO_TDA(0xFF);
+                       lp->tx_throttle = 0;
+#ifdef SMC_USE_DMA
+                       if (!lp->txdma_active)
+#endif
+                               netif_wake_queue(dev);
+                       SMC_ACK_INT(INT_STS_TDFA_);
+               }
+               /* Handle transmit done condition */
+#if 1
+               if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) {
+                       DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC,
+                               "%s: Tx stat FIFO limit (%d) /GPT irq\n",
+                               dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16);
+                       smc911x_tx(dev);
+                       SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+                       SMC_ACK_INT(INT_STS_TSFL_);
+                       SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_);
+               }
+#else
+               if (status & INT_STS_TSFL_) {
+                       DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, );
+                       smc911x_tx(dev);
+                       SMC_ACK_INT(INT_STS_TSFL_);
+               }
+
+               if (status & INT_STS_GPT_INT_) {
+                       DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n",
+                               dev->name,
+                               SMC_GET_IRQ_CFG(),
+                               SMC_GET_FIFO_INT(),
+                               SMC_GET_RX_CFG());
+                       DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x "
+                               "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n",
+                               dev->name,
+                               (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16,
+                               SMC_GET_RX_FIFO_INF() & 0xffff,
+                               SMC_GET_RX_STS_FIFO_PEEK());
+                       SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+                       SMC_ACK_INT(INT_STS_GPT_INT_);
+               }
+#endif
+
+               /* Handle PHY interupt condition */
+               if (status & INT_STS_PHY_INT_) {
+                       DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name);
+                       smc911x_phy_interrupt(dev);
+                       SMC_ACK_INT(INT_STS_PHY_INT_);
+               }
+       } while (--timeout);
+
+       /* restore mask state */
+       SMC_SET_INT_EN(mask);
+
+       DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n",
+               dev->name, 8-timeout);
+
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef SMC_USE_DMA
+static void
+smc911x_tx_dma_irq(int dma, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct smc911x_local *lp = netdev_priv(dev);
+       struct sk_buff *skb = lp->current_tx_skb;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name);
+       /* Clear the DMA interrupt sources */
+       SMC_DMA_ACK_IRQ(dev, dma);
+       BUG_ON(skb == NULL);
+       dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE);
+       dev->trans_start = jiffies;
+       dev_kfree_skb_irq(skb);
+       lp->current_tx_skb = NULL;
+       if (lp->pending_tx_skb != NULL)
+               smc911x_hardware_send_pkt(dev);
+       else {
+               DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA,
+                       "%s: No pending Tx packets. DMA disabled\n", dev->name);
+               spin_lock_irqsave(&lp->lock, flags);
+               lp->txdma_active = 0;
+               if (!lp->tx_throttle) {
+                       netif_wake_queue(dev);
+               }
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+
+       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA,
+               "%s: TX DMA irq completed\n", dev->name);
+}
+static void
+smc911x_rx_dma_irq(int dma, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)data;
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       struct sk_buff *skb = lp->current_rx_skb;
+       unsigned long flags;
+       unsigned int pkts;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+       DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name);
+       /* Clear the DMA interrupt sources */
+       SMC_DMA_ACK_IRQ(dev, dma);
+       dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE);
+       BUG_ON(skb == NULL);
+       lp->current_rx_skb = NULL;
+       PRINT_PKT(skb->data, skb->len);
+       dev->last_rx = jiffies;
+       skb->dev = dev;
+       skb->protocol = eth_type_trans(skb, dev);
+       netif_rx(skb);
+       lp->stats.rx_packets++;
+       lp->stats.rx_bytes += skb->len;
+
+       spin_lock_irqsave(&lp->lock, flags);
+       pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16;
+       if (pkts != 0) {
+               smc911x_rcv(dev);
+       }else {
+               lp->rxdma_active = 0;
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+       DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
+               "%s: RX DMA irq completed. DMA RX FIFO PKTS %d\n",
+               dev->name, pkts);
+}
+#endif  /* SMC_USE_DMA */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void smc911x_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       smc911x_interrupt(dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+}
+#endif
+
+/* Our watchdog timed out. Called by the networking layer */
+static void smc911x_timeout(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int status, mask;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       status = SMC_GET_INT();
+       mask = SMC_GET_INT_EN();
+       spin_unlock_irqrestore(&lp->lock, flags);
+       DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n",
+               dev->name, status, mask);
+
+       /* Dump the current TX FIFO contents and restart */
+       mask = SMC_GET_TX_CFG();
+       SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_);
+       /*
+        * Reconfiguring the PHY doesn't seem like a bad idea here, but
+        * smc911x_phy_configure() calls msleep() which calls schedule_timeout()
+        * which calls schedule().       Hence we use a work queue.
+        */
+       if (lp->phy_type != 0) {
+               if (schedule_work(&lp->phy_configure)) {
+                       lp->work_pending = 1;
+               }
+       }
+
+       /* We can accept TX packets again */
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+}
+
+/*
+ * This routine will, depending on the values passed to it,
+ * either make it accept multicast packets, go into
+ * promiscuous mode (for TCPDUMP and cousins) or accept
+ * a select set of multicast packets
+ */
+static void smc911x_set_multicast_list(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int multicast_table[2];
+       unsigned int mcr, update_multicast = 0;
+       unsigned long flags;
+       /* table for flipping the order of 5 bits */
+       static const unsigned char invert5[] =
+               {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C,
+                0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E,
+                0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D,
+                0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F};
+
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_GET_MAC_CR(mcr);
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       if (dev->flags & IFF_PROMISC) {
+
+               DBG(SMC_DEBUG_MISC, "%s: RCR_PRMS\n", dev->name);
+               mcr |= MAC_CR_PRMS_;
+       }
+       /*
+        * Here, I am setting this to accept all multicast packets.
+        * I don't need to zero the multicast table, because the flag is
+        * checked before the table is
+        */
+       else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) {
+               DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name);
+               mcr |= MAC_CR_MCPAS_;
+       }
+
+       /*
+        * This sets the internal hardware table to filter out unwanted
+        * multicast packets before they take up memory.
+        *
+        * The SMC chip uses a hash table where the high 6 bits of the CRC of
+        * address are the offset into the table.       If that bit is 1, then the
+        * multicast packet is accepted.  Otherwise, it's dropped silently.
+        *
+        * To use the 6 bits as an offset into the table, the high 1 bit is
+        * the number of the 32 bit register, while the low 5 bits are the bit
+        * within that register.
+        */
+       else if (dev->mc_count)  {
+               int i;
+               struct dev_mc_list *cur_addr;
+
+               /* Set the Hash perfec mode */
+               mcr |= MAC_CR_HPFILT_;
+
+               /* start with a table of all zeros: reject all */
+               memset(multicast_table, 0, sizeof(multicast_table));
+
+               cur_addr = dev->mc_list;
+               for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
+                       int position;
+
+                       /* do we have a pointer here? */
+                       if (!cur_addr)
+                               break;
+                       /* make sure this is a multicast address -
+                               shouldn't this be a given if we have it here ? */
+                       if (!(*cur_addr->dmi_addr & 1))
+                                continue;
+
+                       /* only use the low order bits */
+                       position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f;
+
+                       /* do some messy swapping to put the bit in the right spot */
+                       multicast_table[invert5[position&0x1F]&0x1] |=
+                               (1<<invert5[(position>>1)&0x1F]);
+               }
+
+               /* be sure I get rid of flags I might have set */
+               mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+               /* now, the table can be loaded into the chipset */
+               update_multicast = 1;
+       } else   {
+               DBG(SMC_DEBUG_MISC, "%s: ~(MAC_CR_PRMS_|MAC_CR_MCPAS_)\n",
+                       dev->name);
+               mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+               /*
+                * since I'm disabling all multicast entirely, I need to
+                * clear the multicast list
+                */
+               memset(multicast_table, 0, sizeof(multicast_table));
+               update_multicast = 1;
+       }
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_SET_MAC_CR(mcr);
+       if (update_multicast) {
+               DBG(SMC_DEBUG_MISC,
+                       "%s: update mcast hash table 0x%08x 0x%08x\n",
+                       dev->name, multicast_table[0], multicast_table[1]);
+               SMC_SET_HASHL(multicast_table[0]);
+               SMC_SET_HASHH(multicast_table[1]);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+
+/*
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc..
+ */
+static int
+smc911x_open(struct net_device *dev)
+{
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /*
+        * Check that the address is valid.  If its not, refuse
+        * to bring the device up.       The user must specify an
+        * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
+        */
+       if (!is_valid_ether_addr(dev->dev_addr)) {
+               PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* reset the hardware */
+       smc911x_reset(dev);
+
+       /* Configure the PHY, initialize the link state */
+       smc911x_phy_configure(dev);
+
+       /* Turn on Tx + Rx */
+       smc911x_enable(dev);
+
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+/*
+ * smc911x_close
+ *
+ * this makes the board clean up everything that it can
+ * and not talk to the outside world.   Caused by
+ * an 'ifconfig ethX down'
+ */
+static int smc911x_close(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       netif_stop_queue(dev);
+       netif_carrier_off(dev);
+
+       /* clear everything */
+       smc911x_shutdown(dev);
+
+       if (lp->phy_type != 0) {
+               /* We need to ensure that no calls to
+                * smc911x_phy_configure are pending.
+
+                * flush_scheduled_work() cannot be called because we
+                * are running with the netlink semaphore held (from
+                * devinet_ioctl()) and the pending work queue
+                * contains linkwatch_event() (scheduled by
+                * netif_carrier_off() above). linkwatch_event() also
+                * wants the netlink semaphore.
+                */
+               while (lp->work_pending)
+                       schedule();
+               smc911x_phy_powerdown(dev, lp->mii.phy_id);
+       }
+
+       if (lp->pending_tx_skb) {
+               dev_kfree_skb(lp->pending_tx_skb);
+               lp->pending_tx_skb = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *smc911x_query_statistics(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+
+       return &lp->stats;
+}
+
+/*
+ * Ethtool support
+ */
+static int
+smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int ret, status;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+       cmd->maxtxpkt = 1;
+       cmd->maxrxpkt = 1;
+
+       if (lp->phy_type != 0) {
+               spin_lock_irqsave(&lp->lock, flags);
+               ret = mii_ethtool_gset(&lp->mii, cmd);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       } else {
+               cmd->supported = SUPPORTED_10baseT_Half |
+                               SUPPORTED_10baseT_Full |
+                               SUPPORTED_TP | SUPPORTED_AUI;
+
+               if (lp->ctl_rspeed == 10)
+                       cmd->speed = SPEED_10;
+               else if (lp->ctl_rspeed == 100)
+                       cmd->speed = SPEED_100;
+
+               cmd->autoneg = AUTONEG_DISABLE;
+               if (lp->mii.phy_id==1)
+                       cmd->transceiver = XCVR_INTERNAL;
+               else
+                       cmd->transceiver = XCVR_EXTERNAL;
+               cmd->port = 0;
+               SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status);
+               cmd->duplex =
+                       (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ?
+                               DUPLEX_FULL : DUPLEX_HALF;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int
+smc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       int ret;
+       unsigned long flags;
+
+       if (lp->phy_type != 0) {
+               spin_lock_irqsave(&lp->lock, flags);
+               ret = mii_ethtool_sset(&lp->mii, cmd);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       } else {
+               if (cmd->autoneg != AUTONEG_DISABLE ||
+                       cmd->speed != SPEED_10 ||
+                       (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) ||
+                       (cmd->port != PORT_TP && cmd->port != PORT_AUI))
+                       return -EINVAL;
+
+               lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL;
+
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static void
+smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       strncpy(info->driver, CARDNAME, sizeof(info->driver));
+       strncpy(info->version, version, sizeof(info->version));
+       strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+}
+
+static int smc911x_ethtool_nwayreset(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       int ret = -EINVAL;
+       unsigned long flags;
+
+       if (lp->phy_type != 0) {
+               spin_lock_irqsave(&lp->lock, flags);
+               ret = mii_nway_restart(&lp->mii);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+
+       return ret;
+}
+
+static u32 smc911x_ethtool_getmsglevel(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       return lp->msg_enable;
+}
+
+static void smc911x_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       lp->msg_enable = level;
+}
+
+static int smc911x_ethtool_getregslen(struct net_device *dev)
+{
+       /* System regs + MAC regs + PHY regs */
+       return (((E2P_CMD - ID_REV)/4 + 1) +
+                       (WUCSR - MAC_CR)+1 + 32) * sizeof(u32);
+}
+
+static void smc911x_ethtool_getregs(struct net_device *dev,
+                                                                                struct ethtool_regs* regs, void *buf)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long flags;
+       u32 reg,i,j=0;
+       u32 *data = (u32*)buf;
+
+       regs->version = lp->version;
+       for(i=ID_REV;i<=E2P_CMD;i+=4) {
+               data[j++] = SMC_inl(ioaddr,i);
+       }
+       for(i=MAC_CR;i<=WUCSR;i++) {
+               spin_lock_irqsave(&lp->lock, flags);
+               SMC_GET_MAC_CSR(i, reg);
+               spin_unlock_irqrestore(&lp->lock, flags);
+               data[j++] = reg;
+       }
+       for(i=0;i<=31;i++) {
+               spin_lock_irqsave(&lp->lock, flags);
+               SMC_GET_MII(i, lp->mii.phy_id, reg);
+               spin_unlock_irqrestore(&lp->lock, flags);
+               data[j++] = reg & 0xFFFF;
+       }
+}
+
+static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int timeout;
+       int e2p_cmd;
+
+       e2p_cmd = SMC_GET_E2P_CMD();
+       for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) {
+               if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) {
+                       PRINTK("%s: %s timeout waiting for EEPROM to respond\n",
+                               dev->name, __FUNCTION__);
+                       return -EFAULT;
+               }
+               mdelay(1);
+               e2p_cmd = SMC_GET_E2P_CMD();
+       }
+       if (timeout == 0) {
+               PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n",
+                       dev->name, __FUNCTION__);
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev,
+                                                                                                       int cmd, int addr)
+{
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+               return ret;
+       SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ |
+               ((cmd) & (0x7<<28)) |
+               ((addr) & 0xFF));
+       return 0;
+}
+
+static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev,
+                                                                                                       u8 *data)
+{
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+               return ret;
+       *data = SMC_GET_E2P_DATA();
+       return 0;
+}
+
+static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev,
+                                                                                                        u8 data)
+{
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+               return ret;
+       SMC_SET_E2P_DATA(data);
+       return 0;
+}
+
+static int smc911x_ethtool_geteeprom(struct net_device *dev,
+                                                                         struct ethtool_eeprom *eeprom, u8 *data)
+{
+       u8 eebuf[SMC911X_EEPROM_LEN];
+       int i, ret;
+
+       for(i=0;i<SMC911X_EEPROM_LEN;i++) {
+               if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ_, i ))!=0)
+                       return ret;
+               if ((ret=smc911x_ethtool_read_eeprom_byte(dev, &eebuf[i]))!=0)
+                       return ret;
+               }
+       memcpy(data, eebuf+eeprom->offset, eeprom->len);
+       return 0;
+}
+
+static int smc911x_ethtool_seteeprom(struct net_device *dev,
+                                                                          struct ethtool_eeprom *eeprom, u8 *data)
+{
+       int i, ret;
+
+       /* Enable erase */
+       if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN_, 0 ))!=0)
+               return ret;
+       for(i=eeprom->offset;i<(eeprom->offset+eeprom->len);i++) {
+               /* erase byte */
+               if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE_, i ))!=0)
+                       return ret;
+               /* write byte */
+               if ((ret=smc911x_ethtool_write_eeprom_byte(dev, *data))!=0)
+                        return ret;
+               if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE_, i ))!=0)
+                       return ret;
+               }
+        return 0;
+}
+
+static int smc911x_ethtool_geteeprom_len(struct net_device *dev)
+{
+        return SMC911X_EEPROM_LEN;
+}
+
+static struct ethtool_ops smc911x_ethtool_ops = {
+       .get_settings    = smc911x_ethtool_getsettings,
+       .set_settings    = smc911x_ethtool_setsettings,
+       .get_drvinfo     = smc911x_ethtool_getdrvinfo,
+       .get_msglevel    = smc911x_ethtool_getmsglevel,
+       .set_msglevel    = smc911x_ethtool_setmsglevel,
+       .nway_reset = smc911x_ethtool_nwayreset,
+       .get_link        = ethtool_op_get_link,
+       .get_regs_len    = smc911x_ethtool_getregslen,
+       .get_regs        = smc911x_ethtool_getregs,
+       .get_eeprom_len = smc911x_ethtool_geteeprom_len,
+       .get_eeprom = smc911x_ethtool_geteeprom,
+       .set_eeprom = smc911x_ethtool_seteeprom,
+};
+
+/*
+ * smc911x_findirq
+ *
+ * This routine has a simple purpose -- make the SMC chip generate an
+ * interrupt, so an auto-detect routine can detect it, and find the IRQ,
+ */
+static int __init smc911x_findirq(unsigned long ioaddr)
+{
+       int timeout = 20;
+       unsigned long cookie;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+
+       cookie = probe_irq_on();
+
+       /*
+        * Force a SW interrupt
+        */
+
+       SMC_SET_INT_EN(INT_EN_SW_INT_EN_);
+
+       /*
+        * Wait until positive that the interrupt has been generated
+        */
+       do {
+               int int_status;
+               udelay(10);
+               int_status = SMC_GET_INT_EN();
+               if (int_status & INT_EN_SW_INT_EN_)
+                        break;         /* got the interrupt */
+       } while (--timeout);
+
+       /*
+        * there is really nothing that I can do here if timeout fails,
+        * as autoirq_report will return a 0 anyway, which is what I
+        * want in this case.    Plus, the clean up is needed in both
+        * cases.
+        */
+
+       /* and disable all interrupts again */
+       SMC_SET_INT_EN(0);
+
+       /* and return what I found */
+       return probe_irq_off(cookie);
+}
+
+/*
+ * Function: smc911x_probe(unsigned long ioaddr)
+ *
+ * Purpose:
+ *      Tests to see if a given ioaddr points to an SMC911x chip.
+ *      Returns a 0 on success
+ *
+ * Algorithm:
+ *      (1) see if the endian word is OK
+ *      (1) see if I recognize the chip ID in the appropriate register
+ *
+ * Here I do typical initialization tasks.
+ *
+ * o  Initialize the structure if needed
+ * o  print out my vanity message if not done so already
+ * o  print out what type of hardware is detected
+ * o  print out the ethernet address
+ * o  find the IRQ
+ * o  set up my private data
+ * o  configure the dev structure with my subroutines
+ * o  actually GRAB the irq.
+ * o  GRAB the region
+ */
+static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       int i, retval;
+       unsigned int val, chip_id, revision;
+       const char *version_string;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /* First, see if the endian word is recognized */
+       val = SMC_GET_BYTE_TEST();
+       DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val);
+       if (val != 0x87654321) {
+               printk(KERN_ERR "Invalid chip endian 0x08%x\n",val);
+               retval = -ENODEV;
+               goto err_out;
+       }
+
+       /*
+        * check if the revision register is something that I
+        * recognize.   These might need to be added to later,
+        * as future revisions could be added.
+        */
+       chip_id = SMC_GET_PN();
+       DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id);
+       for(i=0;chip_ids[i].id != 0; i++) {
+               if (chip_ids[i].id == chip_id) break;
+       }
+       if (!chip_ids[i].id) {
+               printk(KERN_ERR "Unknown chip ID %04x\n", chip_id);
+               retval = -ENODEV;
+               goto err_out;
+       }
+       version_string = chip_ids[i].name;
+
+       revision = SMC_GET_REV();
+       DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision);
+
+       /* At this point I'll assume that the chip is an SMC911x. */
+       DBG(SMC_DEBUG_MISC, "%s: Found a %s\n", CARDNAME, chip_ids[i].name);
+
+       /* Validate the TX FIFO size requested */
+       if ((tx_fifo_kb < 2) || (tx_fifo_kb > 14)) {
+               printk(KERN_ERR "Invalid TX FIFO size requested %d\n", tx_fifo_kb);
+               retval = -EINVAL;
+               goto err_out;
+       }
+
+       /* fill in some of the fields */
+       dev->base_addr = ioaddr;
+       lp->version = chip_ids[i].id;
+       lp->revision = revision;
+       lp->tx_fifo_kb = tx_fifo_kb;
+       /* Reverse calculate the RX FIFO size from the TX */
+       lp->tx_fifo_size=(lp->tx_fifo_kb<<10) - 512;
+       lp->rx_fifo_size= ((0x4000 - 512 - lp->tx_fifo_size) / 16) * 15;
+
+       /* Set the automatic flow control values */
+       switch(lp->tx_fifo_kb) {
+               /*
+                *       AFC_HI is about ((Rx Data Fifo Size)*2/3)/64
+                *       AFC_LO is AFC_HI/2
+                *       BACK_DUR is about 5uS*(AFC_LO) rounded down
+                */
+               case 2:/* 13440 Rx Data Fifo Size */
+                       lp->afc_cfg=0x008C46AF;break;
+               case 3:/* 12480 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0082419F;break;
+               case 4:/* 11520 Rx Data Fifo Size */
+                       lp->afc_cfg=0x00783C9F;break;
+               case 5:/* 10560 Rx Data Fifo Size */
+                       lp->afc_cfg=0x006E374F;break;
+               case 6:/* 9600 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0064328F;break;
+               case 7:/* 8640 Rx Data Fifo Size */
+                       lp->afc_cfg=0x005A2D7F;break;
+               case 8:/* 7680 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0050287F;break;
+               case 9:/* 6720 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0046236F;break;
+               case 10:/* 5760 Rx Data Fifo Size */
+                       lp->afc_cfg=0x003C1E6F;break;
+               case 11:/* 4800 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0032195F;break;
+               /*
+                *       AFC_HI is ~1520 bytes less than RX Data Fifo Size
+                *       AFC_LO is AFC_HI/2
+                *       BACK_DUR is about 5uS*(AFC_LO) rounded down
+                */
+               case 12:/* 3840 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0024124F;break;
+               case 13:/* 2880 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0015073F;break;
+               case 14:/* 1920 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0006032F;break;
+                default:
+                        PRINTK("%s: ERROR -- no AFC_CFG setting found",
+                               dev->name);
+                        break;
+       }
+
+       DBG(SMC_DEBUG_MISC | SMC_DEBUG_TX | SMC_DEBUG_RX,
+               "%s: tx_fifo %d rx_fifo %d afc_cfg 0x%08x\n", CARDNAME,
+               lp->tx_fifo_size, lp->rx_fifo_size, lp->afc_cfg);
+
+       spin_lock_init(&lp->lock);
+
+       /* Get the MAC address */
+       SMC_GET_MAC_ADDR(dev->dev_addr);
+
+       /* now, reset the chip, and put it into a known state */
+       smc911x_reset(dev);
+
+       /*
+        * If dev->irq is 0, then the device has to be banged on to see
+        * what the IRQ is.
+        *
+        * Specifying an IRQ is done with the assumption that the user knows
+        * what (s)he is doing.  No checking is done!!!!
+        */
+       if (dev->irq < 1) {
+               int trials;
+
+               trials = 3;
+               while (trials--) {
+                       dev->irq = smc911x_findirq(ioaddr);
+                       if (dev->irq)
+                               break;
+                       /* kick the card and try again */
+                       smc911x_reset(dev);
+               }
+       }
+       if (dev->irq == 0) {
+               printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
+                       dev->name);
+               retval = -ENODEV;
+               goto err_out;
+       }
+       dev->irq = irq_canonicalize(dev->irq);
+
+       /* Fill in the fields of the device structure with ethernet values. */
+       ether_setup(dev);
+
+       dev->open = smc911x_open;
+       dev->stop = smc911x_close;
+       dev->hard_start_xmit = smc911x_hard_start_xmit;
+       dev->tx_timeout = smc911x_timeout;
+       dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+       dev->get_stats = smc911x_query_statistics;
+       dev->set_multicast_list = smc911x_set_multicast_list;
+       dev->ethtool_ops = &smc911x_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = smc911x_poll_controller;
+#endif
+
+       INIT_WORK(&lp->phy_configure, smc911x_phy_configure, dev);
+       lp->mii.phy_id_mask = 0x1f;
+       lp->mii.reg_num_mask = 0x1f;
+       lp->mii.force_media = 0;
+       lp->mii.full_duplex = 0;
+       lp->mii.dev = dev;
+       lp->mii.mdio_read = smc911x_phy_read;
+       lp->mii.mdio_write = smc911x_phy_write;
+
+       /*
+        * Locate the phy, if any.
+        */
+       smc911x_phy_detect(dev);
+
+       /* Set default parameters */
+       lp->msg_enable = NETIF_MSG_LINK;
+       lp->ctl_rfduplx = 1;
+       lp->ctl_rspeed = 100;
+
+       /* Grab the IRQ */
+       retval = request_irq(dev->irq, &smc911x_interrupt, IRQF_SHARED, dev->name, dev);
+       if (retval)
+               goto err_out;
+
+       set_irq_type(dev->irq, IRQT_FALLING);
+
+#ifdef SMC_USE_DMA
+       lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq);
+       lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq);
+       lp->rxdma_active = 0;
+       lp->txdma_active = 0;
+       dev->dma = lp->rxdma;
+#endif
+
+       retval = register_netdev(dev);
+       if (retval == 0) {
+               /* now, print out the card info, in a short format.. */
+               printk("%s: %s (rev %d) at %#lx IRQ %d",
+                       dev->name, version_string, lp->revision,
+                       dev->base_addr, dev->irq);
+
+#ifdef SMC_USE_DMA
+               if (lp->rxdma != -1)
+                       printk(" RXDMA %d ", lp->rxdma);
+
+               if (lp->txdma != -1)
+                       printk("TXDMA %d", lp->txdma);
+#endif
+               printk("\n");
+               if (!is_valid_ether_addr(dev->dev_addr)) {
+                       printk("%s: Invalid ethernet MAC address. Please "
+                                       "set using ifconfig\n", dev->name);
+               } else {
+                       /* Print the Ethernet address */
+                       printk("%s: Ethernet addr: ", dev->name);
+                       for (i = 0; i < 5; i++)
+                               printk("%2.2x:", dev->dev_addr[i]);
+                       printk("%2.2x\n", dev->dev_addr[5]);
+               }
+
+               if (lp->phy_type == 0) {
+                       PRINTK("%s: No PHY found\n", dev->name);
+               } else if ((lp->phy_type & ~0xff) == LAN911X_INTERNAL_PHY_ID) {
+                       PRINTK("%s: LAN911x Internal PHY\n", dev->name);
+               } else {
+                       PRINTK("%s: External PHY 0x%08x\n", dev->name, lp->phy_type);
+               }
+       }
+
+err_out:
+#ifdef SMC_USE_DMA
+       if (retval) {
+               if (lp->rxdma != -1) {
+                       SMC_DMA_FREE(dev, lp->rxdma);
+               }
+               if (lp->txdma != -1) {
+                       SMC_DMA_FREE(dev, lp->txdma);
+               }
+       }
+#endif
+       return retval;
+}
+
+/*
+ * smc911x_init(void)
+ *
+ *       Output:
+ *      0 --> there is a device
+ *      anything else, error
+ */
+static int smc911x_drv_probe(struct platform_device *pdev)
+{
+       struct net_device *ndev;
+       struct resource *res;
+       unsigned int *addr;
+       int ret;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n",  __FUNCTION__);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /*
+        * Request the regions.
+        */
+       if (!request_mem_region(res->start, SMC911X_IO_EXTENT, CARDNAME)) {
+                ret = -EBUSY;
+                goto out;
+       }
+
+       ndev = alloc_etherdev(sizeof(struct smc911x_local));
+       if (!ndev) {
+               printk("%s: could not allocate device.\n", CARDNAME);
+               ret = -ENOMEM;
+               goto release_1;
+       }
+       SET_MODULE_OWNER(ndev);
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       ndev->dma = (unsigned char)-1;
+       ndev->irq = platform_get_irq(pdev, 0);
+
+       addr = ioremap(res->start, SMC911X_IO_EXTENT);
+       if (!addr) {
+               ret = -ENOMEM;
+               goto release_both;
+       }
+
+       platform_set_drvdata(pdev, ndev);
+       ret = smc911x_probe(ndev, (unsigned long)addr);
+       if (ret != 0) {
+               platform_set_drvdata(pdev, NULL);
+               iounmap(addr);
+release_both:
+               free_netdev(ndev);
+release_1:
+               release_mem_region(res->start, SMC911X_IO_EXTENT);
+out:
+               printk("%s: not found (%d).\n", CARDNAME, ret);
+       }
+#ifdef SMC_USE_DMA
+       else {
+               struct smc911x_local *lp = netdev_priv(ndev);
+               lp->physaddr = res->start;
+               lp->dev = &pdev->dev;
+       }
+#endif
+
+       return ret;
+}
+
+static int smc911x_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+       platform_set_drvdata(pdev, NULL);
+
+       unregister_netdev(ndev);
+
+       free_irq(ndev->irq, ndev);
+
+#ifdef SMC_USE_DMA
+       {
+               struct smc911x_local *lp = netdev_priv(ndev);
+               if (lp->rxdma != -1) {
+                       SMC_DMA_FREE(dev, lp->rxdma);
+               }
+               if (lp->txdma != -1) {
+                       SMC_DMA_FREE(dev, lp->txdma);
+               }
+       }
+#endif
+       iounmap((void *)ndev->base_addr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, SMC911X_IO_EXTENT);
+
+       free_netdev(ndev);
+       return 0;
+}
+
+static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+       unsigned long ioaddr = ndev->base_addr;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+       if (ndev) {
+               if (netif_running(ndev)) {
+                       netif_device_detach(ndev);
+                       smc911x_shutdown(ndev);
+#if POWER_DOWN
+                       /* Set D2 - Energy detect only setting */
+                       SMC_SET_PMT_CTRL(2<<12);
+#endif
+               }
+       }
+       return 0;
+}
+
+static int smc911x_drv_resume(struct platform_device *dev)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+       if (ndev) {
+               struct smc911x_local *lp = netdev_priv(ndev);
+
+               if (netif_running(ndev)) {
+                       smc911x_reset(ndev);
+                       smc911x_enable(ndev);
+                       if (lp->phy_type != 0)
+                               smc911x_phy_configure(ndev);
+                       netif_device_attach(ndev);
+               }
+       }
+       return 0;
+}
+
+static struct platform_driver smc911x_driver = {
+       .probe           = smc911x_drv_probe,
+       .remove  = smc911x_drv_remove,
+       .suspend         = smc911x_drv_suspend,
+       .resume  = smc911x_drv_resume,
+       .driver  = {
+               .name    = CARDNAME,
+       },
+};
+
+static int __init smc911x_init(void)
+{
+       return platform_driver_register(&smc911x_driver);
+}
+
+static void __exit smc911x_cleanup(void)
+{
+       platform_driver_unregister(&smc911x_driver);
+}
+
+module_init(smc911x_init);
+module_exit(smc911x_cleanup);
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
new file mode 100644 (file)
index 0000000..962a710
--- /dev/null
@@ -0,0 +1,835 @@
+/*------------------------------------------------------------------------
+ . smc911x.h - macros for SMSC's LAN911{5,6,7,8} single-chip Ethernet device.
+ .
+ . Copyright (C) 2005 Sensoria Corp.
+ . Derived from the unified SMC91x driver by Nicolas Pitre
+ .
+ . This program is free software; you can redistribute it and/or modify
+ . it under the terms of the GNU General Public License as published by
+ . the Free Software Foundation; either version 2 of the License, or
+ . (at your option) any later version.
+ .
+ . This program is distributed in the hope that it will be useful,
+ . but WITHOUT ANY WARRANTY; without even the implied warranty of
+ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ . GNU 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
+ .
+ . Information contained in this file was obtained from the LAN9118
+ . manual from SMC.  To get a copy, if you really want one, you can find
+ . information under www.smsc.com.
+ .
+ . Authors
+ .      Dustin McIntire                 <dustin@sensoria.com>
+ .
+ ---------------------------------------------------------------------------*/
+#ifndef _SMC911X_H_
+#define _SMC911X_H_
+
+/*
+ * Use the DMA feature on PXA chips
+ */
+#ifdef CONFIG_ARCH_PXA
+  #define SMC_USE_PXA_DMA      1
+  #define SMC_USE_16BIT                0
+  #define SMC_USE_32BIT                1
+#endif
+
+
+/*
+ * Define the bus width specific IO macros
+ */
+
+#if    SMC_USE_16BIT
+#define SMC_inb(a, r)                   readb((a) + (r))
+#define SMC_inw(a, r)                   readw((a) + (r))
+#define SMC_inl(a, r)                   ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16))
+#define SMC_outb(v, a, r)               writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)               writew(v, (a) + (r))
+#define SMC_outl(v, a, r)                       \
+       do{                                      \
+                writel(v & 0xFFFF, (a) + (r));  \
+                writel(v >> 16, (a) + (r) + 2); \
+        } while (0)
+#define SMC_insl(a, r, p, l)    readsw((short*)((a) + (r)), p, l*2)
+#define SMC_outsl(a, r, p, l)   writesw((short*)((a) + (r)), p, l*2)
+
+#elif  SMC_USE_32BIT
+#define SMC_inb(a, r)           readb((a) + (r))
+#define SMC_inw(a, r)           readw((a) + (r))
+#define SMC_inl(a, r)           readl((a) + (r))
+#define SMC_outb(v, a, r)       writeb(v, (a) + (r))
+#define SMC_outl(v, a, r)       writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)    readsl((int*)((a) + (r)), p, l)
+#define SMC_outsl(a, r, p, l)   writesl((int*)((a) + (r)), p, l)
+
+#endif /* SMC_USE_16BIT */
+
+
+
+#if     SMC_USE_PXA_DMA
+#define SMC_USE_DMA
+
+/*
+ * Define the request and free functions
+ * These are unfortunately architecture specific as no generic allocation
+ * mechanism exits
+ */
+#define SMC_DMA_REQUEST(dev, handler) \
+        pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev)
+
+#define SMC_DMA_FREE(dev, dma) \
+        pxa_free_dma(dma)
+
+#define SMC_DMA_ACK_IRQ(dev, dma)                                      \
+{                                                                      \
+       if (DCSR(dma) & DCSR_BUSERR) {                                  \
+               printk("%s: DMA %d bus error!\n", dev->name, dma);      \
+       }                                                               \
+       DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;            \
+}
+
+/*
+ * Use a DMA for RX and TX packets.
+ */
+#include <linux/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/arch/pxa-regs.h>
+
+static dma_addr_t rx_dmabuf, tx_dmabuf;
+static int rx_dmalen, tx_dmalen;
+
+#ifdef SMC_insl
+#undef SMC_insl
+#define SMC_insl(a, r, p, l) \
+       smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+
+static inline void
+smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr,
+               int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       if ((long)buf & 4) {
+               *((u32 *)buf) = SMC_inl(ioaddr, reg);
+               buf += 4;
+               len--;
+       }
+
+       len *= 4;
+       rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+       rx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DTADR(dma) = rx_dmabuf;
+       DSADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+               DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_insw
+#undef SMC_insw
+#define SMC_insw(a, r, p, l) \
+       smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+
+static inline void
+smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr,
+               int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       while ((long)buf & 6) {
+               *((u16 *)buf) = SMC_inw(ioaddr, reg);
+               buf += 2;
+               len--;
+       }
+
+       len *= 2;
+       rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+       rx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DTADR(dma) = rx_dmabuf;
+       DSADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+               DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_outsl
+#undef SMC_outsl
+#define SMC_outsl(a, r, p, l) \
+        smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+
+static inline void
+smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr,
+               int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       if ((long)buf & 4) {
+               SMC_outl(*((u32 *)buf), ioaddr, reg);
+               buf += 4;
+               len--;
+       }
+
+       len *= 4;
+       tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+       tx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DSADR(dma) = tx_dmabuf;
+       DTADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
+               DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_outsw
+#undef SMC_outsw
+#define SMC_outsw(a, r, p, l) \
+       smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+
+static inline void
+smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr,
+                 int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       while ((long)buf & 6) {
+               SMC_outw(*((u16 *)buf), ioaddr, reg);
+               buf += 2;
+               len--;
+       }
+
+       len *= 2;
+       tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+       tx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DSADR(dma) = tx_dmabuf;
+       DTADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
+               DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#endif  /* SMC_USE_PXA_DMA */
+
+
+/* Chip Parameters and Register Definitions */
+
+#define SMC911X_TX_FIFO_LOW_THRESHOLD  (1536*2)
+
+#define SMC911X_IO_EXTENT       0x100
+
+#define SMC911X_EEPROM_LEN      7
+
+/* Below are the register offsets and bit definitions
+ * of the Lan911x memory space
+ */
+#define RX_DATA_FIFO            (0x00)
+
+#define TX_DATA_FIFO            (0x20)
+#define        TX_CMD_A_INT_ON_COMP_           (0x80000000)
+#define        TX_CMD_A_INT_BUF_END_ALGN_      (0x03000000)
+#define        TX_CMD_A_INT_4_BYTE_ALGN_       (0x00000000)
+#define        TX_CMD_A_INT_16_BYTE_ALGN_      (0x01000000)
+#define        TX_CMD_A_INT_32_BYTE_ALGN_      (0x02000000)
+#define        TX_CMD_A_INT_DATA_OFFSET_       (0x001F0000)
+#define        TX_CMD_A_INT_FIRST_SEG_         (0x00002000)
+#define        TX_CMD_A_INT_LAST_SEG_          (0x00001000)
+#define        TX_CMD_A_BUF_SIZE_              (0x000007FF)
+#define        TX_CMD_B_PKT_TAG_               (0xFFFF0000)
+#define        TX_CMD_B_ADD_CRC_DISABLE_       (0x00002000)
+#define        TX_CMD_B_DISABLE_PADDING_       (0x00001000)
+#define        TX_CMD_B_PKT_BYTE_LENGTH_       (0x000007FF)
+
+#define RX_STATUS_FIFO         (0x40)
+#define        RX_STS_PKT_LEN_                 (0x3FFF0000)
+#define        RX_STS_ES_                      (0x00008000)
+#define        RX_STS_BCST_                    (0x00002000)
+#define        RX_STS_LEN_ERR_                 (0x00001000)
+#define        RX_STS_RUNT_ERR_                (0x00000800)
+#define        RX_STS_MCAST_                   (0x00000400)
+#define        RX_STS_TOO_LONG_                (0x00000080)
+#define        RX_STS_COLL_                    (0x00000040)
+#define        RX_STS_ETH_TYPE_                (0x00000020)
+#define        RX_STS_WDOG_TMT_                (0x00000010)
+#define        RX_STS_MII_ERR_                 (0x00000008)
+#define        RX_STS_DRIBBLING_               (0x00000004)
+#define        RX_STS_CRC_ERR_                 (0x00000002)
+#define RX_STATUS_FIFO_PEEK    (0x44)
+#define TX_STATUS_FIFO         (0x48)
+#define        TX_STS_TAG_                     (0xFFFF0000)
+#define        TX_STS_ES_                      (0x00008000)
+#define        TX_STS_LOC_                     (0x00000800)
+#define        TX_STS_NO_CARR_                 (0x00000400)
+#define        TX_STS_LATE_COLL_               (0x00000200)
+#define        TX_STS_MANY_COLL_               (0x00000100)
+#define        TX_STS_COLL_CNT_                (0x00000078)
+#define        TX_STS_MANY_DEFER_              (0x00000004)
+#define        TX_STS_UNDERRUN_                (0x00000002)
+#define        TX_STS_DEFERRED_                (0x00000001)
+#define TX_STATUS_FIFO_PEEK    (0x4C)
+#define ID_REV                 (0x50)
+#define        ID_REV_CHIP_ID_                 (0xFFFF0000)  /* RO */
+#define        ID_REV_REV_ID_                  (0x0000FFFF)  /* RO */
+
+#define INT_CFG                        (0x54)
+#define        INT_CFG_INT_DEAS_               (0xFF000000)  /* R/W */
+#define        INT_CFG_INT_DEAS_CLR_           (0x00004000)
+#define        INT_CFG_INT_DEAS_STS_           (0x00002000)
+#define        INT_CFG_IRQ_INT_                (0x00001000)  /* RO */
+#define        INT_CFG_IRQ_EN_                 (0x00000100)  /* R/W */
+#define        INT_CFG_IRQ_POL_                (0x00000010)  /* R/W Not Affected by SW Reset */
+#define        INT_CFG_IRQ_TYPE_               (0x00000001)  /* R/W Not Affected by SW Reset */
+
+#define INT_STS                        (0x58)
+#define        INT_STS_SW_INT_                 (0x80000000)  /* R/WC */
+#define        INT_STS_TXSTOP_INT_             (0x02000000)  /* R/WC */
+#define        INT_STS_RXSTOP_INT_             (0x01000000)  /* R/WC */
+#define        INT_STS_RXDFH_INT_              (0x00800000)  /* R/WC */
+#define        INT_STS_RXDF_INT_               (0x00400000)  /* R/WC */
+#define        INT_STS_TX_IOC_                 (0x00200000)  /* R/WC */
+#define        INT_STS_RXD_INT_                (0x00100000)  /* R/WC */
+#define        INT_STS_GPT_INT_                (0x00080000)  /* R/WC */
+#define        INT_STS_PHY_INT_                (0x00040000)  /* RO */
+#define        INT_STS_PME_INT_                (0x00020000)  /* R/WC */
+#define        INT_STS_TXSO_                   (0x00010000)  /* R/WC */
+#define        INT_STS_RWT_                    (0x00008000)  /* R/WC */
+#define        INT_STS_RXE_                    (0x00004000)  /* R/WC */
+#define        INT_STS_TXE_                    (0x00002000)  /* R/WC */
+//#define      INT_STS_ERX_            (0x00001000)  /* R/WC */
+#define        INT_STS_TDFU_                   (0x00000800)  /* R/WC */
+#define        INT_STS_TDFO_                   (0x00000400)  /* R/WC */
+#define        INT_STS_TDFA_                   (0x00000200)  /* R/WC */
+#define        INT_STS_TSFF_                   (0x00000100)  /* R/WC */
+#define        INT_STS_TSFL_                   (0x00000080)  /* R/WC */
+//#define      INT_STS_RXDF_           (0x00000040)  /* R/WC */
+#define        INT_STS_RDFO_                   (0x00000040)  /* R/WC */
+#define        INT_STS_RDFL_                   (0x00000020)  /* R/WC */
+#define        INT_STS_RSFF_                   (0x00000010)  /* R/WC */
+#define        INT_STS_RSFL_                   (0x00000008)  /* R/WC */
+#define        INT_STS_GPIO2_INT_              (0x00000004)  /* R/WC */
+#define        INT_STS_GPIO1_INT_              (0x00000002)  /* R/WC */
+#define        INT_STS_GPIO0_INT_              (0x00000001)  /* R/WC */
+
+#define INT_EN                 (0x5C)
+#define        INT_EN_SW_INT_EN_               (0x80000000)  /* R/W */
+#define        INT_EN_TXSTOP_INT_EN_           (0x02000000)  /* R/W */
+#define        INT_EN_RXSTOP_INT_EN_           (0x01000000)  /* R/W */
+#define        INT_EN_RXDFH_INT_EN_            (0x00800000)  /* R/W */
+//#define      INT_EN_RXDF_INT_EN_             (0x00400000)  /* R/W */
+#define        INT_EN_TIOC_INT_EN_             (0x00200000)  /* R/W */
+#define        INT_EN_RXD_INT_EN_              (0x00100000)  /* R/W */
+#define        INT_EN_GPT_INT_EN_              (0x00080000)  /* R/W */
+#define        INT_EN_PHY_INT_EN_              (0x00040000)  /* R/W */
+#define        INT_EN_PME_INT_EN_              (0x00020000)  /* R/W */
+#define        INT_EN_TXSO_EN_                 (0x00010000)  /* R/W */
+#define        INT_EN_RWT_EN_                  (0x00008000)  /* R/W */
+#define        INT_EN_RXE_EN_                  (0x00004000)  /* R/W */
+#define        INT_EN_TXE_EN_                  (0x00002000)  /* R/W */
+//#define      INT_EN_ERX_EN_                  (0x00001000)  /* R/W */
+#define        INT_EN_TDFU_EN_                 (0x00000800)  /* R/W */
+#define        INT_EN_TDFO_EN_                 (0x00000400)  /* R/W */
+#define        INT_EN_TDFA_EN_                 (0x00000200)  /* R/W */
+#define        INT_EN_TSFF_EN_                 (0x00000100)  /* R/W */
+#define        INT_EN_TSFL_EN_                 (0x00000080)  /* R/W */
+//#define      INT_EN_RXDF_EN_                 (0x00000040)  /* R/W */
+#define        INT_EN_RDFO_EN_                 (0x00000040)  /* R/W */
+#define        INT_EN_RDFL_EN_                 (0x00000020)  /* R/W */
+#define        INT_EN_RSFF_EN_                 (0x00000010)  /* R/W */
+#define        INT_EN_RSFL_EN_                 (0x00000008)  /* R/W */
+#define        INT_EN_GPIO2_INT_               (0x00000004)  /* R/W */
+#define        INT_EN_GPIO1_INT_               (0x00000002)  /* R/W */
+#define        INT_EN_GPIO0_INT_               (0x00000001)  /* R/W */
+
+#define BYTE_TEST              (0x64)
+#define FIFO_INT               (0x68)
+#define        FIFO_INT_TX_AVAIL_LEVEL_        (0xFF000000)  /* R/W */
+#define        FIFO_INT_TX_STS_LEVEL_          (0x00FF0000)  /* R/W */
+#define        FIFO_INT_RX_AVAIL_LEVEL_        (0x0000FF00)  /* R/W */
+#define        FIFO_INT_RX_STS_LEVEL_          (0x000000FF)  /* R/W */
+
+#define RX_CFG                 (0x6C)
+#define        RX_CFG_RX_END_ALGN_             (0xC0000000)  /* R/W */
+#define                RX_CFG_RX_END_ALGN4_            (0x00000000)  /* R/W */
+#define                RX_CFG_RX_END_ALGN16_           (0x40000000)  /* R/W */
+#define                RX_CFG_RX_END_ALGN32_           (0x80000000)  /* R/W */
+#define        RX_CFG_RX_DMA_CNT_              (0x0FFF0000)  /* R/W */
+#define        RX_CFG_RX_DUMP_                 (0x00008000)  /* R/W */
+#define        RX_CFG_RXDOFF_                  (0x00001F00)  /* R/W */
+//#define      RX_CFG_RXBAD_                   (0x00000001)  /* R/W */
+
+#define TX_CFG                 (0x70)
+//#define      TX_CFG_TX_DMA_LVL_              (0xE0000000)     /* R/W */
+//#define      TX_CFG_TX_DMA_CNT_              (0x0FFF0000)     /* R/W Self Clearing */
+#define        TX_CFG_TXS_DUMP_                (0x00008000)  /* Self Clearing */
+#define        TX_CFG_TXD_DUMP_                (0x00004000)  /* Self Clearing */
+#define        TX_CFG_TXSAO_                   (0x00000004)  /* R/W */
+#define        TX_CFG_TX_ON_                   (0x00000002)  /* R/W */
+#define        TX_CFG_STOP_TX_                 (0x00000001)  /* Self Clearing */
+
+#define HW_CFG                 (0x74)
+#define        HW_CFG_TTM_                     (0x00200000)  /* R/W */
+#define        HW_CFG_SF_                      (0x00100000)  /* R/W */
+#define        HW_CFG_TX_FIF_SZ_               (0x000F0000)  /* R/W */
+#define        HW_CFG_TR_                      (0x00003000)  /* R/W */
+#define        HW_CFG_PHY_CLK_SEL_             (0x00000060)  /* R/W */
+#define                 HW_CFG_PHY_CLK_SEL_INT_PHY_    (0x00000000) /* R/W */
+#define                 HW_CFG_PHY_CLK_SEL_EXT_PHY_    (0x00000020) /* R/W */
+#define                 HW_CFG_PHY_CLK_SEL_CLK_DIS_    (0x00000040) /* R/W */
+#define        HW_CFG_SMI_SEL_                 (0x00000010)  /* R/W */
+#define        HW_CFG_EXT_PHY_DET_             (0x00000008)  /* RO */
+#define        HW_CFG_EXT_PHY_EN_              (0x00000004)  /* R/W */
+#define        HW_CFG_32_16_BIT_MODE_          (0x00000004)  /* RO */
+#define        HW_CFG_SRST_TO_                 (0x00000002)  /* RO */
+#define        HW_CFG_SRST_                    (0x00000001)  /* Self Clearing */
+
+#define RX_DP_CTRL             (0x78)
+#define        RX_DP_CTRL_RX_FFWD_             (0x80000000)  /* R/W */
+#define        RX_DP_CTRL_FFWD_BUSY_           (0x80000000)  /* RO */
+
+#define RX_FIFO_INF            (0x7C)
+#define         RX_FIFO_INF_RXSUSED_           (0x00FF0000)  /* RO */
+#define         RX_FIFO_INF_RXDUSED_           (0x0000FFFF)  /* RO */
+
+#define TX_FIFO_INF            (0x80)
+#define        TX_FIFO_INF_TSUSED_             (0x00FF0000)  /* RO */
+#define        TX_FIFO_INF_TDFREE_             (0x0000FFFF)  /* RO */
+
+#define PMT_CTRL               (0x84)
+#define        PMT_CTRL_PM_MODE_               (0x00003000)  /* Self Clearing */
+#define        PMT_CTRL_PHY_RST_               (0x00000400)  /* Self Clearing */
+#define        PMT_CTRL_WOL_EN_                (0x00000200)  /* R/W */
+#define        PMT_CTRL_ED_EN_                 (0x00000100)  /* R/W */
+#define        PMT_CTRL_PME_TYPE_              (0x00000040)  /* R/W Not Affected by SW Reset */
+#define        PMT_CTRL_WUPS_                  (0x00000030)  /* R/WC */
+#define                PMT_CTRL_WUPS_NOWAKE_           (0x00000000)  /* R/WC */
+#define                PMT_CTRL_WUPS_ED_               (0x00000010)  /* R/WC */
+#define                PMT_CTRL_WUPS_WOL_              (0x00000020)  /* R/WC */
+#define                PMT_CTRL_WUPS_MULTI_            (0x00000030)  /* R/WC */
+#define        PMT_CTRL_PME_IND_               (0x00000008)  /* R/W */
+#define        PMT_CTRL_PME_POL_               (0x00000004)  /* R/W */
+#define        PMT_CTRL_PME_EN_                (0x00000002)  /* R/W Not Affected by SW Reset */
+#define        PMT_CTRL_READY_                 (0x00000001)  /* RO */
+
+#define GPIO_CFG               (0x88)
+#define        GPIO_CFG_LED3_EN_               (0x40000000)  /* R/W */
+#define        GPIO_CFG_LED2_EN_               (0x20000000)  /* R/W */
+#define        GPIO_CFG_LED1_EN_               (0x10000000)  /* R/W */
+#define        GPIO_CFG_GPIO2_INT_POL_         (0x04000000)  /* R/W */
+#define        GPIO_CFG_GPIO1_INT_POL_         (0x02000000)  /* R/W */
+#define        GPIO_CFG_GPIO0_INT_POL_         (0x01000000)  /* R/W */
+#define        GPIO_CFG_EEPR_EN_               (0x00700000)  /* R/W */
+#define        GPIO_CFG_GPIOBUF2_              (0x00040000)  /* R/W */
+#define        GPIO_CFG_GPIOBUF1_              (0x00020000)  /* R/W */
+#define        GPIO_CFG_GPIOBUF0_              (0x00010000)  /* R/W */
+#define        GPIO_CFG_GPIODIR2_              (0x00000400)  /* R/W */
+#define        GPIO_CFG_GPIODIR1_              (0x00000200)  /* R/W */
+#define        GPIO_CFG_GPIODIR0_              (0x00000100)  /* R/W */
+#define        GPIO_CFG_GPIOD4_                (0x00000010)  /* R/W */
+#define        GPIO_CFG_GPIOD3_                (0x00000008)  /* R/W */
+#define        GPIO_CFG_GPIOD2_                (0x00000004)  /* R/W */
+#define        GPIO_CFG_GPIOD1_                (0x00000002)  /* R/W */
+#define        GPIO_CFG_GPIOD0_                (0x00000001)  /* R/W */
+
+#define GPT_CFG                        (0x8C)
+#define        GPT_CFG_TIMER_EN_               (0x20000000)  /* R/W */
+#define        GPT_CFG_GPT_LOAD_               (0x0000FFFF)  /* R/W */
+
+#define GPT_CNT                        (0x90)
+#define        GPT_CNT_GPT_CNT_                (0x0000FFFF)  /* RO */
+
+#define ENDIAN                 (0x98)
+#define FREE_RUN               (0x9C)
+#define RX_DROP                        (0xA0)
+#define MAC_CSR_CMD            (0xA4)
+#define         MAC_CSR_CMD_CSR_BUSY_          (0x80000000)  /* Self Clearing */
+#define         MAC_CSR_CMD_R_NOT_W_           (0x40000000)  /* R/W */
+#define         MAC_CSR_CMD_CSR_ADDR_          (0x000000FF)  /* R/W */
+
+#define MAC_CSR_DATA           (0xA8)
+#define AFC_CFG                        (0xAC)
+#define                AFC_CFG_AFC_HI_                 (0x00FF0000)  /* R/W */
+#define                AFC_CFG_AFC_LO_                 (0x0000FF00)  /* R/W */
+#define                AFC_CFG_BACK_DUR_               (0x000000F0)  /* R/W */
+#define                AFC_CFG_FCMULT_                 (0x00000008)  /* R/W */
+#define                AFC_CFG_FCBRD_                  (0x00000004)  /* R/W */
+#define                AFC_CFG_FCADD_                  (0x00000002)  /* R/W */
+#define                AFC_CFG_FCANY_                  (0x00000001)  /* R/W */
+
+#define E2P_CMD                        (0xB0)
+#define        E2P_CMD_EPC_BUSY_               (0x80000000)  /* Self Clearing */
+#define        E2P_CMD_EPC_CMD_                        (0x70000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_READ_           (0x00000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_EWDS_           (0x10000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_EWEN_           (0x20000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_WRITE_          (0x30000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_WRAL_           (0x40000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_ERASE_          (0x50000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_ERAL_           (0x60000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_RELOAD_         (0x70000000)  /* R/W */
+#define        E2P_CMD_EPC_TIMEOUT_            (0x00000200)  /* RO */
+#define        E2P_CMD_MAC_ADDR_LOADED_        (0x00000100)  /* RO */
+#define        E2P_CMD_EPC_ADDR_               (0x000000FF)  /* R/W */
+
+#define E2P_DATA               (0xB4)
+#define        E2P_DATA_EEPROM_DATA_           (0x000000FF)  /* R/W */
+/* end of LAN register offsets and bit definitions */
+
+/*
+ ****************************************************************************
+ ****************************************************************************
+ * MAC Control and Status Register (Indirect Address)
+ * Offset (through the MAC_CSR CMD and DATA port)
+ ****************************************************************************
+ ****************************************************************************
+ *
+ */
+#define MAC_CR                 (0x01)  /* R/W */
+
+/* MAC_CR - MAC Control Register */
+#define MAC_CR_RXALL_                  (0x80000000)
+// TODO: delete this bit? It is not described in the data sheet.
+#define MAC_CR_HBDIS_                  (0x10000000)
+#define MAC_CR_RCVOWN_                 (0x00800000)
+#define MAC_CR_LOOPBK_                 (0x00200000)
+#define MAC_CR_FDPX_                   (0x00100000)
+#define MAC_CR_MCPAS_                  (0x00080000)
+#define MAC_CR_PRMS_                   (0x00040000)
+#define MAC_CR_INVFILT_                        (0x00020000)
+#define MAC_CR_PASSBAD_                        (0x00010000)
+#define MAC_CR_HFILT_                  (0x00008000)
+#define MAC_CR_HPFILT_                 (0x00002000)
+#define MAC_CR_LCOLL_                  (0x00001000)
+#define MAC_CR_BCAST_                  (0x00000800)
+#define MAC_CR_DISRTY_                 (0x00000400)
+#define MAC_CR_PADSTR_                 (0x00000100)
+#define MAC_CR_BOLMT_MASK_             (0x000000C0)
+#define MAC_CR_DFCHK_                  (0x00000020)
+#define MAC_CR_TXEN_                   (0x00000008)
+#define MAC_CR_RXEN_                   (0x00000004)
+
+#define ADDRH                  (0x02)    /* R/W mask 0x0000FFFFUL */
+#define ADDRL                  (0x03)    /* R/W mask 0xFFFFFFFFUL */
+#define HASHH                  (0x04)    /* R/W */
+#define HASHL                  (0x05)    /* R/W */
+
+#define MII_ACC                        (0x06)    /* R/W */
+#define MII_ACC_PHY_ADDR_              (0x0000F800)
+#define MII_ACC_MIIRINDA_              (0x000007C0)
+#define MII_ACC_MII_WRITE_             (0x00000002)
+#define MII_ACC_MII_BUSY_              (0x00000001)
+
+#define MII_DATA               (0x07)    /* R/W mask 0x0000FFFFUL */
+
+#define FLOW                   (0x08)    /* R/W */
+#define FLOW_FCPT_                     (0xFFFF0000)
+#define FLOW_FCPASS_                   (0x00000004)
+#define FLOW_FCEN_                     (0x00000002)
+#define FLOW_FCBSY_                    (0x00000001)
+
+#define VLAN1                  (0x09)    /* R/W mask 0x0000FFFFUL */
+#define VLAN1_VTI1_                    (0x0000ffff)
+
+#define VLAN2                  (0x0A)    /* R/W mask 0x0000FFFFUL */
+#define VLAN2_VTI2_                    (0x0000ffff)
+
+#define WUFF                   (0x0B)    /* WO */
+
+#define WUCSR                  (0x0C)    /* R/W */
+#define WUCSR_GUE_                     (0x00000200)
+#define WUCSR_WUFR_                    (0x00000040)
+#define WUCSR_MPR_                     (0x00000020)
+#define WUCSR_WAKE_EN_                 (0x00000004)
+#define WUCSR_MPEN_                    (0x00000002)
+
+/*
+ ****************************************************************************
+ * Chip Specific MII Defines
+ ****************************************************************************
+ *
+ * Phy register offsets and bit definitions
+ *
+ */
+
+#define PHY_MODE_CTRL_STS      ((u32)17)       /* Mode Control/Status Register */
+//#define MODE_CTRL_STS_FASTRIP_         ((u16)0x4000)
+#define MODE_CTRL_STS_EDPWRDOWN_        ((u16)0x2000)
+//#define MODE_CTRL_STS_LOWSQEN_          ((u16)0x0800)
+//#define MODE_CTRL_STS_MDPREBP_          ((u16)0x0400)
+//#define MODE_CTRL_STS_FARLOOPBACK_  ((u16)0x0200)
+//#define MODE_CTRL_STS_FASTEST_          ((u16)0x0100)
+//#define MODE_CTRL_STS_REFCLKEN_         ((u16)0x0010)
+//#define MODE_CTRL_STS_PHYADBP_          ((u16)0x0008)
+//#define MODE_CTRL_STS_FORCE_G_LINK_ ((u16)0x0004)
+#define MODE_CTRL_STS_ENERGYON_                ((u16)0x0002)
+
+#define PHY_INT_SRC                    ((u32)29)
+#define PHY_INT_SRC_ENERGY_ON_                 ((u16)0x0080)
+#define PHY_INT_SRC_ANEG_COMP_                 ((u16)0x0040)
+#define PHY_INT_SRC_REMOTE_FAULT_              ((u16)0x0020)
+#define PHY_INT_SRC_LINK_DOWN_                 ((u16)0x0010)
+#define PHY_INT_SRC_ANEG_LP_ACK_               ((u16)0x0008)
+#define PHY_INT_SRC_PAR_DET_FAULT_             ((u16)0x0004)
+#define PHY_INT_SRC_ANEG_PGRX_                 ((u16)0x0002)
+
+#define PHY_INT_MASK                   ((u32)30)
+#define PHY_INT_MASK_ENERGY_ON_                        ((u16)0x0080)
+#define PHY_INT_MASK_ANEG_COMP_                        ((u16)0x0040)
+#define PHY_INT_MASK_REMOTE_FAULT_             ((u16)0x0020)
+#define PHY_INT_MASK_LINK_DOWN_                        ((u16)0x0010)
+#define PHY_INT_MASK_ANEG_LP_ACK_              ((u16)0x0008)
+#define PHY_INT_MASK_PAR_DET_FAULT_            ((u16)0x0004)
+#define PHY_INT_MASK_ANEG_PGRX_                        ((u16)0x0002)
+
+#define PHY_SPECIAL                    ((u32)31)
+#define PHY_SPECIAL_ANEG_DONE_                 ((u16)0x1000)
+#define PHY_SPECIAL_RES_                       ((u16)0x0040)
+#define PHY_SPECIAL_RES_MASK_                  ((u16)0x0FE1)
+#define PHY_SPECIAL_SPD_                       ((u16)0x001C)
+#define PHY_SPECIAL_SPD_10HALF_                        ((u16)0x0004)
+#define PHY_SPECIAL_SPD_10FULL_                        ((u16)0x0014)
+#define PHY_SPECIAL_SPD_100HALF_               ((u16)0x0008)
+#define PHY_SPECIAL_SPD_100FULL_               ((u16)0x0018)
+
+#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
+
+struct chip_id {
+       u16 id;
+       char *name;
+};
+
+static const struct chip_id chip_ids[] =  {
+       { CHIP_9115, "LAN9115" },
+       { CHIP_9116, "LAN9116" },
+       { CHIP_9117, "LAN9117" },
+       { CHIP_9118, "LAN9118" },
+       { 0, NULL },
+};
+
+#define IS_REV_A(x)    ((x & 0xFFFF)==0)
+
+/*
+ * Macros to abstract register access according to the data bus
+ * capabilities.  Please use those and not the in/out primitives.
+ */
+/* FIFO read/write macros */
+#define SMC_PUSH_DATA(p, l)    SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 )
+#define SMC_PULL_DATA(p, l)    SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 )
+#define SMC_SET_TX_FIFO(x)     SMC_outl( x, ioaddr, TX_DATA_FIFO )
+#define SMC_GET_RX_FIFO()      SMC_inl( ioaddr, RX_DATA_FIFO )
+
+
+/* I/O mapped register read/write macros */
+#define SMC_GET_TX_STS_FIFO()          SMC_inl( ioaddr, TX_STATUS_FIFO )
+#define SMC_GET_RX_STS_FIFO()          SMC_inl( ioaddr, RX_STATUS_FIFO )
+#define SMC_GET_RX_STS_FIFO_PEEK()     SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK )
+#define SMC_GET_PN()                   (SMC_inl( ioaddr, ID_REV ) >> 16)
+#define SMC_GET_REV()                  (SMC_inl( ioaddr, ID_REV ) & 0xFFFF)
+#define SMC_GET_IRQ_CFG()              SMC_inl( ioaddr, INT_CFG )
+#define SMC_SET_IRQ_CFG(x)             SMC_outl( x, ioaddr, INT_CFG )
+#define SMC_GET_INT()                  SMC_inl( ioaddr, INT_STS )
+#define SMC_ACK_INT(x)                 SMC_outl( x, ioaddr, INT_STS )
+#define SMC_GET_INT_EN()               SMC_inl( ioaddr, INT_EN )
+#define SMC_SET_INT_EN(x)              SMC_outl( x, ioaddr, INT_EN )
+#define SMC_GET_BYTE_TEST()            SMC_inl( ioaddr, BYTE_TEST )
+#define SMC_SET_BYTE_TEST(x)           SMC_outl( x, ioaddr, BYTE_TEST )
+#define SMC_GET_FIFO_INT()             SMC_inl( ioaddr, FIFO_INT )
+#define SMC_SET_FIFO_INT(x)            SMC_outl( x, ioaddr, FIFO_INT )
+#define SMC_SET_FIFO_TDA(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24);      \
+               SMC_SET_FIFO_INT( __mask | (x)<<24 );           \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_SET_FIFO_TSL(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16);      \
+               SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_SET_FIFO_RSA(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8);       \
+               SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8));  \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_SET_FIFO_RSL(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~0xFF;            \
+               SMC_SET_FIFO_INT( __mask | ((x) & 0xFF));       \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_GET_RX_CFG()               SMC_inl( ioaddr, RX_CFG )
+#define SMC_SET_RX_CFG(x)              SMC_outl( x, ioaddr, RX_CFG )
+#define SMC_GET_TX_CFG()               SMC_inl( ioaddr, TX_CFG )
+#define SMC_SET_TX_CFG(x)              SMC_outl( x, ioaddr, TX_CFG )
+#define SMC_GET_HW_CFG()               SMC_inl( ioaddr, HW_CFG )
+#define SMC_SET_HW_CFG(x)              SMC_outl( x, ioaddr, HW_CFG )
+#define SMC_GET_RX_DP_CTRL()           SMC_inl( ioaddr, RX_DP_CTRL )
+#define SMC_SET_RX_DP_CTRL(x)          SMC_outl( x, ioaddr, RX_DP_CTRL )
+#define SMC_GET_PMT_CTRL()             SMC_inl( ioaddr, PMT_CTRL )
+#define SMC_SET_PMT_CTRL(x)            SMC_outl( x, ioaddr, PMT_CTRL )
+#define SMC_GET_GPIO_CFG()             SMC_inl( ioaddr, GPIO_CFG )
+#define SMC_SET_GPIO_CFG(x)            SMC_outl( x, ioaddr, GPIO_CFG )
+#define SMC_GET_RX_FIFO_INF()          SMC_inl( ioaddr, RX_FIFO_INF )
+#define SMC_SET_RX_FIFO_INF(x)         SMC_outl( x, ioaddr, RX_FIFO_INF )
+#define SMC_GET_TX_FIFO_INF()          SMC_inl( ioaddr, TX_FIFO_INF )
+#define SMC_SET_TX_FIFO_INF(x)         SMC_outl( x, ioaddr, TX_FIFO_INF )
+#define SMC_GET_GPT_CFG()              SMC_inl( ioaddr, GPT_CFG )
+#define SMC_SET_GPT_CFG(x)             SMC_outl( x, ioaddr, GPT_CFG )
+#define SMC_GET_RX_DROP()              SMC_inl( ioaddr, RX_DROP )
+#define SMC_SET_RX_DROP(x)             SMC_outl( x, ioaddr, RX_DROP )
+#define SMC_GET_MAC_CMD()              SMC_inl( ioaddr, MAC_CSR_CMD )
+#define SMC_SET_MAC_CMD(x)             SMC_outl( x, ioaddr, MAC_CSR_CMD )
+#define SMC_GET_MAC_DATA()             SMC_inl( ioaddr, MAC_CSR_DATA )
+#define SMC_SET_MAC_DATA(x)            SMC_outl( x, ioaddr, MAC_CSR_DATA )
+#define SMC_GET_AFC_CFG()              SMC_inl( ioaddr, AFC_CFG )
+#define SMC_SET_AFC_CFG(x)             SMC_outl( x, ioaddr, AFC_CFG )
+#define SMC_GET_E2P_CMD()              SMC_inl( ioaddr, E2P_CMD )
+#define SMC_SET_E2P_CMD(x)             SMC_outl( x, ioaddr, E2P_CMD )
+#define SMC_GET_E2P_DATA()             SMC_inl( ioaddr, E2P_DATA )
+#define SMC_SET_E2P_DATA(x)            SMC_outl( x, ioaddr, E2P_DATA )
+
+/* MAC register read/write macros */
+#define SMC_GET_MAC_CSR(a,v)                                           \
+       do {                                                            \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ |                 \
+                       MAC_CSR_CMD_R_NOT_W_ | (a) );                   \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               v = SMC_GET_MAC_DATA();                                 \
+       } while (0)
+#define SMC_SET_MAC_CSR(a,v)                                           \
+       do {                                                            \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               SMC_SET_MAC_DATA(v);                                    \
+               SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) );          \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+       } while (0)
+#define SMC_GET_MAC_CR(x)      SMC_GET_MAC_CSR( MAC_CR, x )
+#define SMC_SET_MAC_CR(x)      SMC_SET_MAC_CSR( MAC_CR, x )
+#define SMC_GET_ADDRH(x)       SMC_GET_MAC_CSR( ADDRH, x )
+#define SMC_SET_ADDRH(x)       SMC_SET_MAC_CSR( ADDRH, x )
+#define SMC_GET_ADDRL(x)       SMC_GET_MAC_CSR( ADDRL, x )
+#define SMC_SET_ADDRL(x)       SMC_SET_MAC_CSR( ADDRL, x )
+#define SMC_GET_HASHH(x)       SMC_GET_MAC_CSR( HASHH, x )
+#define SMC_SET_HASHH(x)       SMC_SET_MAC_CSR( HASHH, x )
+#define SMC_GET_HASHL(x)       SMC_GET_MAC_CSR( HASHL, x )
+#define SMC_SET_HASHL(x)       SMC_SET_MAC_CSR( HASHL, x )
+#define SMC_GET_MII_ACC(x)     SMC_GET_MAC_CSR( MII_ACC, x )
+#define SMC_SET_MII_ACC(x)     SMC_SET_MAC_CSR( MII_ACC, x )
+#define SMC_GET_MII_DATA(x)    SMC_GET_MAC_CSR( MII_DATA, x )
+#define SMC_SET_MII_DATA(x)    SMC_SET_MAC_CSR( MII_DATA, x )
+#define SMC_GET_FLOW(x)                SMC_GET_MAC_CSR( FLOW, x )
+#define SMC_SET_FLOW(x)                SMC_SET_MAC_CSR( FLOW, x )
+#define SMC_GET_VLAN1(x)       SMC_GET_MAC_CSR( VLAN1, x )
+#define SMC_SET_VLAN1(x)       SMC_SET_MAC_CSR( VLAN1, x )
+#define SMC_GET_VLAN2(x)       SMC_GET_MAC_CSR( VLAN2, x )
+#define SMC_SET_VLAN2(x)       SMC_SET_MAC_CSR( VLAN2, x )
+#define SMC_SET_WUFF(x)                SMC_SET_MAC_CSR( WUFF, x )
+#define SMC_GET_WUCSR(x)       SMC_GET_MAC_CSR( WUCSR, x )
+#define SMC_SET_WUCSR(x)       SMC_SET_MAC_CSR( WUCSR, x )
+
+/* PHY register read/write macros */
+#define SMC_GET_MII(a,phy,v)                                   \
+       do {                                                    \
+               u32 __v;                                        \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+               SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
+                       MII_ACC_MII_BUSY_);                     \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+               SMC_GET_MII_DATA(v);                            \
+       } while (0)
+#define SMC_SET_MII(a,phy,v)                                   \
+       do {                                                    \
+               u32 __v;                                        \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+               SMC_SET_MII_DATA(v);                            \
+               SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
+                       MII_ACC_MII_BUSY_        |              \
+                       MII_ACC_MII_WRITE_  );                  \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+       } while (0)
+#define SMC_GET_PHY_BMCR(phy,x)                SMC_GET_MII( MII_BMCR, phy, x )
+#define SMC_SET_PHY_BMCR(phy,x)                SMC_SET_MII( MII_BMCR, phy, x )
+#define SMC_GET_PHY_BMSR(phy,x)                SMC_GET_MII( MII_BMSR, phy, x )
+#define SMC_GET_PHY_ID1(phy,x)         SMC_GET_MII( MII_PHYSID1, phy, x )
+#define SMC_GET_PHY_ID2(phy,x)         SMC_GET_MII( MII_PHYSID2, phy, x )
+#define SMC_GET_PHY_MII_ADV(phy,x)     SMC_GET_MII( MII_ADVERTISE, phy, x )
+#define SMC_SET_PHY_MII_ADV(phy,x)     SMC_SET_MII( MII_ADVERTISE, phy, x )
+#define SMC_GET_PHY_MII_LPA(phy,x)     SMC_GET_MII( MII_LPA, phy, x )
+#define SMC_SET_PHY_MII_LPA(phy,x)     SMC_SET_MII( MII_LPA, phy, x )
+#define SMC_GET_PHY_CTRL_STS(phy,x)    SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x )
+#define SMC_SET_PHY_CTRL_STS(phy,x)    SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x )
+#define SMC_GET_PHY_INT_SRC(phy,x)     SMC_GET_MII( PHY_INT_SRC, phy, x )
+#define SMC_SET_PHY_INT_SRC(phy,x)     SMC_SET_MII( PHY_INT_SRC, phy, x )
+#define SMC_GET_PHY_INT_MASK(phy,x)    SMC_GET_MII( PHY_INT_MASK, phy, x )
+#define SMC_SET_PHY_INT_MASK(phy,x)    SMC_SET_MII( PHY_INT_MASK, phy, x )
+#define SMC_GET_PHY_SPECIAL(phy,x)     SMC_GET_MII( PHY_SPECIAL, phy, x )
+
+
+
+/* Misc read/write macros */
+
+#ifndef SMC_GET_MAC_ADDR
+#define SMC_GET_MAC_ADDR(addr)                                 \
+       do {                                                    \
+               unsigned int __v;                               \
+                                                               \
+               SMC_GET_MAC_CSR(ADDRL, __v);                    \
+               addr[0] = __v; addr[1] = __v >> 8;              \
+               addr[2] = __v >> 16; addr[3] = __v >> 24;       \
+               SMC_GET_MAC_CSR(ADDRH, __v);                    \
+               addr[4] = __v; addr[5] = __v >> 8;              \
+       } while (0)
+#endif
+
+#define SMC_SET_MAC_ADDR(addr)                                 \
+       do {                                                    \
+                SMC_SET_MAC_CSR(ADDRL,                         \
+                                addr[0] |                      \
+                               (addr[1] << 8) |                \
+                               (addr[2] << 16) |               \
+                               (addr[3] << 24));               \
+                SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\
+       } while (0)
+
+
+#define SMC_WRITE_EEPROM_CMD(cmd, addr)                                        \
+       do {                                                            \
+               while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a );             \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+       } while (0)
+
+#endif  /* _SMC911X_H_ */
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
new file mode 100644 (file)
index 0000000..47f49ef
--- /dev/null
@@ -0,0 +1,4278 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * QE UCC Gigabit Ethernet Driver
+ *
+ * Changelog:
+ * Jul 6, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/mii.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_phy.h"
+
+#undef DEBUG
+
+#define DRV_DESC "QE UCC Gigabit Ethernet Controller version:June 20, 2006"
+#define DRV_NAME "ucc_geth"
+
+#define ugeth_printk(level, format, arg...)  \
+        printk(level format "\n", ## arg)
+
+#define ugeth_dbg(format, arg...)            \
+        ugeth_printk(KERN_DEBUG , format , ## arg)
+#define ugeth_err(format, arg...)            \
+        ugeth_printk(KERN_ERR , format , ## arg)
+#define ugeth_info(format, arg...)           \
+        ugeth_printk(KERN_INFO , format , ## arg)
+#define ugeth_warn(format, arg...)           \
+        ugeth_printk(KERN_WARNING , format , ## arg)
+
+#ifdef UGETH_VERBOSE_DEBUG
+#define ugeth_vdbg ugeth_dbg
+#else
+#define ugeth_vdbg(fmt, args...) do { } while (0)
+#endif                         /* UGETH_VERBOSE_DEBUG */
+
+static DEFINE_SPINLOCK(ugeth_lock);
+
+static ucc_geth_info_t ugeth_primary_info = {
+       .uf_info = {
+                   .bd_mem_part = MEM_PART_SYSTEM,
+                   .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
+                   .max_rx_buf_length = 1536,
+/* FIXME: should be changed in run time for 1G and 100M */
+#ifdef CONFIG_UGETH_HAS_GIGA
+                   .urfs = UCC_GETH_URFS_GIGA_INIT,
+                   .urfet = UCC_GETH_URFET_GIGA_INIT,
+                   .urfset = UCC_GETH_URFSET_GIGA_INIT,
+                   .utfs = UCC_GETH_UTFS_GIGA_INIT,
+                   .utfet = UCC_GETH_UTFET_GIGA_INIT,
+                   .utftt = UCC_GETH_UTFTT_GIGA_INIT,
+#else
+                   .urfs = UCC_GETH_URFS_INIT,
+                   .urfet = UCC_GETH_URFET_INIT,
+                   .urfset = UCC_GETH_URFSET_INIT,
+                   .utfs = UCC_GETH_UTFS_INIT,
+                   .utfet = UCC_GETH_UTFET_INIT,
+                   .utftt = UCC_GETH_UTFTT_INIT,
+#endif
+                   .ufpt = 256,
+                   .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,
+                   .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
+                   .tenc = UCC_FAST_TX_ENCODING_NRZ,
+                   .renc = UCC_FAST_RX_ENCODING_NRZ,
+                   .tcrc = UCC_FAST_16_BIT_CRC,
+                   .synl = UCC_FAST_SYNC_LEN_NOT_USED,
+                   },
+       .numQueuesTx = 1,
+       .numQueuesRx = 1,
+       .extendedFilteringChainPointer = ((uint32_t) NULL),
+       .typeorlen = 3072 /*1536 */ ,
+       .nonBackToBackIfgPart1 = 0x40,
+       .nonBackToBackIfgPart2 = 0x60,
+       .miminumInterFrameGapEnforcement = 0x50,
+       .backToBackInterFrameGap = 0x60,
+       .mblinterval = 128,
+       .nortsrbytetime = 5,
+       .fracsiz = 1,
+       .strictpriorityq = 0xff,
+       .altBebTruncation = 0xa,
+       .excessDefer = 1,
+       .maxRetransmission = 0xf,
+       .collisionWindow = 0x37,
+       .receiveFlowControl = 1,
+       .maxGroupAddrInHash = 4,
+       .maxIndAddrInHash = 4,
+       .prel = 7,
+       .maxFrameLength = 1518,
+       .minFrameLength = 64,
+       .maxD1Length = 1520,
+       .maxD2Length = 1520,
+       .vlantype = 0x8100,
+       .ecamptr = ((uint32_t) NULL),
+       .eventRegMask = UCCE_OTHER,
+       .pausePeriod = 0xf000,
+       .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},
+       .bdRingLenTx = {
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN,
+                       TX_BD_RING_LEN},
+
+       .bdRingLenRx = {
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN,
+                       RX_BD_RING_LEN},
+
+       .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
+       .largestexternallookupkeysize =
+           QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
+       .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE,
+       .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
+       .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
+       .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
+       .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,
+       .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,
+       .numThreadsTx = UCC_GETH_NUM_OF_THREADS_4,
+       .numThreadsRx = UCC_GETH_NUM_OF_THREADS_4,
+       .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+       .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+};
+
+static ucc_geth_info_t ugeth_info[8];
+
+#ifdef DEBUG
+static void mem_disp(u8 *addr, int size)
+{
+       u8 *i;
+       int size16Aling = (size >> 4) << 4;
+       int size4Aling = (size >> 2) << 2;
+       int notAlign = 0;
+       if (size % 16)
+               notAlign = 1;
+
+       for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)
+               printk("0x%08x: %08x %08x %08x %08x\r\n",
+                      (u32) i,
+                      *((u32 *) (i)),
+                      *((u32 *) (i + 4)),
+                      *((u32 *) (i + 8)), *((u32 *) (i + 12)));
+       if (notAlign == 1)
+               printk("0x%08x: ", (u32) i);
+       for (; (u32) i < (u32) addr + size4Aling; i += 4)
+               printk("%08x ", *((u32 *) (i)));
+       for (; (u32) i < (u32) addr + size; i++)
+               printk("%02x", *((u8 *) (i)));
+       if (notAlign == 1)
+               printk("\r\n");
+}
+#endif /* DEBUG */
+
+#ifdef CONFIG_UGETH_FILTERING
+static void enqueue(struct list_head *node, struct list_head *lh)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(ugeth_lock, flags);
+       list_add_tail(node, lh);
+       spin_unlock_irqrestore(ugeth_lock, flags);
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static struct list_head *dequeue(struct list_head *lh)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(ugeth_lock, flags);
+       if (!list_empty(lh)) {
+               struct list_head *node = lh->next;
+               list_del(node);
+               spin_unlock_irqrestore(ugeth_lock, flags);
+               return node;
+       } else {
+               spin_unlock_irqrestore(ugeth_lock, flags);
+               return NULL;
+       }
+}
+
+static int get_interface_details(enet_interface_e enet_interface,
+                                enet_speed_e *speed,
+                                int *r10m,
+                                int *rmm,
+                                int *rpm,
+                                int *tbi, int *limited_to_full_duplex)
+{
+       /* Analyze enet_interface according to Interface Mode
+       Configuration table */
+       switch (enet_interface) {
+       case ENET_10_MII:
+               *speed = ENET_SPEED_10BT;
+               break;
+       case ENET_10_RMII:
+               *speed = ENET_SPEED_10BT;
+               *r10m = 1;
+               *rmm = 1;
+               break;
+       case ENET_10_RGMII:
+               *speed = ENET_SPEED_10BT;
+               *rpm = 1;
+               *r10m = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_100_MII:
+               *speed = ENET_SPEED_100BT;
+               break;
+       case ENET_100_RMII:
+               *speed = ENET_SPEED_100BT;
+               *rmm = 1;
+               break;
+       case ENET_100_RGMII:
+               *speed = ENET_SPEED_100BT;
+               *rpm = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_GMII:
+               *speed = ENET_SPEED_1000BT;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_RGMII:
+               *speed = ENET_SPEED_1000BT;
+               *rpm = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_TBI:
+               *speed = ENET_SPEED_1000BT;
+               *tbi = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       case ENET_1000_RTBI:
+               *speed = ENET_SPEED_1000BT;
+               *rpm = 1;
+               *tbi = 1;
+               *limited_to_full_duplex = 1;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       return 0;
+}
+
+static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd)
+{
+       struct sk_buff *skb = NULL;
+
+       skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
+                                 UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+
+       if (skb == NULL)
+               return NULL;
+
+       /* We need the data buffer to be aligned properly.  We will reserve
+        * as many bytes as needed to align the data properly
+        */
+       skb_reserve(skb,
+                   UCC_GETH_RX_DATA_BUF_ALIGNMENT -
+                   (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
+                                             1)));
+
+       skb->dev = ugeth->dev;
+
+       BD_BUFFER_SET(bd,
+                     dma_map_single(NULL,
+                                    skb->data,
+                                    ugeth->ug_info->uf_info.max_rx_buf_length +
+                                    UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+                                    DMA_FROM_DEVICE));
+
+       BD_STATUS_AND_LENGTH_SET(bd,
+                                (R_E | R_I |
+                                 (BD_STATUS_AND_LENGTH(bd) & R_W)));
+
+       return skb;
+}
+
+static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ)
+{
+       u8 *bd;
+       u32 bd_status;
+       struct sk_buff *skb;
+       int i;
+
+       bd = ugeth->p_rx_bd_ring[rxQ];
+       i = 0;
+
+       do {
+               bd_status = BD_STATUS_AND_LENGTH(bd);
+               skb = get_new_skb(ugeth, bd);
+
+               if (!skb)       /* If can not allocate data buffer,
+                               abort. Cleanup will be elsewhere */
+                       return -ENOMEM;
+
+               ugeth->rx_skbuff[rxQ][i] = skb;
+
+               /* advance the BD pointer */
+               bd += UCC_GETH_SIZE_OF_BD;
+               i++;
+       } while (!(bd_status & R_W));
+
+       return 0;
+}
+
+static int fill_init_enet_entries(ucc_geth_private_t *ugeth,
+                                 volatile u32 *p_start,
+                                 u8 num_entries,
+                                 u32 thread_size,
+                                 u32 thread_alignment,
+                                 qe_risc_allocation_e risc,
+                                 int skip_page_for_first_entry)
+{
+       u32 init_enet_offset;
+       u8 i;
+       int snum;
+
+       for (i = 0; i < num_entries; i++) {
+               if ((snum = qe_get_snum()) < 0) {
+                       ugeth_err("fill_init_enet_entries: Can not get SNUM.");
+                       return snum;
+               }
+               if ((i == 0) && skip_page_for_first_entry)
+               /* First entry of Rx does not have page */
+                       init_enet_offset = 0;
+               else {
+                       init_enet_offset =
+                           qe_muram_alloc(thread_size, thread_alignment);
+                       if (IS_MURAM_ERR(init_enet_offset)) {
+                               ugeth_err
+               ("fill_init_enet_entries: Can not allocate DPRAM memory.");
+                               qe_put_snum((u8) snum);
+                               return -ENOMEM;
+                       }
+               }
+               *(p_start++) =
+                   ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset
+                   | risc;
+       }
+
+       return 0;
+}
+
+static int return_init_enet_entries(ucc_geth_private_t *ugeth,
+                                   volatile u32 *p_start,
+                                   u8 num_entries,
+                                   qe_risc_allocation_e risc,
+                                   int skip_page_for_first_entry)
+{
+       u32 init_enet_offset;
+       u8 i;
+       int snum;
+
+       for (i = 0; i < num_entries; i++) {
+               /* Check that this entry was actually valid --
+               needed in case failed in allocations */
+               if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
+                       snum =
+                           (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
+                           ENET_INIT_PARAM_SNUM_SHIFT;
+                       qe_put_snum((u8) snum);
+                       if (!((i == 0) && skip_page_for_first_entry)) {
+                       /* First entry of Rx does not have page */
+                               init_enet_offset =
+                                   (in_be32(p_start) &
+                                    ENET_INIT_PARAM_PTR_MASK);
+                               qe_muram_free(init_enet_offset);
+                       }
+                       *(p_start++) = 0;       /* Just for cosmetics */
+               }
+       }
+
+       return 0;
+}
+
+#ifdef DEBUG
+static int dump_init_enet_entries(ucc_geth_private_t *ugeth,
+                                 volatile u32 *p_start,
+                                 u8 num_entries,
+                                 u32 thread_size,
+                                 qe_risc_allocation_e risc,
+                                 int skip_page_for_first_entry)
+{
+       u32 init_enet_offset;
+       u8 i;
+       int snum;
+
+       for (i = 0; i < num_entries; i++) {
+               /* Check that this entry was actually valid --
+               needed in case failed in allocations */
+               if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
+                       snum =
+                           (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
+                           ENET_INIT_PARAM_SNUM_SHIFT;
+                       qe_put_snum((u8) snum);
+                       if (!((i == 0) && skip_page_for_first_entry)) {
+                       /* First entry of Rx does not have page */
+                               init_enet_offset =
+                                   (in_be32(p_start) &
+                                    ENET_INIT_PARAM_PTR_MASK);
+                               ugeth_info("Init enet entry %d:", i);
+                               ugeth_info("Base address: 0x%08x",
+                                          (u32)
+                                          qe_muram_addr(init_enet_offset));
+                               mem_disp(qe_muram_addr(init_enet_offset),
+                                        thread_size);
+                       }
+                       p_start++;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_UGETH_FILTERING
+static enet_addr_container_t *get_enet_addr_container(void)
+{
+       enet_addr_container_t *enet_addr_cont;
+
+       /* allocate memory */
+       enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL);
+       if (!enet_addr_cont) {
+               ugeth_err("%s: No memory for enet_addr_container_t object.",
+                         __FUNCTION__);
+               return NULL;
+       }
+
+       return enet_addr_cont;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont)
+{
+       kfree(enet_addr_cont);
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth,
+                               enet_addr_t *p_enet_addr, u8 paddr_num)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+
+       if (!(paddr_num < NUM_OF_PADDRS)) {
+               ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       /* Ethernet frames are defined in Little Endian mode,    */
+       /* therefore to insert the address we reverse the bytes. */
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].h,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
+                       (u16) (*p_enet_addr)[4]));
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].m,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
+                       (u16) (*p_enet_addr)[2]));
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].l,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
+                       (u16) (*p_enet_addr)[0]));
+
+       return 0;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+
+       if (!(paddr_num < NUM_OF_PADDRS)) {
+               ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       /* Writing address ff.ff.ff.ff.ff.ff disables address
+       recognition for this register */
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff);
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff);
+       out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff);
+
+       return 0;
+}
+
+static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth,
+                               enet_addr_t *p_enet_addr)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       u32 cecr_subblock;
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+
+       /* Ethernet frames are defined in Little Endian mode,
+       therefor to insert */
+       /* the address to the hash (Big Endian mode), we reverse the bytes.*/
+       out_be16(&p_82xx_addr_filt->taddr.h,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
+                       (u16) (*p_enet_addr)[4]));
+       out_be16(&p_82xx_addr_filt->taddr.m,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
+                       (u16) (*p_enet_addr)[2]));
+       out_be16(&p_82xx_addr_filt->taddr.l,
+                (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
+                       (u16) (*p_enet_addr)[0]));
+
+       qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
+                    (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+}
+
+#ifdef CONFIG_UGETH_MAGIC_PACKET
+static void magic_packet_detection_enable(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       ucc_geth_t *ug_regs;
+       u32 maccfg2, uccm;
+
+       uccf = ugeth->uccf;
+       ug_regs = ugeth->ug_regs;
+
+       /* Enable interrupts for magic packet detection */
+       uccm = in_be32(uccf->p_uccm);
+       uccm |= UCCE_MPD;
+       out_be32(uccf->p_uccm, uccm);
+
+       /* Enable magic packet detection */
+       maccfg2 = in_be32(&ug_regs->maccfg2);
+       maccfg2 |= MACCFG2_MPE;
+       out_be32(&ug_regs->maccfg2, maccfg2);
+}
+
+static void magic_packet_detection_disable(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       ucc_geth_t *ug_regs;
+       u32 maccfg2, uccm;
+
+       uccf = ugeth->uccf;
+       ug_regs = ugeth->ug_regs;
+
+       /* Disable interrupts for magic packet detection */
+       uccm = in_be32(uccf->p_uccm);
+       uccm &= ~UCCE_MPD;
+       out_be32(uccf->p_uccm, uccm);
+
+       /* Disable magic packet detection */
+       maccfg2 = in_be32(&ug_regs->maccfg2);
+       maccfg2 &= ~MACCFG2_MPE;
+       out_be32(&ug_regs->maccfg2, maccfg2);
+}
+#endif /* MAGIC_PACKET */
+
+static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2)
+{
+       return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
+}
+
+#ifdef DEBUG
+static void get_statistics(ucc_geth_private_t *ugeth,
+                          ucc_geth_tx_firmware_statistics_t *
+                          tx_firmware_statistics,
+                          ucc_geth_rx_firmware_statistics_t *
+                          rx_firmware_statistics,
+                          ucc_geth_hardware_statistics_t *hardware_statistics)
+{
+       ucc_fast_t *uf_regs;
+       ucc_geth_t *ug_regs;
+       ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+       ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+
+       ug_regs = ugeth->ug_regs;
+       uf_regs = (ucc_fast_t *) ug_regs;
+       p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
+       p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;
+
+       /* Tx firmware only if user handed pointer and driver actually
+       gathers Tx firmware statistics */
+       if (tx_firmware_statistics && p_tx_fw_statistics_pram) {
+               tx_firmware_statistics->sicoltx =
+                   in_be32(&p_tx_fw_statistics_pram->sicoltx);
+               tx_firmware_statistics->mulcoltx =
+                   in_be32(&p_tx_fw_statistics_pram->mulcoltx);
+               tx_firmware_statistics->latecoltxfr =
+                   in_be32(&p_tx_fw_statistics_pram->latecoltxfr);
+               tx_firmware_statistics->frabortduecol =
+                   in_be32(&p_tx_fw_statistics_pram->frabortduecol);
+               tx_firmware_statistics->frlostinmactxer =
+                   in_be32(&p_tx_fw_statistics_pram->frlostinmactxer);
+               tx_firmware_statistics->carriersenseertx =
+                   in_be32(&p_tx_fw_statistics_pram->carriersenseertx);
+               tx_firmware_statistics->frtxok =
+                   in_be32(&p_tx_fw_statistics_pram->frtxok);
+               tx_firmware_statistics->txfrexcessivedefer =
+                   in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer);
+               tx_firmware_statistics->txpkts256 =
+                   in_be32(&p_tx_fw_statistics_pram->txpkts256);
+               tx_firmware_statistics->txpkts512 =
+                   in_be32(&p_tx_fw_statistics_pram->txpkts512);
+               tx_firmware_statistics->txpkts1024 =
+                   in_be32(&p_tx_fw_statistics_pram->txpkts1024);
+               tx_firmware_statistics->txpktsjumbo =
+                   in_be32(&p_tx_fw_statistics_pram->txpktsjumbo);
+       }
+
+       /* Rx firmware only if user handed pointer and driver actually
+        * gathers Rx firmware statistics */
+       if (rx_firmware_statistics && p_rx_fw_statistics_pram) {
+               int i;
+               rx_firmware_statistics->frrxfcser =
+                   in_be32(&p_rx_fw_statistics_pram->frrxfcser);
+               rx_firmware_statistics->fraligner =
+                   in_be32(&p_rx_fw_statistics_pram->fraligner);
+               rx_firmware_statistics->inrangelenrxer =
+                   in_be32(&p_rx_fw_statistics_pram->inrangelenrxer);
+               rx_firmware_statistics->outrangelenrxer =
+                   in_be32(&p_rx_fw_statistics_pram->outrangelenrxer);
+               rx_firmware_statistics->frtoolong =
+                   in_be32(&p_rx_fw_statistics_pram->frtoolong);
+               rx_firmware_statistics->runt =
+                   in_be32(&p_rx_fw_statistics_pram->runt);
+               rx_firmware_statistics->verylongevent =
+                   in_be32(&p_rx_fw_statistics_pram->verylongevent);
+               rx_firmware_statistics->symbolerror =
+                   in_be32(&p_rx_fw_statistics_pram->symbolerror);
+               rx_firmware_statistics->dropbsy =
+                   in_be32(&p_rx_fw_statistics_pram->dropbsy);
+               for (i = 0; i < 0x8; i++)
+                       rx_firmware_statistics->res0[i] =
+                           p_rx_fw_statistics_pram->res0[i];
+               rx_firmware_statistics->mismatchdrop =
+                   in_be32(&p_rx_fw_statistics_pram->mismatchdrop);
+               rx_firmware_statistics->underpkts =
+                   in_be32(&p_rx_fw_statistics_pram->underpkts);
+               rx_firmware_statistics->pkts256 =
+                   in_be32(&p_rx_fw_statistics_pram->pkts256);
+               rx_firmware_statistics->pkts512 =
+                   in_be32(&p_rx_fw_statistics_pram->pkts512);
+               rx_firmware_statistics->pkts1024 =
+                   in_be32(&p_rx_fw_statistics_pram->pkts1024);
+               rx_firmware_statistics->pktsjumbo =
+                   in_be32(&p_rx_fw_statistics_pram->pktsjumbo);
+               rx_firmware_statistics->frlossinmacer =
+                   in_be32(&p_rx_fw_statistics_pram->frlossinmacer);
+               rx_firmware_statistics->pausefr =
+                   in_be32(&p_rx_fw_statistics_pram->pausefr);
+               for (i = 0; i < 0x4; i++)
+                       rx_firmware_statistics->res1[i] =
+                           p_rx_fw_statistics_pram->res1[i];
+               rx_firmware_statistics->removevlan =
+                   in_be32(&p_rx_fw_statistics_pram->removevlan);
+               rx_firmware_statistics->replacevlan =
+                   in_be32(&p_rx_fw_statistics_pram->replacevlan);
+               rx_firmware_statistics->insertvlan =
+                   in_be32(&p_rx_fw_statistics_pram->insertvlan);
+       }
+
+       /* Hardware only if user handed pointer and driver actually
+       gathers hardware statistics */
+       if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
+               hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
+               hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
+               hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
+               hardware_statistics->rx64 = in_be32(&ug_regs->rx64);
+               hardware_statistics->rx127 = in_be32(&ug_regs->rx127);
+               hardware_statistics->rx255 = in_be32(&ug_regs->rx255);
+               hardware_statistics->txok = in_be32(&ug_regs->txok);
+               hardware_statistics->txcf = in_be16(&ug_regs->txcf);
+               hardware_statistics->tmca = in_be32(&ug_regs->tmca);
+               hardware_statistics->tbca = in_be32(&ug_regs->tbca);
+               hardware_statistics->rxfok = in_be32(&ug_regs->rxfok);
+               hardware_statistics->rxbok = in_be32(&ug_regs->rxbok);
+               hardware_statistics->rbyt = in_be32(&ug_regs->rbyt);
+               hardware_statistics->rmca = in_be32(&ug_regs->rmca);
+               hardware_statistics->rbca = in_be32(&ug_regs->rbca);
+       }
+}
+
+static void dump_bds(ucc_geth_private_t *ugeth)
+{
+       int i;
+       int length;
+
+       for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+               if (ugeth->p_tx_bd_ring[i]) {
+                       length =
+                           (ugeth->ug_info->bdRingLenTx[i] *
+                            UCC_GETH_SIZE_OF_BD);
+                       ugeth_info("TX BDs[%d]", i);
+                       mem_disp(ugeth->p_tx_bd_ring[i], length);
+               }
+       }
+       for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+               if (ugeth->p_rx_bd_ring[i]) {
+                       length =
+                           (ugeth->ug_info->bdRingLenRx[i] *
+                            UCC_GETH_SIZE_OF_BD);
+                       ugeth_info("RX BDs[%d]", i);
+                       mem_disp(ugeth->p_rx_bd_ring[i], length);
+               }
+       }
+}
+
+static void dump_regs(ucc_geth_private_t *ugeth)
+{
+       int i;
+
+       ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num);
+       ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs);
+
+       ugeth_info("maccfg1    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->maccfg1,
+                  in_be32(&ugeth->ug_regs->maccfg1));
+       ugeth_info("maccfg2    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->maccfg2,
+                  in_be32(&ugeth->ug_regs->maccfg2));
+       ugeth_info("ipgifg     : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->ipgifg,
+                  in_be32(&ugeth->ug_regs->ipgifg));
+       ugeth_info("hafdup     : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->hafdup,
+                  in_be32(&ugeth->ug_regs->hafdup));
+       ugeth_info("miimcfg    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimcfg,
+                  in_be32(&ugeth->ug_regs->miimng.miimcfg));
+       ugeth_info("miimcom    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimcom,
+                  in_be32(&ugeth->ug_regs->miimng.miimcom));
+       ugeth_info("miimadd    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimadd,
+                  in_be32(&ugeth->ug_regs->miimng.miimadd));
+       ugeth_info("miimcon    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimcon,
+                  in_be32(&ugeth->ug_regs->miimng.miimcon));
+       ugeth_info("miimstat   : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimstat,
+                  in_be32(&ugeth->ug_regs->miimng.miimstat));
+       ugeth_info("miimmind   : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->miimng.miimind,
+                  in_be32(&ugeth->ug_regs->miimng.miimind));
+       ugeth_info("ifctl      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->ifctl,
+                  in_be32(&ugeth->ug_regs->ifctl));
+       ugeth_info("ifstat     : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->ifstat,
+                  in_be32(&ugeth->ug_regs->ifstat));
+       ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->macstnaddr1,
+                  in_be32(&ugeth->ug_regs->macstnaddr1));
+       ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->macstnaddr2,
+                  in_be32(&ugeth->ug_regs->macstnaddr2));
+       ugeth_info("uempr      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->uempr,
+                  in_be32(&ugeth->ug_regs->uempr));
+       ugeth_info("utbipar    : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->utbipar,
+                  in_be32(&ugeth->ug_regs->utbipar));
+       ugeth_info("uescr      : addr - 0x%08x, val - 0x%04x",
+                  (u32) & ugeth->ug_regs->uescr,
+                  in_be16(&ugeth->ug_regs->uescr));
+       ugeth_info("tx64       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tx64,
+                  in_be32(&ugeth->ug_regs->tx64));
+       ugeth_info("tx127      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tx127,
+                  in_be32(&ugeth->ug_regs->tx127));
+       ugeth_info("tx255      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tx255,
+                  in_be32(&ugeth->ug_regs->tx255));
+       ugeth_info("rx64       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rx64,
+                  in_be32(&ugeth->ug_regs->rx64));
+       ugeth_info("rx127      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rx127,
+                  in_be32(&ugeth->ug_regs->rx127));
+       ugeth_info("rx255      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rx255,
+                  in_be32(&ugeth->ug_regs->rx255));
+       ugeth_info("txok       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->txok,
+                  in_be32(&ugeth->ug_regs->txok));
+       ugeth_info("txcf       : addr - 0x%08x, val - 0x%04x",
+                  (u32) & ugeth->ug_regs->txcf,
+                  in_be16(&ugeth->ug_regs->txcf));
+       ugeth_info("tmca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tmca,
+                  in_be32(&ugeth->ug_regs->tmca));
+       ugeth_info("tbca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->tbca,
+                  in_be32(&ugeth->ug_regs->tbca));
+       ugeth_info("rxfok      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rxfok,
+                  in_be32(&ugeth->ug_regs->rxfok));
+       ugeth_info("rxbok      : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rxbok,
+                  in_be32(&ugeth->ug_regs->rxbok));
+       ugeth_info("rbyt       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rbyt,
+                  in_be32(&ugeth->ug_regs->rbyt));
+       ugeth_info("rmca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rmca,
+                  in_be32(&ugeth->ug_regs->rmca));
+       ugeth_info("rbca       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->rbca,
+                  in_be32(&ugeth->ug_regs->rbca));
+       ugeth_info("scar       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->scar,
+                  in_be32(&ugeth->ug_regs->scar));
+       ugeth_info("scam       : addr - 0x%08x, val - 0x%08x",
+                  (u32) & ugeth->ug_regs->scam,
+                  in_be32(&ugeth->ug_regs->scam));
+
+       if (ugeth->p_thread_data_tx) {
+               int numThreadsTxNumerical;
+               switch (ugeth->ug_info->numThreadsTx) {
+               case UCC_GETH_NUM_OF_THREADS_1:
+                       numThreadsTxNumerical = 1;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_2:
+                       numThreadsTxNumerical = 2;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_4:
+                       numThreadsTxNumerical = 4;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_6:
+                       numThreadsTxNumerical = 6;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_8:
+                       numThreadsTxNumerical = 8;
+                       break;
+               default:
+                       numThreadsTxNumerical = 0;
+                       break;
+               }
+
+               ugeth_info("Thread data TXs:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_thread_data_tx);
+               for (i = 0; i < numThreadsTxNumerical; i++) {
+                       ugeth_info("Thread data TX[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_thread_data_tx[i]);
+                       mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
+                                sizeof(ucc_geth_thread_data_tx_t));
+               }
+       }
+       if (ugeth->p_thread_data_rx) {
+               int numThreadsRxNumerical;
+               switch (ugeth->ug_info->numThreadsRx) {
+               case UCC_GETH_NUM_OF_THREADS_1:
+                       numThreadsRxNumerical = 1;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_2:
+                       numThreadsRxNumerical = 2;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_4:
+                       numThreadsRxNumerical = 4;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_6:
+                       numThreadsRxNumerical = 6;
+                       break;
+               case UCC_GETH_NUM_OF_THREADS_8:
+                       numThreadsRxNumerical = 8;
+                       break;
+               default:
+                       numThreadsRxNumerical = 0;
+                       break;
+               }
+
+               ugeth_info("Thread data RX:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_thread_data_rx);
+               for (i = 0; i < numThreadsRxNumerical; i++) {
+                       ugeth_info("Thread data RX[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_thread_data_rx[i]);
+                       mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
+                                sizeof(ucc_geth_thread_data_rx_t));
+               }
+       }
+       if (ugeth->p_exf_glbl_param) {
+               ugeth_info("EXF global param:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_exf_glbl_param);
+               mem_disp((u8 *) ugeth->p_exf_glbl_param,
+                        sizeof(*ugeth->p_exf_glbl_param));
+       }
+       if (ugeth->p_tx_glbl_pram) {
+               ugeth_info("TX global param:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram);
+               ugeth_info("temoder      : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_tx_glbl_pram->temoder,
+                          in_be16(&ugeth->p_tx_glbl_pram->temoder));
+               ugeth_info("sqptr        : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->sqptr,
+                          in_be32(&ugeth->p_tx_glbl_pram->sqptr));
+               ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer,
+                          in_be32(&ugeth->p_tx_glbl_pram->
+                                  schedulerbasepointer));
+               ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr,
+                          in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr));
+               ugeth_info("tstate       : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->tstate,
+                          in_be32(&ugeth->p_tx_glbl_pram->tstate));
+               ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[0],
+                          ugeth->p_tx_glbl_pram->iphoffset[0]);
+               ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[1],
+                          ugeth->p_tx_glbl_pram->iphoffset[1]);
+               ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[2],
+                          ugeth->p_tx_glbl_pram->iphoffset[2]);
+               ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[3],
+                          ugeth->p_tx_glbl_pram->iphoffset[3]);
+               ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[4],
+                          ugeth->p_tx_glbl_pram->iphoffset[4]);
+               ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[5],
+                          ugeth->p_tx_glbl_pram->iphoffset[5]);
+               ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[6],
+                          ugeth->p_tx_glbl_pram->iphoffset[6]);
+               ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_tx_glbl_pram->iphoffset[7],
+                          ugeth->p_tx_glbl_pram->iphoffset[7]);
+               ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[0],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0]));
+               ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[1],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1]));
+               ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[2],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2]));
+               ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[3],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3]));
+               ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[4],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4]));
+               ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[5],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5]));
+               ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[6],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6]));
+               ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->vtagtable[7],
+                          in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7]));
+               ugeth_info("tqptr        : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_tx_glbl_pram->tqptr,
+                          in_be32(&ugeth->p_tx_glbl_pram->tqptr));
+       }
+       if (ugeth->p_rx_glbl_pram) {
+               ugeth_info("RX global param:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram);
+               ugeth_info("remoder         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->remoder,
+                          in_be32(&ugeth->p_rx_glbl_pram->remoder));
+               ugeth_info("rqptr           : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->rqptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->rqptr));
+               ugeth_info("typeorlen       : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->typeorlen,
+                          in_be16(&ugeth->p_rx_glbl_pram->typeorlen));
+               ugeth_info("rxgstpack       : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_rx_glbl_pram->rxgstpack,
+                          ugeth->p_rx_glbl_pram->rxgstpack);
+               ugeth_info("rxrmonbaseptr   : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr));
+               ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr));
+               ugeth_info("rstate          : addr - 0x%08x, val - 0x%02x",
+                          (u32) & ugeth->p_rx_glbl_pram->rstate,
+                          ugeth->p_rx_glbl_pram->rstate);
+               ugeth_info("mrblr           : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->mrblr,
+                          in_be16(&ugeth->p_rx_glbl_pram->mrblr));
+               ugeth_info("rbdqptr         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->rbdqptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->rbdqptr));
+               ugeth_info("mflr            : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->mflr,
+                          in_be16(&ugeth->p_rx_glbl_pram->mflr));
+               ugeth_info("minflr          : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->minflr,
+                          in_be16(&ugeth->p_rx_glbl_pram->minflr));
+               ugeth_info("maxd1           : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->maxd1,
+                          in_be16(&ugeth->p_rx_glbl_pram->maxd1));
+               ugeth_info("maxd2           : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->maxd2,
+                          in_be16(&ugeth->p_rx_glbl_pram->maxd2));
+               ugeth_info("ecamptr         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->ecamptr,
+                          in_be32(&ugeth->p_rx_glbl_pram->ecamptr));
+               ugeth_info("l2qt            : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l2qt,
+                          in_be32(&ugeth->p_rx_glbl_pram->l2qt));
+               ugeth_info("l3qt[0]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[0],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[0]));
+               ugeth_info("l3qt[1]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[1],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[1]));
+               ugeth_info("l3qt[2]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[2],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[2]));
+               ugeth_info("l3qt[3]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[3],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[3]));
+               ugeth_info("l3qt[4]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[4],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[4]));
+               ugeth_info("l3qt[5]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[5],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[5]));
+               ugeth_info("l3qt[6]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[6],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[6]));
+               ugeth_info("l3qt[7]         : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->l3qt[7],
+                          in_be32(&ugeth->p_rx_glbl_pram->l3qt[7]));
+               ugeth_info("vlantype        : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->vlantype,
+                          in_be16(&ugeth->p_rx_glbl_pram->vlantype));
+               ugeth_info("vlantci         : addr - 0x%08x, val - 0x%04x",
+                          (u32) & ugeth->p_rx_glbl_pram->vlantci,
+                          in_be16(&ugeth->p_rx_glbl_pram->vlantci));
+               for (i = 0; i < 64; i++)
+                       ugeth_info
+                   ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x",
+                            i,
+                            (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i],
+                            ugeth->p_rx_glbl_pram->addressfiltering[i]);
+               ugeth_info("exfGlobalParam  : addr - 0x%08x, val - 0x%08x",
+                          (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam,
+                          in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam));
+       }
+       if (ugeth->p_send_q_mem_reg) {
+               ugeth_info("Send Q memory registers:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_send_q_mem_reg);
+               for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+                       ugeth_info("SQQD[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_send_q_mem_reg->sqqd[i]);
+                       mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
+                                sizeof(ucc_geth_send_queue_qd_t));
+               }
+       }
+       if (ugeth->p_scheduler) {
+               ugeth_info("Scheduler:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler);
+               mem_disp((u8 *) ugeth->p_scheduler,
+                        sizeof(*ugeth->p_scheduler));
+       }
+       if (ugeth->p_tx_fw_statistics_pram) {
+               ugeth_info("TX FW statistics pram:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_tx_fw_statistics_pram);
+               mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram,
+                        sizeof(*ugeth->p_tx_fw_statistics_pram));
+       }
+       if (ugeth->p_rx_fw_statistics_pram) {
+               ugeth_info("RX FW statistics pram:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_rx_fw_statistics_pram);
+               mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram,
+                        sizeof(*ugeth->p_rx_fw_statistics_pram));
+       }
+       if (ugeth->p_rx_irq_coalescing_tbl) {
+               ugeth_info("RX IRQ coalescing tables:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_rx_irq_coalescing_tbl);
+               for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+                       ugeth_info("RX IRQ coalescing table entry[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_rx_irq_coalescing_tbl->
+                                  coalescingentry[i]);
+                       ugeth_info
+               ("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_irq_coalescing_tbl->
+                            coalescingentry[i].interruptcoalescingmaxvalue,
+                            in_be32(&ugeth->p_rx_irq_coalescing_tbl->
+                                    coalescingentry[i].
+                                    interruptcoalescingmaxvalue));
+                       ugeth_info
+               ("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_irq_coalescing_tbl->
+                            coalescingentry[i].interruptcoalescingcounter,
+                            in_be32(&ugeth->p_rx_irq_coalescing_tbl->
+                                    coalescingentry[i].
+                                    interruptcoalescingcounter));
+               }
+       }
+       if (ugeth->p_rx_bd_qs_tbl) {
+               ugeth_info("RX BD QS tables:");
+               ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl);
+               for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+                       ugeth_info("RX BD QS table[%d]:", i);
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32) & ugeth->p_rx_bd_qs_tbl[i]);
+                       ugeth_info
+                           ("bdbaseptr        : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr));
+                       ugeth_info
+                           ("bdptr            : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr));
+                       ugeth_info
+                           ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].
+                                    externalbdbaseptr));
+                       ugeth_info
+                           ("externalbdptr    : addr - 0x%08x, val - 0x%08x",
+                            (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr,
+                            in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr));
+                       ugeth_info("ucode RX Prefetched BDs:");
+                       ugeth_info("Base address: 0x%08x",
+                                  (u32)
+                                  qe_muram_addr(in_be32
+                                                (&ugeth->p_rx_bd_qs_tbl[i].
+                                                 bdbaseptr)));
+                       mem_disp((u8 *)
+                                qe_muram_addr(in_be32
+                                              (&ugeth->p_rx_bd_qs_tbl[i].
+                                               bdbaseptr)),
+                                sizeof(ucc_geth_rx_prefetched_bds_t));
+               }
+       }
+       if (ugeth->p_init_enet_param_shadow) {
+               int size;
+               ugeth_info("Init enet param shadow:");
+               ugeth_info("Base address: 0x%08x",
+                          (u32) ugeth->p_init_enet_param_shadow);
+               mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
+                        sizeof(*ugeth->p_init_enet_param_shadow));
+
+               size = sizeof(ucc_geth_thread_rx_pram_t);
+               if (ugeth->ug_info->rxExtendedFiltering) {
+                       size +=
+                           THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
+                       if (ugeth->ug_info->largestexternallookupkeysize ==
+                           QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+                               size +=
+                       THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
+                       if (ugeth->ug_info->largestexternallookupkeysize ==
+                           QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
+                               size +=
+                       THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
+               }
+
+               dump_init_enet_entries(ugeth,
+                                      &(ugeth->p_init_enet_param_shadow->
+                                        txthread[0]),
+                                      ENET_INIT_PARAM_MAX_ENTRIES_TX,
+                                      sizeof(ucc_geth_thread_tx_pram_t),
+                                      ugeth->ug_info->riscTx, 0);
+               dump_init_enet_entries(ugeth,
+                                      &(ugeth->p_init_enet_param_shadow->
+                                        rxthread[0]),
+                                      ENET_INIT_PARAM_MAX_ENTRIES_RX, size,
+                                      ugeth->ug_info->riscRx, 1);
+       }
+}
+#endif /* DEBUG */
+
+static void init_default_reg_vals(volatile u32 *upsmr_register,
+                                 volatile u32 *maccfg1_register,
+                                 volatile u32 *maccfg2_register)
+{
+       out_be32(upsmr_register, UCC_GETH_UPSMR_INIT);
+       out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT);
+       out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT);
+}
+
+static int init_half_duplex_params(int alt_beb,
+                                  int back_pressure_no_backoff,
+                                  int no_backoff,
+                                  int excess_defer,
+                                  u8 alt_beb_truncation,
+                                  u8 max_retransmissions,
+                                  u8 collision_window,
+                                  volatile u32 *hafdup_register)
+{
+       u32 value = 0;
+
+       if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) ||
+           (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) ||
+           (collision_window > HALFDUP_COLLISION_WINDOW_MAX))
+               return -EINVAL;
+
+       value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT);
+
+       if (alt_beb)
+               value |= HALFDUP_ALT_BEB;
+       if (back_pressure_no_backoff)
+               value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF;
+       if (no_backoff)
+               value |= HALFDUP_NO_BACKOFF;
+       if (excess_defer)
+               value |= HALFDUP_EXCESSIVE_DEFER;
+
+       value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT);
+
+       value |= collision_window;
+
+       out_be32(hafdup_register, value);
+       return 0;
+}
+
+static int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
+                                      u8 non_btb_ipg,
+                                      u8 min_ifg,
+                                      u8 btb_ipg,
+                                      volatile u32 *ipgifg_register)
+{
+       u32 value = 0;
+
+       /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back
+       IPG part 2 */
+       if (non_btb_cs_ipg > non_btb_ipg)
+               return -EINVAL;
+
+       if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) ||
+           (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) ||
+           /*(min_ifg        > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */
+           (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX))
+               return -EINVAL;
+
+       value |=
+           ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) &
+            IPGIFG_NBTB_CS_IPG_MASK);
+       value |=
+           ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) &
+            IPGIFG_NBTB_IPG_MASK);
+       value |=
+           ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) &
+            IPGIFG_MIN_IFG_MASK);
+       value |= (btb_ipg & IPGIFG_BTB_IPG_MASK);
+
+       out_be32(ipgifg_register, value);
+       return 0;
+}
+
+static int init_flow_control_params(u32 automatic_flow_control_mode,
+                                   int rx_flow_control_enable,
+                                   int tx_flow_control_enable,
+                                   u16 pause_period,
+                                   u16 extension_field,
+                                   volatile u32 *upsmr_register,
+                                   volatile u32 *uempr_register,
+                                   volatile u32 *maccfg1_register)
+{
+       u32 value = 0;
+
+       /* Set UEMPR register */
+       value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT;
+       value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT;
+       out_be32(uempr_register, value);
+
+       /* Set UPSMR register */
+       value = in_be32(upsmr_register);
+       value |= automatic_flow_control_mode;
+       out_be32(upsmr_register, value);
+
+       value = in_be32(maccfg1_register);
+       if (rx_flow_control_enable)
+               value |= MACCFG1_FLOW_RX;
+       if (tx_flow_control_enable)
+               value |= MACCFG1_FLOW_TX;
+       out_be32(maccfg1_register, value);
+
+       return 0;
+}
+
+static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
+                                            int auto_zero_hardware_statistics,
+                                            volatile u32 *upsmr_register,
+                                            volatile u16 *uescr_register)
+{
+       u32 upsmr_value = 0;
+       u16 uescr_value = 0;
+       /* Enable hardware statistics gathering if requested */
+       if (enable_hardware_statistics) {
+               upsmr_value = in_be32(upsmr_register);
+               upsmr_value |= UPSMR_HSE;
+               out_be32(upsmr_register, upsmr_value);
+       }
+
+       /* Clear hardware statistics counters */
+       uescr_value = in_be16(uescr_register);
+       uescr_value |= UESCR_CLRCNT;
+       /* Automatically zero hardware statistics counters on read,
+       if requested */
+       if (auto_zero_hardware_statistics)
+               uescr_value |= UESCR_AUTOZ;
+       out_be16(uescr_register, uescr_value);
+
+       return 0;
+}
+
+static int init_firmware_statistics_gathering_mode(int
+               enable_tx_firmware_statistics,
+               int enable_rx_firmware_statistics,
+               volatile u32 *tx_rmon_base_ptr,
+               u32 tx_firmware_statistics_structure_address,
+               volatile u32 *rx_rmon_base_ptr,
+               u32 rx_firmware_statistics_structure_address,
+               volatile u16 *temoder_register,
+               volatile u32 *remoder_register)
+{
+       /* Note: this function does not check if */
+       /* the parameters it receives are NULL   */
+       u16 temoder_value;
+       u32 remoder_value;
+
+       if (enable_tx_firmware_statistics) {
+               out_be32(tx_rmon_base_ptr,
+                        tx_firmware_statistics_structure_address);
+               temoder_value = in_be16(temoder_register);
+               temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
+               out_be16(temoder_register, temoder_value);
+       }
+
+       if (enable_rx_firmware_statistics) {
+               out_be32(rx_rmon_base_ptr,
+                        rx_firmware_statistics_structure_address);
+               remoder_value = in_be32(remoder_register);
+               remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
+               out_be32(remoder_register, remoder_value);
+       }
+
+       return 0;
+}
+
+static int init_mac_station_addr_regs(u8 address_byte_0,
+                                     u8 address_byte_1,
+                                     u8 address_byte_2,
+                                     u8 address_byte_3,
+                                     u8 address_byte_4,
+                                     u8 address_byte_5,
+                                     volatile u32 *macstnaddr1_register,
+                                     volatile u32 *macstnaddr2_register)
+{
+       u32 value = 0;
+
+       /* Example: for a station address of 0x12345678ABCD, */
+       /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */
+
+       /* MACSTNADDR1 Register: */
+
+       /* 0                      7   8                      15  */
+       /* station address byte 5     station address byte 4     */
+       /* 16                     23  24                     31  */
+       /* station address byte 3     station address byte 2     */
+       value |= (u32) ((address_byte_2 << 0) & 0x000000FF);
+       value |= (u32) ((address_byte_3 << 8) & 0x0000FF00);
+       value |= (u32) ((address_byte_4 << 16) & 0x00FF0000);
+       value |= (u32) ((address_byte_5 << 24) & 0xFF000000);
+
+       out_be32(macstnaddr1_register, value);
+
+       /* MACSTNADDR2 Register: */
+
+       /* 0                      7   8                      15  */
+       /* station address byte 1     station address byte 0     */
+       /* 16                     23  24                     31  */
+       /*         reserved                   reserved           */
+       value = 0;
+       value |= (u32) ((address_byte_0 << 16) & 0x00FF0000);
+       value |= (u32) ((address_byte_1 << 24) & 0xFF000000);
+
+       out_be32(macstnaddr2_register, value);
+
+       return 0;
+}
+
+static int init_mac_duplex_mode(int full_duplex,
+                               int limited_to_full_duplex,
+                               volatile u32 *maccfg2_register)
+{
+       u32 value = 0;
+
+       /* some interfaces must work in full duplex mode */
+       if ((full_duplex == 0) && (limited_to_full_duplex == 1))
+               return -EINVAL;
+
+       value = in_be32(maccfg2_register);
+
+       if (full_duplex)
+               value |= MACCFG2_FDX;
+       else
+               value &= ~MACCFG2_FDX;
+
+       out_be32(maccfg2_register, value);
+       return 0;
+}
+
+static int init_check_frame_length_mode(int length_check,
+                                       volatile u32 *maccfg2_register)
+{
+       u32 value = 0;
+
+       value = in_be32(maccfg2_register);
+
+       if (length_check)
+               value |= MACCFG2_LC;
+       else
+               value &= ~MACCFG2_LC;
+
+       out_be32(maccfg2_register, value);
+       return 0;
+}
+
+static int init_preamble_length(u8 preamble_length,
+                               volatile u32 *maccfg2_register)
+{
+       u32 value = 0;
+
+       if ((preamble_length < 3) || (preamble_length > 7))
+               return -EINVAL;
+
+       value = in_be32(maccfg2_register);
+       value &= ~MACCFG2_PREL_MASK;
+       value |= (preamble_length << MACCFG2_PREL_SHIFT);
+       out_be32(maccfg2_register, value);
+       return 0;
+}
+
+static int init_mii_management_configuration(int reset_mgmt,
+                                            int preamble_supress,
+                                            volatile u32 *miimcfg_register,
+                                            volatile u32 *miimind_register)
+{
+       unsigned int timeout = PHY_INIT_TIMEOUT;
+       u32 value = 0;
+
+       value = in_be32(miimcfg_register);
+       if (reset_mgmt) {
+               value |= MIIMCFG_RESET_MANAGEMENT;
+               out_be32(miimcfg_register, value);
+       }
+
+       value = 0;
+
+       if (preamble_supress)
+               value |= MIIMCFG_NO_PREAMBLE;
+
+       value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT;
+       out_be32(miimcfg_register, value);
+
+       /* Wait until the bus is free */
+       while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--)
+               cpu_relax();
+
+       if (timeout <= 0) {
+               ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int init_rx_parameters(int reject_broadcast,
+                             int receive_short_frames,
+                             int promiscuous, volatile u32 *upsmr_register)
+{
+       u32 value = 0;
+
+       value = in_be32(upsmr_register);
+
+       if (reject_broadcast)
+               value |= UPSMR_BRO;
+       else
+               value &= ~UPSMR_BRO;
+
+       if (receive_short_frames)
+               value |= UPSMR_RSH;
+       else
+               value &= ~UPSMR_RSH;
+
+       if (promiscuous)
+               value |= UPSMR_PRO;
+       else
+               value &= ~UPSMR_PRO;
+
+       out_be32(upsmr_register, value);
+
+       return 0;
+}
+
+static int init_max_rx_buff_len(u16 max_rx_buf_len,
+                               volatile u16 *mrblr_register)
+{
+       /* max_rx_buf_len value must be a multiple of 128 */
+       if ((max_rx_buf_len == 0)
+           || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
+               return -EINVAL;
+
+       out_be16(mrblr_register, max_rx_buf_len);
+       return 0;
+}
+
+static int init_min_frame_len(u16 min_frame_length,
+                             volatile u16 *minflr_register,
+                             volatile u16 *mrblr_register)
+{
+       u16 mrblr_value = 0;
+
+       mrblr_value = in_be16(mrblr_register);
+       if (min_frame_length >= (mrblr_value - 4))
+               return -EINVAL;
+
+       out_be16(minflr_register, min_frame_length);
+       return 0;
+}
+
+static int adjust_enet_interface(ucc_geth_private_t *ugeth)
+{
+       ucc_geth_info_t *ug_info;
+       ucc_geth_t *ug_regs;
+       ucc_fast_t *uf_regs;
+       enet_speed_e speed;
+       int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm =
+           0, limited_to_full_duplex = 0;
+       u32 upsmr, maccfg2, utbipar, tbiBaseAddress;
+       u16 value;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ug_info = ugeth->ug_info;
+       ug_regs = ugeth->ug_regs;
+       uf_regs = ugeth->uccf->uf_regs;
+
+       /* Analyze enet_interface according to Interface Mode Configuration
+       table */
+       ret_val =
+           get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm,
+                                 &rpm, &tbi, &limited_to_full_duplex);
+       if (ret_val != 0) {
+               ugeth_err
+                 ("%s: half duplex not supported in requested configuration.",
+                    __FUNCTION__);
+               return ret_val;
+       }
+
+       /*                    Set MACCFG2                    */
+       maccfg2 = in_be32(&ug_regs->maccfg2);
+       maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
+       if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT))
+               maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
+       else if (speed == ENET_SPEED_1000BT)
+               maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
+       maccfg2 |= ug_info->padAndCrc;
+       out_be32(&ug_regs->maccfg2, maccfg2);
+
+       /*                    Set UPSMR                      */
+       upsmr = in_be32(&uf_regs->upsmr);
+       upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
+       if (rpm)
+               upsmr |= UPSMR_RPM;
+       if (r10m)
+               upsmr |= UPSMR_R10M;
+       if (tbi)
+               upsmr |= UPSMR_TBIM;
+       if (rmm)
+               upsmr |= UPSMR_RMM;
+       out_be32(&uf_regs->upsmr, upsmr);
+
+       /*                    Set UTBIPAR                    */
+       utbipar = in_be32(&ug_regs->utbipar);
+       utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK;
+       if (tbi)
+               utbipar |=
+                   (ug_info->phy_address +
+                    ugeth->ug_info->uf_info.
+                    ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
+       else
+               utbipar |=
+                   (0x10 +
+                    ugeth->ug_info->uf_info.
+                    ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
+       out_be32(&ug_regs->utbipar, utbipar);
+
+       /* Disable autonegotiation in tbi mode, because by default it
+       comes up in autonegotiation mode. */
+       /* Note that this depends on proper setting in utbipar register. */
+       if (tbi) {
+               tbiBaseAddress = in_be32(&ug_regs->utbipar);
+               tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK;
+               tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT;
+               value =
+                   ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress,
+                                              ENET_TBI_MII_CR);
+               value &= ~0x1000;       /* Turn off autonegotiation */
+               ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress,
+                                           ENET_TBI_MII_CR, value);
+       }
+
+       ret_val = init_mac_duplex_mode(1,
+                                      limited_to_full_duplex,
+                                      &ug_regs->maccfg2);
+       if (ret_val != 0) {
+               ugeth_err
+               ("%s: half duplex not supported in requested configuration.",
+                    __FUNCTION__);
+               return ret_val;
+       }
+
+       init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
+
+       ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
+       if (ret_val != 0) {
+               ugeth_err
+                   ("%s: Preamble length must be between 3 and 7 inclusive.",
+                    __FUNCTION__);
+               return ret_val;
+       }
+
+       return 0;
+}
+
+/* Called every time the controller might need to be made
+ * aware of new link state.  The PHY code conveys this
+ * information through variables in the ugeth structure, and this
+ * function converts those variables into the appropriate
+ * register values, and can bring down the device if needed.
+ */
+static void adjust_link(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_geth_t *ug_regs;
+       u32 tempval;
+       struct ugeth_mii_info *mii_info = ugeth->mii_info;
+
+       ug_regs = ugeth->ug_regs;
+
+       if (mii_info->link) {
+               /* Now we make sure that we can be in full duplex mode.
+                * If not, we operate in half-duplex mode. */
+               if (mii_info->duplex != ugeth->oldduplex) {
+                       if (!(mii_info->duplex)) {
+                               tempval = in_be32(&ug_regs->maccfg2);
+                               tempval &= ~(MACCFG2_FDX);
+                               out_be32(&ug_regs->maccfg2, tempval);
+
+                               ugeth_info("%s: Half Duplex", dev->name);
+                       } else {
+                               tempval = in_be32(&ug_regs->maccfg2);
+                               tempval |= MACCFG2_FDX;
+                               out_be32(&ug_regs->maccfg2, tempval);
+
+                               ugeth_info("%s: Full Duplex", dev->name);
+                       }
+
+                       ugeth->oldduplex = mii_info->duplex;
+               }
+
+               if (mii_info->speed != ugeth->oldspeed) {
+                       switch (mii_info->speed) {
+                       case 1000:
+#ifdef CONFIG_MPC836x
+/* FIXME: This code is for 100Mbs BUG fixing,
+remove this when it is fixed!!! */
+                               if (ugeth->ug_info->enet_interface ==
+                                   ENET_1000_GMII)
+                               /* Run the commands which initialize the PHY */
+                               {
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id, 0x1b);
+                                       tempval |= 0x000f;
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, 0x1b,
+                                               (u16) tempval);
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id,
+                                               MII_BMCR);
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, MII_BMCR,
+                                               (u16) (tempval | BMCR_RESET));
+                               } else if (ugeth->ug_info->enet_interface ==
+                                          ENET_1000_RGMII)
+                               /* Run the commands which initialize the PHY */
+                               {
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id, 0x1b);
+                                       tempval = (tempval & ~0x000f) | 0x000b;
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, 0x1b,
+                                               (u16) tempval);
+                                       tempval =
+                                           (u32) mii_info->mdio_read(ugeth->
+                                               dev, mii_info->mii_id,
+                                               MII_BMCR);
+                                       mii_info->mdio_write(ugeth->dev,
+                                               mii_info->mii_id, MII_BMCR,
+                                               (u16) (tempval | BMCR_RESET));
+                               }
+                               msleep(4000);
+#endif                         /* CONFIG_MPC8360 */
+                               adjust_enet_interface(ugeth);
+                               break;
+                       case 100:
+                       case 10:
+#ifdef CONFIG_MPC836x
+/* FIXME: This code is for 100Mbs BUG fixing,
+remove this lines when it will be fixed!!! */
+                               ugeth->ug_info->enet_interface = ENET_100_RGMII;
+                               tempval =
+                                   (u32) mii_info->mdio_read(ugeth->dev,
+                                                             mii_info->mii_id,
+                                                             0x1b);
+                               tempval = (tempval & ~0x000f) | 0x000b;
+                               mii_info->mdio_write(ugeth->dev,
+                                                    mii_info->mii_id, 0x1b,
+                                                    (u16) tempval);
+                               tempval =
+                                   (u32) mii_info->mdio_read(ugeth->dev,
+                                                             mii_info->mii_id,
+                                                             MII_BMCR);
+                               mii_info->mdio_write(ugeth->dev,
+                                                    mii_info->mii_id, MII_BMCR,
+                                                    (u16) (tempval |
+                                                           BMCR_RESET));
+                               msleep(4000);
+#endif                         /* CONFIG_MPC8360 */
+                               adjust_enet_interface(ugeth);
+                               break;
+                       default:
+                               ugeth_warn
+                                   ("%s: Ack!  Speed (%d) is not 10/100/1000!",
+                                    dev->name, mii_info->speed);
+                               break;
+                       }
+
+                       ugeth_info("%s: Speed %dBT", dev->name,
+                                  mii_info->speed);
+
+                       ugeth->oldspeed = mii_info->speed;
+               }
+
+               if (!ugeth->oldlink) {
+                       ugeth_info("%s: Link is up", dev->name);
+                       ugeth->oldlink = 1;
+                       netif_carrier_on(dev);
+                       netif_schedule(dev);
+               }
+       } else {
+               if (ugeth->oldlink) {
+                       ugeth_info("%s: Link is down", dev->name);
+                       ugeth->oldlink = 0;
+                       ugeth->oldspeed = 0;
+                       ugeth->oldduplex = -1;
+                       netif_carrier_off(dev);
+               }
+       }
+}
+
+/* Configure the PHY for dev.
+ * returns 0 if success.  -1 if failure
+ */
+static int init_phy(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       struct phy_info *curphy;
+       ucc_mii_mng_t *mii_regs;
+       struct ugeth_mii_info *mii_info;
+       int err;
+
+       mii_regs = &ugeth->ug_regs->miimng;
+
+       ugeth->oldlink = 0;
+       ugeth->oldspeed = 0;
+       ugeth->oldduplex = -1;
+
+       mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL);
+
+       if (NULL == mii_info) {
+               ugeth_err("%s: Could not allocate mii_info", dev->name);
+               return -ENOMEM;
+       }
+
+       mii_info->mii_regs = mii_regs;
+       mii_info->speed = SPEED_1000;
+       mii_info->duplex = DUPLEX_FULL;
+       mii_info->pause = 0;
+       mii_info->link = 0;
+
+       mii_info->advertising = (ADVERTISED_10baseT_Half |
+                                ADVERTISED_10baseT_Full |
+                                ADVERTISED_100baseT_Half |
+                                ADVERTISED_100baseT_Full |
+                                ADVERTISED_1000baseT_Full);
+       mii_info->autoneg = 1;
+
+       mii_info->mii_id = ugeth->ug_info->phy_address;
+
+       mii_info->dev = dev;
+
+       mii_info->mdio_read = &read_phy_reg;
+       mii_info->mdio_write = &write_phy_reg;
+
+       ugeth->mii_info = mii_info;
+
+       spin_lock_irq(&ugeth->lock);
+
+       /* Set this UCC to be the master of the MII managment */
+       ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
+
+       if (init_mii_management_configuration(1,
+                                             ugeth->ug_info->
+                                             miiPreambleSupress,
+                                             &mii_regs->miimcfg,
+                                             &mii_regs->miimind)) {
+               ugeth_err("%s: The MII Bus is stuck!", dev->name);
+               err = -1;
+               goto bus_fail;
+       }
+
+       spin_unlock_irq(&ugeth->lock);
+
+       /* get info for this PHY */
+       curphy = get_phy_info(ugeth->mii_info);
+
+       if (curphy == NULL) {
+               ugeth_err("%s: No PHY found", dev->name);
+               err = -1;
+               goto no_phy;
+       }
+
+       mii_info->phyinfo = curphy;
+
+       /* Run the commands which initialize the PHY */
+       if (curphy->init) {
+               err = curphy->init(ugeth->mii_info);
+               if (err)
+                       goto phy_init_fail;
+       }
+
+       return 0;
+
+      phy_init_fail:
+      no_phy:
+      bus_fail:
+       kfree(mii_info);
+
+       return err;
+}
+
+#ifdef CONFIG_UGETH_TX_ON_DEMOND
+static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_transmit_on_demand(ugeth->uccf);
+
+       return 0;
+}
+#endif
+
+static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+       u32 temp;
+
+       uccf = ugeth->uccf;
+
+       /* Mask GRACEFUL STOP TX interrupt bit and clear it */
+       temp = in_be32(uccf->p_uccm);
+       temp &= ~UCCE_GRA;
+       out_be32(uccf->p_uccm, temp);
+       out_be32(uccf->p_ucce, UCCE_GRA);       /* clear by writing 1 */
+
+       /* Issue host command */
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
+                    (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+
+       /* Wait for command to complete */
+       do {
+               temp = in_be32(uccf->p_ucce);
+       } while (!(temp & UCCE_GRA));
+
+       uccf->stopped_tx = 1;
+
+       return 0;
+}
+
+static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+       u8 temp;
+
+       uccf = ugeth->uccf;
+
+       /* Clear acknowledge bit */
+       temp = ugeth->p_rx_glbl_pram->rxgstpack;
+       temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
+       ugeth->p_rx_glbl_pram->rxgstpack = temp;
+
+       /* Keep issuing command and checking acknowledge bit until
+       it is asserted, according to spec */
+       do {
+               /* Issue host command */
+               cecr_subblock =
+                   ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
+                                               ucc_num);
+               qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
+                            (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+
+               temp = ugeth->p_rx_glbl_pram->rxgstpack;
+       } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
+
+       uccf->stopped_rx = 1;
+
+       return 0;
+}
+
+static int ugeth_restart_tx(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+
+       uccf = ugeth->uccf;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+                    0);
+       uccf->stopped_tx = 0;
+
+       return 0;
+}
+
+static int ugeth_restart_rx(ucc_geth_private_t *ugeth)
+{
+       ucc_fast_private_t *uccf;
+       u32 cecr_subblock;
+
+       uccf = ugeth->uccf;
+
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+                    0);
+       uccf->stopped_rx = 0;
+
+       return 0;
+}
+
+static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode)
+{
+       ucc_fast_private_t *uccf;
+       int enabled_tx, enabled_rx;
+
+       uccf = ugeth->uccf;
+
+       /* check if the UCC number is in range. */
+       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+               ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       enabled_tx = uccf->enabled_tx;
+       enabled_rx = uccf->enabled_rx;
+
+       /* Get Tx and Rx going again, in case this channel was actively
+       disabled. */
+       if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
+               ugeth_restart_tx(ugeth);
+       if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
+               ugeth_restart_rx(ugeth);
+
+       ucc_fast_enable(uccf, mode);    /* OK to do even if not disabled */
+
+       return 0;
+
+}
+
+static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode)
+{
+       ucc_fast_private_t *uccf;
+
+       uccf = ugeth->uccf;
+
+       /* check if the UCC number is in range. */
+       if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+               ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Stop any transmissions */
+       if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
+               ugeth_graceful_stop_tx(ugeth);
+
+       /* Stop any receptions */
+       if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
+               ugeth_graceful_stop_rx(ugeth);
+
+       ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
+
+       return 0;
+}
+
+static void ugeth_dump_regs(ucc_geth_private_t *ugeth)
+{
+#ifdef DEBUG
+       ucc_fast_dump_regs(ugeth->uccf);
+       dump_regs(ugeth);
+       dump_bds(ugeth);
+#endif
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t *
+                                            p_UccGethTadParams,
+                                            qe_fltr_tad_t *qe_fltr_tad)
+{
+       u16 temp;
+
+       /* Zero serialized TAD */
+       memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);
+
+       qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V;   /* Must have this */
+       if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||
+           (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
+           || (p_UccGethTadParams->vnontag_op !=
+               UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)
+           )
+               qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;
+       if (p_UccGethTadParams->reject_frame)
+               qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;
+       temp =
+           (u16) (((u16) p_UccGethTadParams->
+                   vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);
+       qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */
+
+       qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff);     /* lower bits */
+       if (p_UccGethTadParams->vnontag_op ==
+           UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)
+               qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;
+       qe_fltr_tad->serialized[1] |=
+           p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;
+
+       qe_fltr_tad->serialized[2] |=
+           p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;
+       /* upper bits */
+       qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);
+       /* lower bits */
+       qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);
+
+       return 0;
+}
+
+static enet_addr_container_t
+    *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth,
+                                                enet_addr_t *p_enet_addr)
+{
+       enet_addr_container_t *enet_addr_cont;
+       struct list_head *p_lh;
+       u16 i, num;
+       int32_t j;
+       u8 *p_counter;
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+               p_lh = &ugeth->group_hash_q;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else {
+               p_lh = &ugeth->ind_hash_q;
+               p_counter = &(ugeth->numIndAddrInHash);
+       }
+
+       if (!p_lh)
+               return NULL;
+
+       num = *p_counter;
+
+       for (i = 0; i < num; i++) {
+               enet_addr_cont =
+                   (enet_addr_container_t *)
+                   ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
+               for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
+                       if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
+                               break;
+                       if (j == 0)
+                               return enet_addr_cont;  /* Found */
+               }
+               enqueue(p_lh, &enet_addr_cont->node);   /* Put it back */
+       }
+       return NULL;
+}
+
+static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth,
+                                                enet_addr_t *p_enet_addr)
+{
+       ucc_geth_enet_address_recognition_location_e location;
+       enet_addr_container_t *enet_addr_cont;
+       struct list_head *p_lh;
+       u8 i;
+       u32 limit;
+       u8 *p_counter;
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+               p_lh = &ugeth->group_hash_q;
+               limit = ugeth->ug_info->maxGroupAddrInHash;
+               location =
+                   UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else {
+               p_lh = &ugeth->ind_hash_q;
+               limit = ugeth->ug_info->maxIndAddrInHash;
+               location =
+                   UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;
+               p_counter = &(ugeth->numIndAddrInHash);
+       }
+
+       if ((enet_addr_cont =
+            ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {
+               list_add(p_lh, &enet_addr_cont->node);  /* Put it back */
+               return 0;
+       }
+       if ((!p_lh) || (!(*p_counter < limit)))
+               return -EBUSY;
+       if (!(enet_addr_cont = get_enet_addr_container()))
+               return -ENOMEM;
+       for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
+               (enet_addr_cont->address)[i] = (*p_enet_addr)[i];
+       enet_addr_cont->location = location;
+       enqueue(p_lh, &enet_addr_cont->node);   /* Put it back */
+       ++(*p_counter);
+
+       hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+
+       return 0;
+}
+
+static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth,
+                                                  enet_addr_t *p_enet_addr)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       enet_addr_container_t *enet_addr_cont;
+       ucc_fast_private_t *uccf;
+       comm_dir_e comm_dir;
+       u16 i, num;
+       struct list_head *p_lh;
+       u32 *addr_h, *addr_l;
+       u8 *p_counter;
+
+       uccf = ugeth->uccf;
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       if (!
+           (enet_addr_cont =
+            ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))
+               return -ENOENT;
+
+       /* It's been found and removed from the CQ. */
+       /* Now destroy its container */
+       put_enet_addr_container(enet_addr_cont);
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+               addr_h = &(p_82xx_addr_filt->gaddr_h);
+               addr_l = &(p_82xx_addr_filt->gaddr_l);
+               p_lh = &ugeth->group_hash_q;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else {
+               addr_h = &(p_82xx_addr_filt->iaddr_h);
+               addr_l = &(p_82xx_addr_filt->iaddr_l);
+               p_lh = &ugeth->ind_hash_q;
+               p_counter = &(ugeth->numIndAddrInHash);
+       }
+
+       comm_dir = 0;
+       if (uccf->enabled_tx)
+               comm_dir |= COMM_DIR_TX;
+       if (uccf->enabled_rx)
+               comm_dir |= COMM_DIR_RX;
+       if (comm_dir)
+               ugeth_disable(ugeth, comm_dir);
+
+       /* Clear the hash table. */
+       out_be32(addr_h, 0x00000000);
+       out_be32(addr_l, 0x00000000);
+
+       /* Add all remaining CQ elements back into hash */
+       num = --(*p_counter);
+       for (i = 0; i < num; i++) {
+               enet_addr_cont =
+                   (enet_addr_container_t *)
+                   ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
+               hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+               enqueue(p_lh, &enet_addr_cont->node);   /* Put it back */
+       }
+
+       if (comm_dir)
+               ugeth_enable(ugeth, comm_dir);
+
+       return 0;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t *
+                                                      ugeth,
+                                                      enet_addr_type_e
+                                                      enet_addr_type)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       ucc_fast_private_t *uccf;
+       comm_dir_e comm_dir;
+       struct list_head *p_lh;
+       u16 i, num;
+       u32 *addr_h, *addr_l;
+       u8 *p_counter;
+
+       uccf = ugeth->uccf;
+
+       p_82xx_addr_filt =
+           (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+           addressfiltering;
+
+       if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
+               addr_h = &(p_82xx_addr_filt->gaddr_h);
+               addr_l = &(p_82xx_addr_filt->gaddr_l);
+               p_lh = &ugeth->group_hash_q;
+               p_counter = &(ugeth->numGroupAddrInHash);
+       } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {
+               addr_h = &(p_82xx_addr_filt->iaddr_h);
+               addr_l = &(p_82xx_addr_filt->iaddr_l);
+               p_lh = &ugeth->ind_hash_q;
+               p_counter = &(ugeth->numIndAddrInHash);
+       } else
+               return -EINVAL;
+
+       comm_dir = 0;
+       if (uccf->enabled_tx)
+               comm_dir |= COMM_DIR_TX;
+       if (uccf->enabled_rx)
+               comm_dir |= COMM_DIR_RX;
+       if (comm_dir)
+               ugeth_disable(ugeth, comm_dir);
+
+       /* Clear the hash table. */
+       out_be32(addr_h, 0x00000000);
+       out_be32(addr_l, 0x00000000);
+
+       if (!p_lh)
+               return 0;
+
+       num = *p_counter;
+
+       /* Delete all remaining CQ elements */
+       for (i = 0; i < num; i++)
+               put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));
+
+       *p_counter = 0;
+
+       if (comm_dir)
+               ugeth_enable(ugeth, comm_dir);
+
+       return 0;
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth,
+                                                 enet_addr_t *p_enet_addr,
+                                                 u8 paddr_num)
+{
+       int i;
+
+       if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)
+               ugeth_warn
+                   ("%s: multicast address added to paddr will have no "
+                    "effect - is this what you wanted?",
+                    __FUNCTION__);
+
+       ugeth->indAddrRegUsed[paddr_num] = 1;   /* mark this paddr as used */
+       /* store address in our database */
+       for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
+               ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];
+       /* put in hardware */
+       return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth,
+                                                   u8 paddr_num)
+{
+       ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
+       return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
+}
+
+static void ucc_geth_memclean(ucc_geth_private_t *ugeth)
+{
+       u16 i, j;
+       u8 *bd;
+
+       if (!ugeth)
+               return;
+
+       if (ugeth->uccf)
+               ucc_fast_free(ugeth->uccf);
+
+       if (ugeth->p_thread_data_tx) {
+               qe_muram_free(ugeth->thread_dat_tx_offset);
+               ugeth->p_thread_data_tx = NULL;
+       }
+       if (ugeth->p_thread_data_rx) {
+               qe_muram_free(ugeth->thread_dat_rx_offset);
+               ugeth->p_thread_data_rx = NULL;
+       }
+       if (ugeth->p_exf_glbl_param) {
+               qe_muram_free(ugeth->exf_glbl_param_offset);
+               ugeth->p_exf_glbl_param = NULL;
+       }
+       if (ugeth->p_rx_glbl_pram) {
+               qe_muram_free(ugeth->rx_glbl_pram_offset);
+               ugeth->p_rx_glbl_pram = NULL;
+       }
+       if (ugeth->p_tx_glbl_pram) {
+               qe_muram_free(ugeth->tx_glbl_pram_offset);
+               ugeth->p_tx_glbl_pram = NULL;
+       }
+       if (ugeth->p_send_q_mem_reg) {
+               qe_muram_free(ugeth->send_q_mem_reg_offset);
+               ugeth->p_send_q_mem_reg = NULL;
+       }
+       if (ugeth->p_scheduler) {
+               qe_muram_free(ugeth->scheduler_offset);
+               ugeth->p_scheduler = NULL;
+       }
+       if (ugeth->p_tx_fw_statistics_pram) {
+               qe_muram_free(ugeth->tx_fw_statistics_pram_offset);
+               ugeth->p_tx_fw_statistics_pram = NULL;
+       }
+       if (ugeth->p_rx_fw_statistics_pram) {
+               qe_muram_free(ugeth->rx_fw_statistics_pram_offset);
+               ugeth->p_rx_fw_statistics_pram = NULL;
+       }
+       if (ugeth->p_rx_irq_coalescing_tbl) {
+               qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset);
+               ugeth->p_rx_irq_coalescing_tbl = NULL;
+       }
+       if (ugeth->p_rx_bd_qs_tbl) {
+               qe_muram_free(ugeth->rx_bd_qs_tbl_offset);
+               ugeth->p_rx_bd_qs_tbl = NULL;
+       }
+       if (ugeth->p_init_enet_param_shadow) {
+               return_init_enet_entries(ugeth,
+                                        &(ugeth->p_init_enet_param_shadow->
+                                          rxthread[0]),
+                                        ENET_INIT_PARAM_MAX_ENTRIES_RX,
+                                        ugeth->ug_info->riscRx, 1);
+               return_init_enet_entries(ugeth,
+                                        &(ugeth->p_init_enet_param_shadow->
+                                          txthread[0]),
+                                        ENET_INIT_PARAM_MAX_ENTRIES_TX,
+                                        ugeth->ug_info->riscTx, 0);
+               kfree(ugeth->p_init_enet_param_shadow);
+               ugeth->p_init_enet_param_shadow = NULL;
+       }
+       for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+               bd = ugeth->p_tx_bd_ring[i];
+               for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
+                       if (ugeth->tx_skbuff[i][j]) {
+                               dma_unmap_single(NULL,
+                                                BD_BUFFER_ARG(bd),
+                                                (BD_STATUS_AND_LENGTH(bd) &
+                                                 BD_LENGTH_MASK),
+                                                DMA_TO_DEVICE);
+                               dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
+                               ugeth->tx_skbuff[i][j] = NULL;
+                       }
+               }
+
+               kfree(ugeth->tx_skbuff[i]);
+
+               if (ugeth->p_tx_bd_ring[i]) {
+                       if (ugeth->ug_info->uf_info.bd_mem_part ==
+                           MEM_PART_SYSTEM)
+                               kfree((void *)ugeth->tx_bd_ring_offset[i]);
+                       else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                                MEM_PART_MURAM)
+                               qe_muram_free(ugeth->tx_bd_ring_offset[i]);
+                       ugeth->p_tx_bd_ring[i] = NULL;
+               }
+       }
+       for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+               if (ugeth->p_rx_bd_ring[i]) {
+                       /* Return existing data buffers in ring */
+                       bd = ugeth->p_rx_bd_ring[i];
+                       for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
+                               if (ugeth->rx_skbuff[i][j]) {
+                                       dma_unmap_single(NULL, BD_BUFFER(bd),
+                                                ugeth->ug_info->
+                                                uf_info.
+                                                max_rx_buf_length +
+                                                UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+                                                DMA_FROM_DEVICE);
+
+                                       dev_kfree_skb_any(ugeth->
+                                                         rx_skbuff[i][j]);
+                                       ugeth->rx_skbuff[i][j] = NULL;
+                               }
+                               bd += UCC_GETH_SIZE_OF_BD;
+                       }
+
+                       kfree(ugeth->rx_skbuff[i]);
+
+                       if (ugeth->ug_info->uf_info.bd_mem_part ==
+                           MEM_PART_SYSTEM)
+                               kfree((void *)ugeth->rx_bd_ring_offset[i]);
+                       else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                                MEM_PART_MURAM)
+                               qe_muram_free(ugeth->rx_bd_ring_offset[i]);
+                       ugeth->p_rx_bd_ring[i] = NULL;
+               }
+       }
+       while (!list_empty(&ugeth->group_hash_q))
+               put_enet_addr_container(ENET_ADDR_CONT_ENTRY
+                                       (dequeue(&ugeth->group_hash_q)));
+       while (!list_empty(&ugeth->ind_hash_q))
+               put_enet_addr_container(ENET_ADDR_CONT_ENTRY
+                                       (dequeue(&ugeth->ind_hash_q)));
+
+}
+
+static void ucc_geth_set_multi(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth;
+       struct dev_mc_list *dmi;
+       ucc_fast_t *uf_regs;
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       enet_addr_t tempaddr;
+       u8 *mcptr, *tdptr;
+       int i, j;
+
+       ugeth = netdev_priv(dev);
+
+       uf_regs = ugeth->uccf->uf_regs;
+
+       if (dev->flags & IFF_PROMISC) {
+
+               /* Log any net taps. */
+               printk("%s: Promiscuous mode enabled.\n", dev->name);
+               uf_regs->upsmr |= UPSMR_PRO;
+
+       } else {
+
+               uf_regs->upsmr &= ~UPSMR_PRO;
+
+               p_82xx_addr_filt =
+                   (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+                   p_rx_glbl_pram->addressfiltering;
+
+               if (dev->flags & IFF_ALLMULTI) {
+                       /* Catch all multicast addresses, so set the
+                        * filter to all 1's.
+                        */
+                       out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff);
+                       out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff);
+               } else {
+                       /* Clear filter and add the addresses in the list.
+                        */
+                       out_be32(&p_82xx_addr_filt->gaddr_h, 0x0);
+                       out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
+
+                       dmi = dev->mc_list;
+
+                       for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) {
+
+                               /* Only support group multicast for now.
+                                */
+                               if (!(dmi->dmi_addr[0] & 1))
+                                       continue;
+
+                               /* The address in dmi_addr is LSB first,
+                                * and taddr is MSB first.  We have to
+                                * copy bytes MSB first from dmi_addr.
+                                */
+                               mcptr = (u8 *) dmi->dmi_addr + 5;
+                               tdptr = (u8 *) & tempaddr;
+                               for (j = 0; j < 6; j++)
+                                       *tdptr++ = *mcptr--;
+
+                               /* Ask CPM to run CRC and set bit in
+                                * filter mask.
+                                */
+                               hw_add_addr_in_hash(ugeth, &tempaddr);
+
+                       }
+               }
+       }
+}
+
+static void ucc_geth_stop(ucc_geth_private_t *ugeth)
+{
+       ucc_geth_t *ug_regs = ugeth->ug_regs;
+       u32 tempval;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       /* Disable the controller */
+       ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+       /* Tell the kernel the link is down */
+       ugeth->mii_info->link = 0;
+       adjust_link(ugeth->dev);
+
+       /* Mask all interrupts */
+       out_be32(ugeth->uccf->p_ucce, 0x00000000);
+
+       /* Clear all interrupts */
+       out_be32(ugeth->uccf->p_ucce, 0xffffffff);
+
+       /* Disable Rx and Tx */
+       tempval = in_be32(&ug_regs->maccfg1);
+       tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
+       out_be32(&ug_regs->maccfg1, tempval);
+
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+               /* Clear any pending interrupts */
+               mii_clear_phy_interrupt(ugeth->mii_info);
+
+               /* Disable PHY Interrupts */
+               mii_configure_phy_interrupt(ugeth->mii_info,
+                                           MII_INTERRUPT_DISABLED);
+       }
+
+       free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
+
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+               free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev);
+       } else {
+               del_timer_sync(&ugeth->phy_info_timer);
+       }
+
+       ucc_geth_memclean(ugeth);
+}
+
+static int ucc_geth_startup(ucc_geth_private_t *ugeth)
+{
+       ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+       ucc_geth_init_pram_t *p_init_enet_pram;
+       ucc_fast_private_t *uccf;
+       ucc_geth_info_t *ug_info;
+       ucc_fast_info_t *uf_info;
+       ucc_fast_t *uf_regs;
+       ucc_geth_t *ug_regs;
+       int ret_val = -EINVAL;
+       u32 remoder = UCC_GETH_REMODER_INIT;
+       u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
+       u32 ifstat, i, j, size, l2qt, l3qt, length;
+       u16 temoder = UCC_GETH_TEMODER_INIT;
+       u16 test;
+       u8 function_code = 0;
+       u8 *bd, *endOfRing;
+       u8 numThreadsRxNumerical, numThreadsTxNumerical;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ug_info = ugeth->ug_info;
+       uf_info = &ug_info->uf_info;
+
+       if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) ||
+             (uf_info->bd_mem_part == MEM_PART_MURAM))) {
+               ugeth_err("%s: Bad memory partition value.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Rx BD lengths */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
+                   (ug_info->bdRingLenRx[i] %
+                    UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
+                       ugeth_err
+                           ("%s: Rx BD ring length must be multiple of 4,"
+                               " no smaller than 8.", __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       /* Tx BD lengths */
+       for (i = 0; i < ug_info->numQueuesTx; i++) {
+               if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
+                       ugeth_err
+                           ("%s: Tx BD ring length must be no smaller than 2.",
+                            __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       /* mrblr */
+       if ((uf_info->max_rx_buf_length == 0) ||
+           (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
+               ugeth_err
+                   ("%s: max_rx_buf_length must be non-zero multiple of 128.",
+                    __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* num Tx queues */
+       if (ug_info->numQueuesTx > NUM_TX_QUEUES) {
+               ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* num Rx queues */
+       if (ug_info->numQueuesRx > NUM_RX_QUEUES) {
+               ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* l2qt */
+       for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
+               if (ug_info->l2qt[i] >= ug_info->numQueuesRx) {
+                       ugeth_err
+                           ("%s: VLAN priority table entry must not be"
+                               " larger than number of Rx queues.",
+                            __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       /* l3qt */
+       for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
+               if (ug_info->l3qt[i] >= ug_info->numQueuesRx) {
+                       ugeth_err
+                           ("%s: IP priority table entry must not be"
+                               " larger than number of Rx queues.",
+                            __FUNCTION__);
+                       return -EINVAL;
+               }
+       }
+
+       if (ug_info->cam && !ug_info->ecamptr) {
+               ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
+                         __FUNCTION__);
+               return -EINVAL;
+       }
+
+       if ((ug_info->numStationAddresses !=
+            UCC_GETH_NUM_OF_STATION_ADDRESSES_1)
+           && ug_info->rxExtendedFiltering) {
+               ugeth_err("%s: Number of station addresses greater than 1 "
+                         "not allowed in extended parsing mode.",
+                         __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Generate uccm_mask for receive */
+       uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
+       for (i = 0; i < ug_info->numQueuesRx; i++)
+               uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
+
+       for (i = 0; i < ug_info->numQueuesTx; i++)
+               uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
+       /* Initialize the general fast UCC block. */
+       if (ucc_fast_init(uf_info, &uccf)) {
+               ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       ugeth->uccf = uccf;
+
+       switch (ug_info->numThreadsRx) {
+       case UCC_GETH_NUM_OF_THREADS_1:
+               numThreadsRxNumerical = 1;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_2:
+               numThreadsRxNumerical = 2;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_4:
+               numThreadsRxNumerical = 4;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_6:
+               numThreadsRxNumerical = 6;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_8:
+               numThreadsRxNumerical = 8;
+               break;
+       default:
+               ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -EINVAL;
+               break;
+       }
+
+       switch (ug_info->numThreadsTx) {
+       case UCC_GETH_NUM_OF_THREADS_1:
+               numThreadsTxNumerical = 1;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_2:
+               numThreadsTxNumerical = 2;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_4:
+               numThreadsTxNumerical = 4;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_6:
+               numThreadsTxNumerical = 6;
+               break;
+       case UCC_GETH_NUM_OF_THREADS_8:
+               numThreadsTxNumerical = 8;
+               break;
+       default:
+               ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -EINVAL;
+               break;
+       }
+
+       /* Calculate rx_extended_features */
+       ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck ||
+           ug_info->ipAddressAlignment ||
+           (ug_info->numStationAddresses !=
+            UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
+
+       ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
+           (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
+           || (ug_info->vlanOperationNonTagged !=
+               UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
+
+       uf_regs = uccf->uf_regs;
+       ug_regs = (ucc_geth_t *) (uccf->uf_regs);
+       ugeth->ug_regs = ug_regs;
+
+       init_default_reg_vals(&uf_regs->upsmr,
+                             &ug_regs->maccfg1, &ug_regs->maccfg2);
+
+       /*                    Set UPSMR                      */
+       /* For more details see the hardware spec.           */
+       init_rx_parameters(ug_info->bro,
+                          ug_info->rsh, ug_info->pro, &uf_regs->upsmr);
+
+       /* We're going to ignore other registers for now, */
+       /* except as needed to get up and running         */
+
+       /*                    Set MACCFG1                    */
+       /* For more details see the hardware spec.           */
+       init_flow_control_params(ug_info->aufc,
+                                ug_info->receiveFlowControl,
+                                1,
+                                ug_info->pausePeriod,
+                                ug_info->extensionField,
+                                &uf_regs->upsmr,
+                                &ug_regs->uempr, &ug_regs->maccfg1);
+
+       maccfg1 = in_be32(&ug_regs->maccfg1);
+       maccfg1 |= MACCFG1_ENABLE_RX;
+       maccfg1 |= MACCFG1_ENABLE_TX;
+       out_be32(&ug_regs->maccfg1, maccfg1);
+
+       /*                    Set IPGIFG                     */
+       /* For more details see the hardware spec.           */
+       ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1,
+                                             ug_info->nonBackToBackIfgPart2,
+                                             ug_info->
+                                             miminumInterFrameGapEnforcement,
+                                             ug_info->backToBackInterFrameGap,
+                                             &ug_regs->ipgifg);
+       if (ret_val != 0) {
+               ugeth_err("%s: IPGIFG initialization parameter too large.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       /*                    Set HAFDUP                     */
+       /* For more details see the hardware spec.           */
+       ret_val = init_half_duplex_params(ug_info->altBeb,
+                                         ug_info->backPressureNoBackoff,
+                                         ug_info->noBackoff,
+                                         ug_info->excessDefer,
+                                         ug_info->altBebTruncation,
+                                         ug_info->maxRetransmission,
+                                         ug_info->collisionWindow,
+                                         &ug_regs->hafdup);
+       if (ret_val != 0) {
+               ugeth_err("%s: Half Duplex initialization parameter too large.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       /*                    Set IFSTAT                     */
+       /* For more details see the hardware spec.           */
+       /* Read only - resets upon read                      */
+       ifstat = in_be32(&ug_regs->ifstat);
+
+       /*                    Clear UEMPR                    */
+       /* For more details see the hardware spec.           */
+       out_be32(&ug_regs->uempr, 0);
+
+       /*                    Set UESCR                      */
+       /* For more details see the hardware spec.           */
+       init_hw_statistics_gathering_mode((ug_info->statisticsMode &
+                               UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
+                               0, &uf_regs->upsmr, &ug_regs->uescr);
+
+       /* Allocate Tx bds */
+       for (j = 0; j < ug_info->numQueuesTx; j++) {
+               /* Allocate in multiple of
+                  UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
+                  according to spec */
+               length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD)
+                         / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+                   * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+               if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) %
+                   UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+                       length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+               if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+                       u32 align = 4;
+                       if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4)
+                               align = UCC_GETH_TX_BD_RING_ALIGNMENT;
+                       ugeth->tx_bd_ring_offset[j] =
+                               (u32) (kmalloc((u32) (length + align),
+                               GFP_KERNEL));
+                       if (ugeth->tx_bd_ring_offset[j] != 0)
+                               ugeth->p_tx_bd_ring[j] =
+                                       (void*)((ugeth->tx_bd_ring_offset[j] +
+                                       align) & ~(align - 1));
+               } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+                       ugeth->tx_bd_ring_offset[j] =
+                           qe_muram_alloc(length,
+                                          UCC_GETH_TX_BD_RING_ALIGNMENT);
+                       if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j]))
+                               ugeth->p_tx_bd_ring[j] =
+                                   (u8 *) qe_muram_addr(ugeth->
+                                                        tx_bd_ring_offset[j]);
+               }
+               if (!ugeth->p_tx_bd_ring[j]) {
+                       ugeth_err
+                           ("%s: Can not allocate memory for Tx bd rings.",
+                            __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+               /* Zero unused end of bd ring, according to spec */
+               memset(ugeth->p_tx_bd_ring[j] +
+                      ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0,
+                      length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD);
+       }
+
+       /* Allocate Rx bds */
+       for (j = 0; j < ug_info->numQueuesRx; j++) {
+               length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD;
+               if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+                       u32 align = 4;
+                       if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
+                               align = UCC_GETH_RX_BD_RING_ALIGNMENT;
+                       ugeth->rx_bd_ring_offset[j] =
+                           (u32) (kmalloc((u32) (length + align), GFP_KERNEL));
+                       if (ugeth->rx_bd_ring_offset[j] != 0)
+                               ugeth->p_rx_bd_ring[j] =
+                                       (void*)((ugeth->rx_bd_ring_offset[j] +
+                                       align) & ~(align - 1));
+               } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+                       ugeth->rx_bd_ring_offset[j] =
+                           qe_muram_alloc(length,
+                                          UCC_GETH_RX_BD_RING_ALIGNMENT);
+                       if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j]))
+                               ugeth->p_rx_bd_ring[j] =
+                                   (u8 *) qe_muram_addr(ugeth->
+                                                        rx_bd_ring_offset[j]);
+               }
+               if (!ugeth->p_rx_bd_ring[j]) {
+                       ugeth_err
+                           ("%s: Can not allocate memory for Rx bd rings.",
+                            __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+       }
+
+       /* Init Tx bds */
+       for (j = 0; j < ug_info->numQueuesTx; j++) {
+               /* Setup the skbuff rings */
+               ugeth->tx_skbuff[j] =
+                   (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
+                                              ugeth->ug_info->bdRingLenTx[j],
+                                              GFP_KERNEL);
+
+               if (ugeth->tx_skbuff[j] == NULL) {
+                       ugeth_err("%s: Could not allocate tx_skbuff",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++)
+                       ugeth->tx_skbuff[j][i] = NULL;
+
+               ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
+               bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
+               for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
+                       BD_BUFFER_CLEAR(bd);
+                       BD_STATUS_AND_LENGTH_SET(bd, 0);
+                       bd += UCC_GETH_SIZE_OF_BD;
+               }
+               bd -= UCC_GETH_SIZE_OF_BD;
+               BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */
+       }
+
+       /* Init Rx bds */
+       for (j = 0; j < ug_info->numQueuesRx; j++) {
+               /* Setup the skbuff rings */
+               ugeth->rx_skbuff[j] =
+                   (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
+                                              ugeth->ug_info->bdRingLenRx[j],
+                                              GFP_KERNEL);
+
+               if (ugeth->rx_skbuff[j] == NULL) {
+                       ugeth_err("%s: Could not allocate rx_skbuff",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++)
+                       ugeth->rx_skbuff[j][i] = NULL;
+
+               ugeth->skb_currx[j] = 0;
+               bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
+               for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
+                       BD_STATUS_AND_LENGTH_SET(bd, R_I);
+                       BD_BUFFER_CLEAR(bd);
+                       bd += UCC_GETH_SIZE_OF_BD;
+               }
+               bd -= UCC_GETH_SIZE_OF_BD;
+               BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */
+       }
+
+       /*
+        * Global PRAM
+        */
+       /* Tx global PRAM */
+       /* Allocate global tx parameter RAM page */
+       ugeth->tx_glbl_pram_offset =
+           qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t),
+                          UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       ugeth->p_tx_glbl_pram =
+           (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth->
+                                                       tx_glbl_pram_offset);
+       /* Zero out p_tx_glbl_pram */
+       memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t));
+
+       /* Fill global PRAM */
+
+       /* TQPTR */
+       /* Size varies with number of Tx threads */
+       ugeth->thread_dat_tx_offset =
+           qe_muram_alloc(numThreadsTxNumerical *
+                          sizeof(ucc_geth_thread_data_tx_t) +
+                          32 * (numThreadsTxNumerical == 1),
+                          UCC_GETH_THREAD_DATA_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_thread_data_tx =
+           (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth->
+                                                       thread_dat_tx_offset);
+       out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
+
+       /* vtagtable */
+       for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++)
+               out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i],
+                        ug_info->vtagtable[i]);
+
+       /* iphoffset */
+       for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++)
+               ugeth->p_tx_glbl_pram->iphoffset[i] = ug_info->iphoffset[i];
+
+       /* SQPTR */
+       /* Size varies with number of Tx queues */
+       ugeth->send_q_mem_reg_offset =
+           qe_muram_alloc(ug_info->numQueuesTx *
+                          sizeof(ucc_geth_send_queue_qd_t),
+                          UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_send_q_mem_reg =
+           (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth->
+                       send_q_mem_reg_offset);
+       out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
+
+       /* Setup the table */
+       /* Assume BD rings are already established */
+       for (i = 0; i < ug_info->numQueuesTx; i++) {
+               endOfRing =
+                   ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
+                                             1) * UCC_GETH_SIZE_OF_BD;
+               if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
+                                (u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
+                                last_bd_completed_address,
+                                (u32) virt_to_phys(endOfRing));
+               } else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                          MEM_PART_MURAM) {
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
+                                (u32) immrbar_virt_to_phys(ugeth->
+                                                           p_tx_bd_ring[i]));
+                       out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
+                                last_bd_completed_address,
+                                (u32) immrbar_virt_to_phys(endOfRing));
+               }
+       }
+
+       /* schedulerbasepointer */
+
+       if (ug_info->numQueuesTx > 1) {
+       /* scheduler exists only if more than 1 tx queue */
+               ugeth->scheduler_offset =
+                   qe_muram_alloc(sizeof(ucc_geth_scheduler_t),
+                                  UCC_GETH_SCHEDULER_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->scheduler_offset)) {
+                       ugeth_err
+                        ("%s: Can not allocate DPRAM memory for p_scheduler.",
+                            __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               ugeth->p_scheduler =
+                   (ucc_geth_scheduler_t *) qe_muram_addr(ugeth->
+                                                          scheduler_offset);
+               out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
+                        ugeth->scheduler_offset);
+               /* Zero out p_scheduler */
+               memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t));
+
+               /* Set values in scheduler */
+               out_be32(&ugeth->p_scheduler->mblinterval,
+                        ug_info->mblinterval);
+               out_be16(&ugeth->p_scheduler->nortsrbytetime,
+                        ug_info->nortsrbytetime);
+               ugeth->p_scheduler->fracsiz = ug_info->fracsiz;
+               ugeth->p_scheduler->strictpriorityq = ug_info->strictpriorityq;
+               ugeth->p_scheduler->txasap = ug_info->txasap;
+               ugeth->p_scheduler->extrabw = ug_info->extrabw;
+               for (i = 0; i < NUM_TX_QUEUES; i++)
+                       ugeth->p_scheduler->weightfactor[i] =
+                           ug_info->weightfactor[i];
+
+               /* Set pointers to cpucount registers in scheduler */
+               ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0);
+               ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1);
+               ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2);
+               ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3);
+               ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4);
+               ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5);
+               ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6);
+               ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7);
+       }
+
+       /* schedulerbasepointer */
+       /* TxRMON_PTR (statistics) */
+       if (ug_info->
+           statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
+               ugeth->tx_fw_statistics_pram_offset =
+                   qe_muram_alloc(sizeof
+                                  (ucc_geth_tx_firmware_statistics_pram_t),
+                                  UCC_GETH_TX_STATISTICS_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) {
+                       ugeth_err
+                           ("%s: Can not allocate DPRAM memory for"
+                               " p_tx_fw_statistics_pram.", __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+               ugeth->p_tx_fw_statistics_pram =
+                   (ucc_geth_tx_firmware_statistics_pram_t *)
+                   qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
+               /* Zero out p_tx_fw_statistics_pram */
+               memset(ugeth->p_tx_fw_statistics_pram,
+                      0, sizeof(ucc_geth_tx_firmware_statistics_pram_t));
+       }
+
+       /* temoder */
+       /* Already has speed set */
+
+       if (ug_info->numQueuesTx > 1)
+               temoder |= TEMODER_SCHEDULER_ENABLE;
+       if (ug_info->ipCheckSumGenerate)
+               temoder |= TEMODER_IP_CHECKSUM_GENERATE;
+       temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT);
+       out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder);
+
+       test = in_be16(&ugeth->p_tx_glbl_pram->temoder);
+
+       /* Function code register value to be used later */
+       function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL;
+       /* Required for QE */
+
+       /* function code register */
+       out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24);
+
+       /* Rx global PRAM */
+       /* Allocate global rx parameter RAM page */
+       ugeth->rx_glbl_pram_offset =
+           qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t),
+                          UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       ugeth->p_rx_glbl_pram =
+           (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth->
+                                                       rx_glbl_pram_offset);
+       /* Zero out p_rx_glbl_pram */
+       memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t));
+
+       /* Fill global PRAM */
+
+       /* RQPTR */
+       /* Size varies with number of Rx threads */
+       ugeth->thread_dat_rx_offset =
+           qe_muram_alloc(numThreadsRxNumerical *
+                          sizeof(ucc_geth_thread_data_rx_t),
+                          UCC_GETH_THREAD_DATA_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_thread_data_rx =
+           (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth->
+                                                       thread_dat_rx_offset);
+       out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
+
+       /* typeorlen */
+       out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen);
+
+       /* rxrmonbaseptr (statistics) */
+       if (ug_info->
+           statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
+               ugeth->rx_fw_statistics_pram_offset =
+                   qe_muram_alloc(sizeof
+                                  (ucc_geth_rx_firmware_statistics_pram_t),
+                                  UCC_GETH_RX_STATISTICS_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) {
+                       ugeth_err
+                               ("%s: Can not allocate DPRAM memory for"
+                               " p_rx_fw_statistics_pram.", __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+               ugeth->p_rx_fw_statistics_pram =
+                   (ucc_geth_rx_firmware_statistics_pram_t *)
+                   qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
+               /* Zero out p_rx_fw_statistics_pram */
+               memset(ugeth->p_rx_fw_statistics_pram, 0,
+                      sizeof(ucc_geth_rx_firmware_statistics_pram_t));
+       }
+
+       /* intCoalescingPtr */
+
+       /* Size varies with number of Rx queues */
+       ugeth->rx_irq_coalescing_tbl_offset =
+           qe_muram_alloc(ug_info->numQueuesRx *
+                          sizeof(ucc_geth_rx_interrupt_coalescing_entry_t),
+                          UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for"
+                       " p_rx_irq_coalescing_tbl.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_rx_irq_coalescing_tbl =
+           (ucc_geth_rx_interrupt_coalescing_table_t *)
+           qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
+       out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
+                ugeth->rx_irq_coalescing_tbl_offset);
+
+       /* Fill interrupt coalescing table */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
+                        interruptcoalescingmaxvalue,
+                        ug_info->interruptcoalescingmaxvalue[i]);
+               out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
+                        interruptcoalescingcounter,
+                        ug_info->interruptcoalescingmaxvalue[i]);
+       }
+
+       /* MRBLR */
+       init_max_rx_buff_len(uf_info->max_rx_buf_length,
+                            &ugeth->p_rx_glbl_pram->mrblr);
+       /* MFLR */
+       out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength);
+       /* MINFLR */
+       init_min_frame_len(ug_info->minFrameLength,
+                          &ugeth->p_rx_glbl_pram->minflr,
+                          &ugeth->p_rx_glbl_pram->mrblr);
+       /* MAXD1 */
+       out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length);
+       /* MAXD2 */
+       out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length);
+
+       /* l2qt */
+       l2qt = 0;
+       for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++)
+               l2qt |= (ug_info->l2qt[i] << (28 - 4 * i));
+       out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt);
+
+       /* l3qt */
+       for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) {
+               l3qt = 0;
+               for (i = 0; i < 8; i++)
+                       l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
+               out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt);
+       }
+
+       /* vlantype */
+       out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype);
+
+       /* vlantci */
+       out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci);
+
+       /* ecamptr */
+       out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr);
+
+       /* RBDQPTR */
+       /* Size varies with number of Rx queues */
+       ugeth->rx_bd_qs_tbl_offset =
+           qe_muram_alloc(ug_info->numQueuesRx *
+                          (sizeof(ucc_geth_rx_bd_queues_entry_t) +
+                           sizeof(ucc_geth_rx_prefetched_bds_t)),
+                          UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
+       if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+
+       ugeth->p_rx_bd_qs_tbl =
+           (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth->
+                                   rx_bd_qs_tbl_offset);
+       out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
+       /* Zero out p_rx_bd_qs_tbl */
+       memset(ugeth->p_rx_bd_qs_tbl,
+              0,
+              ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) +
+                                      sizeof(ucc_geth_rx_prefetched_bds_t)));
+
+       /* Setup the table */
+       /* Assume BD rings are already established */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
+                       out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+                                (u32) virt_to_phys(ugeth->p_rx_bd_ring[i]));
+               } else if (ugeth->ug_info->uf_info.bd_mem_part ==
+                          MEM_PART_MURAM) {
+                       out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+                                (u32) immrbar_virt_to_phys(ugeth->
+                                                           p_rx_bd_ring[i]));
+               }
+               /* rest of fields handled by QE */
+       }
+
+       /* remoder */
+       /* Already has speed set */
+
+       if (ugeth->rx_extended_features)
+               remoder |= REMODER_RX_EXTENDED_FEATURES;
+       if (ug_info->rxExtendedFiltering)
+               remoder |= REMODER_RX_EXTENDED_FILTERING;
+       if (ug_info->dynamicMaxFrameLength)
+               remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH;
+       if (ug_info->dynamicMinFrameLength)
+               remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH;
+       remoder |=
+           ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT;
+       remoder |=
+           ug_info->
+           vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT;
+       remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT;
+       remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT);
+       if (ug_info->ipCheckSumCheck)
+               remoder |= REMODER_IP_CHECKSUM_CHECK;
+       if (ug_info->ipAddressAlignment)
+               remoder |= REMODER_IP_ADDRESS_ALIGNMENT;
+       out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder);
+
+       /* Note that this function must be called */
+       /* ONLY AFTER p_tx_fw_statistics_pram */
+       /* andp_UccGethRxFirmwareStatisticsPram are allocated ! */
+       init_firmware_statistics_gathering_mode((ug_info->
+               statisticsMode &
+               UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX),
+               (ug_info->statisticsMode &
+               UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX),
+               &ugeth->p_tx_glbl_pram->txrmonbaseptr,
+               ugeth->tx_fw_statistics_pram_offset,
+               &ugeth->p_rx_glbl_pram->rxrmonbaseptr,
+               ugeth->rx_fw_statistics_pram_offset,
+               &ugeth->p_tx_glbl_pram->temoder,
+               &ugeth->p_rx_glbl_pram->remoder);
+
+       /* function code register */
+       ugeth->p_rx_glbl_pram->rstate = function_code;
+
+       /* initialize extended filtering */
+       if (ug_info->rxExtendedFiltering) {
+               if (!ug_info->extendedFilteringChainPointer) {
+                       ugeth_err("%s: Null Extended Filtering Chain Pointer.",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -EINVAL;
+               }
+
+               /* Allocate memory for extended filtering Mode Global
+               Parameters */
+               ugeth->exf_glbl_param_offset =
+                   qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t),
+               UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
+               if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) {
+                       ugeth_err
+                               ("%s: Can not allocate DPRAM memory for"
+                               " p_exf_glbl_param.", __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return -ENOMEM;
+               }
+
+               ugeth->p_exf_glbl_param =
+                   (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth->
+                                exf_glbl_param_offset);
+               out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam,
+                        ugeth->exf_glbl_param_offset);
+               out_be32(&ugeth->p_exf_glbl_param->l2pcdptr,
+                        (u32) ug_info->extendedFilteringChainPointer);
+
+       } else {                /* initialize 82xx style address filtering */
+
+               /* Init individual address recognition registers to disabled */
+
+               for (j = 0; j < NUM_OF_PADDRS; j++)
+                       ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j);
+
+               /* Create CQs for hash tables */
+               if (ug_info->maxGroupAddrInHash > 0) {
+                       INIT_LIST_HEAD(&ugeth->group_hash_q);
+               }
+               if (ug_info->maxIndAddrInHash > 0) {
+                       INIT_LIST_HEAD(&ugeth->ind_hash_q);
+               }
+               p_82xx_addr_filt =
+                   (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+                   p_rx_glbl_pram->addressfiltering;
+
+               ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
+                       ENET_ADDR_TYPE_GROUP);
+               ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
+                       ENET_ADDR_TYPE_INDIVIDUAL);
+       }
+
+       /*
+        * Initialize UCC at QE level
+        */
+
+       command = QE_INIT_TX_RX;
+
+       /* Allocate shadow InitEnet command parameter structure.
+        * This is needed because after the InitEnet command is executed,
+        * the structure in DPRAM is released, because DPRAM is a premium
+        * resource.
+        * This shadow structure keeps a copy of what was done so that the
+        * allocated resources can be released when the channel is freed.
+        */
+       if (!(ugeth->p_init_enet_param_shadow =
+            (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t),
+                                             GFP_KERNEL))) {
+               ugeth_err
+                   ("%s: Can not allocate memory for"
+                       " p_UccInitEnetParamShadows.", __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       /* Zero out *p_init_enet_param_shadow */
+       memset((char *)ugeth->p_init_enet_param_shadow,
+              0, sizeof(ucc_geth_init_pram_t));
+
+       /* Fill shadow InitEnet command parameter structure */
+
+       ugeth->p_init_enet_param_shadow->resinit1 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT1;
+       ugeth->p_init_enet_param_shadow->resinit2 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT2;
+       ugeth->p_init_enet_param_shadow->resinit3 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT3;
+       ugeth->p_init_enet_param_shadow->resinit4 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT4;
+       ugeth->p_init_enet_param_shadow->resinit5 =
+           ENET_INIT_PARAM_MAGIC_RES_INIT5;
+       ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+           ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT;
+       ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+           ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT;
+
+       ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+           ugeth->rx_glbl_pram_offset | ug_info->riscRx;
+       if ((ug_info->largestexternallookupkeysize !=
+            QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE)
+           && (ug_info->largestexternallookupkeysize !=
+               QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+           && (ug_info->largestexternallookupkeysize !=
+               QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
+               ugeth_err("%s: Invalid largest External Lookup Key Size.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -EINVAL;
+       }
+       ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
+           ug_info->largestexternallookupkeysize;
+       size = sizeof(ucc_geth_thread_rx_pram_t);
+       if (ug_info->rxExtendedFiltering) {
+               size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
+               if (ug_info->largestexternallookupkeysize ==
+                   QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+                       size +=
+                           THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
+               if (ug_info->largestexternallookupkeysize ==
+                   QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
+                       size +=
+                           THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
+       }
+
+       if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth->
+               p_init_enet_param_shadow->rxthread[0]),
+               (u8) (numThreadsRxNumerical + 1)
+               /* Rx needs one extra for terminator */
+               , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT,
+               ug_info->riscRx, 1)) != 0) {
+                       ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+                               __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       ugeth->p_init_enet_param_shadow->txglobal =
+           ugeth->tx_glbl_pram_offset | ug_info->riscTx;
+       if ((ret_val =
+            fill_init_enet_entries(ugeth,
+                                   &(ugeth->p_init_enet_param_shadow->
+                                     txthread[0]), numThreadsTxNumerical,
+                                   sizeof(ucc_geth_thread_tx_pram_t),
+                                   UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
+                                   ug_info->riscTx, 0)) != 0) {
+               ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+                         __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return ret_val;
+       }
+
+       /* Load Rx bds with buffers */
+       for (i = 0; i < ug_info->numQueuesRx; i++) {
+               if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
+                       ugeth_err("%s: Can not fill Rx bds with buffers.",
+                                 __FUNCTION__);
+                       ucc_geth_memclean(ugeth);
+                       return ret_val;
+               }
+       }
+
+       /* Allocate InitEnet command parameter structure */
+       init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4);
+       if (IS_MURAM_ERR(init_enet_pram_offset)) {
+               ugeth_err
+                   ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
+                    __FUNCTION__);
+               ucc_geth_memclean(ugeth);
+               return -ENOMEM;
+       }
+       p_init_enet_pram =
+           (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset);
+
+       /* Copy shadow InitEnet command parameter structure into PRAM */
+       p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1;
+       p_init_enet_pram->resinit2 = ugeth->p_init_enet_param_shadow->resinit2;
+       p_init_enet_pram->resinit3 = ugeth->p_init_enet_param_shadow->resinit3;
+       p_init_enet_pram->resinit4 = ugeth->p_init_enet_param_shadow->resinit4;
+       out_be16(&p_init_enet_pram->resinit5,
+                ugeth->p_init_enet_param_shadow->resinit5);
+       p_init_enet_pram->largestexternallookupkeysize =
+           ugeth->p_init_enet_param_shadow->largestexternallookupkeysize;
+       out_be32(&p_init_enet_pram->rgftgfrxglobal,
+                ugeth->p_init_enet_param_shadow->rgftgfrxglobal);
+       for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++)
+               out_be32(&p_init_enet_pram->rxthread[i],
+                        ugeth->p_init_enet_param_shadow->rxthread[i]);
+       out_be32(&p_init_enet_pram->txglobal,
+                ugeth->p_init_enet_param_shadow->txglobal);
+       for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++)
+               out_be32(&p_init_enet_pram->txthread[i],
+                        ugeth->p_init_enet_param_shadow->txthread[i]);
+
+       /* Issue QE command */
+       cecr_subblock =
+           ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+       qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+                    init_enet_pram_offset);
+
+       /* Free InitEnet command parameter */
+       qe_muram_free(init_enet_pram_offset);
+
+       return 0;
+}
+
+/* returns a net_device_stats structure pointer */
+static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       return &(ugeth->stats);
+}
+
+/* ucc_geth_timeout gets called when a packet has not been
+ * transmitted after a set amount of time.
+ * For now, assume that clearing out all the structures, and
+ * starting over will fix the problem. */
+static void ucc_geth_timeout(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ugeth->stats.tx_errors++;
+
+       ugeth_dump_regs(ugeth);
+
+       if (dev->flags & IFF_UP) {
+               ucc_geth_stop(ugeth);
+               ucc_geth_startup(ugeth);
+       }
+
+       netif_schedule(dev);
+}
+
+/* This is called by the kernel when a frame is ready for transmission. */
+/* It is pointed to by the dev->hard_start_xmit function pointer */
+static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       u8 *bd;                 /* BD pointer */
+       u32 bd_status;
+       u8 txQ = 0;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irq(&ugeth->lock);
+
+       ugeth->stats.tx_bytes += skb->len;
+
+       /* Start from the next BD that should be filled */
+       bd = ugeth->txBd[txQ];
+       bd_status = BD_STATUS_AND_LENGTH(bd);
+       /* Save the skb pointer so we can free it later */
+       ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb;
+
+       /* Update the current skb pointer (wrapping if this was the last) */
+       ugeth->skb_curtx[txQ] =
+           (ugeth->skb_curtx[txQ] +
+            1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
+
+       /* set up the buffer descriptor */
+       BD_BUFFER_SET(bd,
+                     dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE));
+
+       //printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data);
+
+       bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len;
+
+       BD_STATUS_AND_LENGTH_SET(bd, bd_status);
+
+       dev->trans_start = jiffies;
+
+       /* Move to next BD in the ring */
+       if (!(bd_status & T_W))
+               ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD;
+       else
+               ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+
+       /* If the next BD still needs to be cleaned up, then the bds
+          are full.  We need to tell the kernel to stop sending us stuff. */
+       if (bd == ugeth->confBd[txQ]) {
+               if (!netif_queue_stopped(dev))
+                       netif_stop_queue(dev);
+       }
+
+       if (ugeth->p_scheduler) {
+               ugeth->cpucount[txQ]++;
+               /* Indicate to QE that there are more Tx bds ready for
+               transmission */
+               /* This is done by writing a running counter of the bd
+               count to the scheduler PRAM. */
+               out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]);
+       }
+
+       spin_unlock_irq(&ugeth->lock);
+
+       return 0;
+}
+
+static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit)
+{
+       struct sk_buff *skb;
+       u8 *bd;
+       u16 length, howmany = 0;
+       u32 bd_status;
+       u8 *bdBuffer;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock(&ugeth->lock);
+       /* collect received buffers */
+       bd = ugeth->rxBd[rxQ];
+
+       bd_status = BD_STATUS_AND_LENGTH(bd);
+
+       /* while there are received buffers and BD is full (~R_E) */
+       while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) {
+               bdBuffer = (u8 *) BD_BUFFER(bd);
+               length = (u16) ((bd_status & BD_LENGTH_MASK) - 4);
+               skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]];
+
+               /* determine whether buffer is first, last, first and last
+               (single buffer frame) or middle (not first and not last) */
+               if (!skb ||
+                   (!(bd_status & (R_F | R_L))) ||
+                   (bd_status & R_ERRORS_FATAL)) {
+                       ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x",
+                                  __FUNCTION__, __LINE__, (u32) skb);
+                       if (skb)
+                               dev_kfree_skb_any(skb);
+
+                       ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
+                       ugeth->stats.rx_dropped++;
+               } else {
+                       ugeth->stats.rx_packets++;
+                       howmany++;
+
+                       /* Prep the skb for the packet */
+                       skb_put(skb, length);
+
+                       /* Tell the skb what kind of packet this is */
+                       skb->protocol = eth_type_trans(skb, ugeth->dev);
+
+                       ugeth->stats.rx_bytes += length;
+                       /* Send the packet up the stack */
+#ifdef CONFIG_UGETH_NAPI
+                       netif_receive_skb(skb);
+#else
+                       netif_rx(skb);
+#endif                         /* CONFIG_UGETH_NAPI */
+               }
+
+               ugeth->dev->last_rx = jiffies;
+
+               skb = get_new_skb(ugeth, bd);
+               if (!skb) {
+                       ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__);
+                       spin_unlock(&ugeth->lock);
+                       ugeth->stats.rx_dropped++;
+                       break;
+               }
+
+               ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb;
+
+               /* update to point at the next skb */
+               ugeth->skb_currx[rxQ] =
+                   (ugeth->skb_currx[rxQ] +
+                    1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]);
+
+               if (bd_status & R_W)
+                       bd = ugeth->p_rx_bd_ring[rxQ];
+               else
+                       bd += UCC_GETH_SIZE_OF_BD;
+
+               bd_status = BD_STATUS_AND_LENGTH(bd);
+       }
+
+       ugeth->rxBd[rxQ] = bd;
+       spin_unlock(&ugeth->lock);
+       return howmany;
+}
+
+static int ucc_geth_tx(struct net_device *dev, u8 txQ)
+{
+       /* Start from the next BD that should be filled */
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       u8 *bd;                 /* BD pointer */
+       u32 bd_status;
+
+       bd = ugeth->confBd[txQ];
+       bd_status = BD_STATUS_AND_LENGTH(bd);
+
+       /* Normal processing. */
+       while ((bd_status & T_R) == 0) {
+               /* BD contains already transmitted buffer.   */
+               /* Handle the transmitted buffer and release */
+               /* the BD to be used with the current frame  */
+
+               if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+                       break;
+
+               ugeth->stats.tx_packets++;
+
+               /* Free the sk buffer associated with this TxBD */
+               dev_kfree_skb_irq(ugeth->
+                                 tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]);
+               ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
+               ugeth->skb_dirtytx[txQ] =
+                   (ugeth->skb_dirtytx[txQ] +
+                    1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
+
+               /* We freed a buffer, so now we can restart transmission */
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
+
+               /* Advance the confirmation BD pointer */
+               if (!(bd_status & T_W))
+                       ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD;
+               else
+                       ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+       }
+       return 0;
+}
+
+#ifdef CONFIG_UGETH_NAPI
+static int ucc_geth_poll(struct net_device *dev, int *budget)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       int howmany;
+       int rx_work_limit = *budget;
+       u8 rxQ = 0;
+
+       if (rx_work_limit > dev->quota)
+               rx_work_limit = dev->quota;
+
+       howmany = ucc_geth_rx(ugeth, rxQ, rx_work_limit);
+
+       dev->quota -= howmany;
+       rx_work_limit -= howmany;
+       *budget -= howmany;
+
+       if (rx_work_limit >= 0)
+               netif_rx_complete(dev);
+
+       return (rx_work_limit < 0) ? 1 : 0;
+}
+#endif                         /* CONFIG_UGETH_NAPI */
+
+static irqreturn_t ucc_geth_irq_handler(int irq, void *info,
+                                       struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)info;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_fast_private_t *uccf;
+       ucc_geth_info_t *ug_info;
+       register u32 ucce = 0;
+       register u32 bit_mask = UCCE_RXBF_SINGLE_MASK;
+       register u32 tx_mask = UCCE_TXBF_SINGLE_MASK;
+       register u8 i;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       if (!ugeth)
+               return IRQ_NONE;
+
+       uccf = ugeth->uccf;
+       ug_info = ugeth->ug_info;
+
+       do {
+               ucce |= (u32) (in_be32(uccf->p_ucce) & in_be32(uccf->p_uccm));
+
+               /* clear event bits for next time */
+               /* Side effect here is to mask ucce variable
+               for future processing below. */
+               out_be32(uccf->p_ucce, ucce);   /* Clear with ones,
+                                               but only bits in UCCM */
+
+               /* We ignore Tx interrupts because Tx confirmation is
+               done inside Tx routine */
+
+               for (i = 0; i < ug_info->numQueuesRx; i++) {
+                       if (ucce & bit_mask)
+                               ucc_geth_rx(ugeth, i,
+                                           (int)ugeth->ug_info->
+                                           bdRingLenRx[i]);
+                       ucce &= ~bit_mask;
+                       bit_mask <<= 1;
+               }
+
+               for (i = 0; i < ug_info->numQueuesTx; i++) {
+                       if (ucce & tx_mask)
+                               ucc_geth_tx(dev, i);
+                       ucce &= ~tx_mask;
+                       tx_mask <<= 1;
+               }
+
+               /* Exceptions */
+               if (ucce & UCCE_BSY) {
+                       ugeth_vdbg("Got BUSY irq!!!!");
+                       ugeth->stats.rx_errors++;
+                       ucce &= ~UCCE_BSY;
+               }
+               if (ucce & UCCE_OTHER) {
+                       ugeth_vdbg("Got frame with error (ucce - 0x%08x)!!!!",
+                                  ucce);
+                       ugeth->stats.rx_errors++;
+                       ucce &= ~ucce;
+               }
+       }
+       while (ucce);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)dev_id;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       /* Clear the interrupt */
+       mii_clear_phy_interrupt(ugeth->mii_info);
+
+       /* Disable PHY interrupts */
+       mii_configure_phy_interrupt(ugeth->mii_info, MII_INTERRUPT_DISABLED);
+
+       /* Schedule the phy change */
+       schedule_work(&ugeth->tq);
+
+       return IRQ_HANDLED;
+}
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void ugeth_phy_change(void *data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_geth_t *ug_regs;
+       int result = 0;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ug_regs = ugeth->ug_regs;
+
+       /* Delay to give the PHY a chance to change the
+        * register state */
+       msleep(1);
+
+       /* Update the link, speed, duplex */
+       result = ugeth->mii_info->phyinfo->read_status(ugeth->mii_info);
+
+       /* Adjust the known status as long as the link
+        * isn't still coming up */
+       if ((0 == result) || (ugeth->mii_info->link == 0))
+               adjust_link(dev);
+
+       /* Reenable interrupts, if needed */
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR)
+               mii_configure_phy_interrupt(ugeth->mii_info,
+                                           MII_INTERRUPT_ENABLED);
+}
+
+/* Called every so often on systems that don't interrupt
+ * the core for PHY changes */
+static void ugeth_phy_timer(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       schedule_work(&ugeth->tq);
+
+       mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ);
+}
+
+/* Keep trying aneg for some time
+ * If, after GFAR_AN_TIMEOUT seconds, it has not
+ * finished, we switch to forced.
+ * Either way, once the process has completed, we either
+ * request the interrupt, or switch the timer over to
+ * using ugeth_phy_timer to check status */
+static void ugeth_phy_startup_timer(unsigned long data)
+{
+       struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
+       ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev);
+       static int secondary = UGETH_AN_TIMEOUT;
+       int result;
+
+       /* Configure the Auto-negotiation */
+       result = mii_info->phyinfo->config_aneg(mii_info);
+
+       /* If autonegotiation failed to start, and
+        * we haven't timed out, reset the timer, and return */
+       if (result && secondary--) {
+               mod_timer(&ugeth->phy_info_timer, jiffies + HZ);
+               return;
+       } else if (result) {
+               /* Couldn't start autonegotiation.
+                * Try switching to forced */
+               mii_info->autoneg = 0;
+               result = mii_info->phyinfo->config_aneg(mii_info);
+
+               /* Forcing failed!  Give up */
+               if (result) {
+                       ugeth_err("%s: Forcing failed!", mii_info->dev->name);
+                       return;
+               }
+       }
+
+       /* Kill the timer so it can be restarted */
+       del_timer_sync(&ugeth->phy_info_timer);
+
+       /* Grab the PHY interrupt, if necessary/possible */
+       if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+               if (request_irq(ugeth->ug_info->phy_interrupt,
+                               phy_interrupt,
+                               SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) {
+                       ugeth_err("%s: Can't get IRQ %d (PHY)",
+                                 mii_info->dev->name,
+                                 ugeth->ug_info->phy_interrupt);
+               } else {
+                       mii_configure_phy_interrupt(ugeth->mii_info,
+                                                   MII_INTERRUPT_ENABLED);
+                       return;
+               }
+       }
+
+       /* Start the timer again, this time in order to
+        * handle a change in status */
+       init_timer(&ugeth->phy_info_timer);
+       ugeth->phy_info_timer.function = &ugeth_phy_timer;
+       ugeth->phy_info_timer.data = (unsigned long)mii_info->dev;
+       mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ);
+}
+
+/* Called when something needs to use the ethernet device */
+/* Returns 0 for success. */
+static int ucc_geth_open(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       int err;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       /* Test station address */
+       if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
+               ugeth_err("%s: Multicast address used for station address"
+                         " - is this what you wanted?", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       err = ucc_geth_startup(ugeth);
+       if (err) {
+               ugeth_err("%s: Cannot configure net device, aborting.",
+                         dev->name);
+               return err;
+       }
+
+       err = adjust_enet_interface(ugeth);
+       if (err) {
+               ugeth_err("%s: Cannot configure net device, aborting.",
+                         dev->name);
+               return err;
+       }
+
+       /*       Set MACSTNADDR1, MACSTNADDR2                */
+       /* For more details see the hardware spec.           */
+       init_mac_station_addr_regs(dev->dev_addr[0],
+                                  dev->dev_addr[1],
+                                  dev->dev_addr[2],
+                                  dev->dev_addr[3],
+                                  dev->dev_addr[4],
+                                  dev->dev_addr[5],
+                                  &ugeth->ug_regs->macstnaddr1,
+                                  &ugeth->ug_regs->macstnaddr2);
+
+       err = init_phy(dev);
+       if (err) {
+               ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name);
+               return err;
+       }
+#ifndef CONFIG_UGETH_NAPI
+       err =
+           request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0,
+                       "UCC Geth", dev);
+       if (err) {
+               ugeth_err("%s: Cannot get IRQ for net device, aborting.",
+                         dev->name);
+               ucc_geth_stop(ugeth);
+               return err;
+       }
+#endif                         /* CONFIG_UGETH_NAPI */
+
+       /* Set up the PHY change work queue */
+       INIT_WORK(&ugeth->tq, ugeth_phy_change, dev);
+
+       init_timer(&ugeth->phy_info_timer);
+       ugeth->phy_info_timer.function = &ugeth_phy_startup_timer;
+       ugeth->phy_info_timer.data = (unsigned long)ugeth->mii_info;
+       mod_timer(&ugeth->phy_info_timer, jiffies + HZ);
+
+       err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+       if (err) {
+               ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
+               ucc_geth_stop(ugeth);
+               return err;
+       }
+
+       netif_start_queue(dev);
+
+       return err;
+}
+
+/* Stops the kernel queue, and halts the controller */
+static int ucc_geth_close(struct net_device *dev)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ucc_geth_stop(ugeth);
+
+       /* Shutdown the PHY */
+       if (ugeth->mii_info->phyinfo->close)
+               ugeth->mii_info->phyinfo->close(ugeth->mii_info);
+
+       kfree(ugeth->mii_info);
+
+       netif_stop_queue(dev);
+
+       return 0;
+}
+
+struct ethtool_ops ucc_geth_ethtool_ops = {
+       .get_settings = NULL,
+       .get_drvinfo = NULL,
+       .get_regs_len = NULL,
+       .get_regs = NULL,
+       .get_link = NULL,
+       .get_coalesce = NULL,
+       .set_coalesce = NULL,
+       .get_ringparam = NULL,
+       .set_ringparam = NULL,
+       .get_strings = NULL,
+       .get_stats_count = NULL,
+       .get_ethtool_stats = NULL,
+};
+
+static int ucc_geth_probe(struct device *device)
+{
+       struct platform_device *pdev = to_platform_device(device);
+       struct ucc_geth_platform_data *ugeth_pdata;
+       struct net_device *dev = NULL;
+       struct ucc_geth_private *ugeth = NULL;
+       struct ucc_geth_info *ug_info;
+       int err;
+       static int mii_mng_configured = 0;
+
+       ugeth_vdbg("%s: IN", __FUNCTION__);
+
+       ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data;
+
+       ug_info = &ugeth_info[pdev->id];
+       ug_info->uf_info.ucc_num = pdev->id;
+       ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock;
+       ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock;
+       ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr;
+       ug_info->uf_info.irq = platform_get_irq(pdev, 0);
+       ug_info->phy_address = ugeth_pdata->phy_id;
+       ug_info->enet_interface = ugeth_pdata->phy_interface;
+       ug_info->board_flags = ugeth_pdata->board_flags;
+       ug_info->phy_interrupt = ugeth_pdata->phy_interrupt;
+
+       printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n",
+               ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs,
+               ug_info->uf_info.irq);
+
+       if (ug_info == NULL) {
+               ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__,
+                         pdev->id);
+               return -ENODEV;
+       }
+
+       if (!mii_mng_configured) {
+               ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num);
+               mii_mng_configured = 1;
+       }
+
+       /* Create an ethernet device instance */
+       dev = alloc_etherdev(sizeof(*ugeth));
+
+       if (dev == NULL)
+               return -ENOMEM;
+
+       ugeth = netdev_priv(dev);
+       spin_lock_init(&ugeth->lock);
+
+       dev_set_drvdata(device, dev);
+
+       /* Set the dev->base_addr to the gfar reg region */
+       dev->base_addr = (unsigned long)(ug_info->uf_info.regs);
+
+       SET_MODULE_OWNER(dev);
+       SET_NETDEV_DEV(dev, device);
+
+       /* Fill in the dev structure */
+       dev->open = ucc_geth_open;
+       dev->hard_start_xmit = ucc_geth_start_xmit;
+       dev->tx_timeout = ucc_geth_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_UGETH_NAPI
+       dev->poll = ucc_geth_poll;
+       dev->weight = UCC_GETH_DEV_WEIGHT;
+#endif                         /* CONFIG_UGETH_NAPI */
+       dev->stop = ucc_geth_close;
+       dev->get_stats = ucc_geth_get_stats;
+//    dev->change_mtu = ucc_geth_change_mtu;
+       dev->mtu = 1500;
+       dev->set_multicast_list = ucc_geth_set_multi;
+       dev->ethtool_ops = &ucc_geth_ethtool_ops;
+
+       err = register_netdev(dev);
+       if (err) {
+               ugeth_err("%s: Cannot register net device, aborting.",
+                         dev->name);
+               free_netdev(dev);
+               return err;
+       }
+
+       ugeth->ug_info = ug_info;
+       ugeth->dev = dev;
+       memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6);
+
+       return 0;
+}
+
+static int ucc_geth_remove(struct device *device)
+{
+       struct net_device *dev = dev_get_drvdata(device);
+       struct ucc_geth_private *ugeth = netdev_priv(dev);
+
+       dev_set_drvdata(device, NULL);
+       ucc_geth_memclean(ugeth);
+       free_netdev(dev);
+
+       return 0;
+}
+
+/* Structure for a device driver */
+static struct device_driver ucc_geth_driver = {
+       .name = DRV_NAME,
+       .bus = &platform_bus_type,
+       .probe = ucc_geth_probe,
+       .remove = ucc_geth_remove,
+};
+
+static int __init ucc_geth_init(void)
+{
+       int i;
+       printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
+       for (i = 0; i < 8; i++)
+               memcpy(&(ugeth_info[i]), &ugeth_primary_info,
+                      sizeof(ugeth_primary_info));
+
+       return driver_register(&ucc_geth_driver);
+}
+
+static void __exit ucc_geth_exit(void)
+{
+       driver_unregister(&ucc_geth_driver);
+}
+
+module_init(ucc_geth_init);
+module_exit(ucc_geth_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
new file mode 100644 (file)
index 0000000..005965f
--- /dev/null
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * Internal header file for UCC Gigabit Ethernet unit routines.
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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 __UCC_GETH_H__
+#define __UCC_GETH_H__
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+#define NUM_TX_QUEUES                   8
+#define NUM_RX_QUEUES                   8
+#define NUM_BDS_IN_PREFETCHED_BDS       4
+#define TX_IP_OFFSET_ENTRY_MAX          8
+#define NUM_OF_PADDRS                   4
+#define ENET_INIT_PARAM_MAX_ENTRIES_RX  9
+#define ENET_INIT_PARAM_MAX_ENTRIES_TX  8
+
+typedef struct ucc_mii_mng {
+       u32 miimcfg;            /* MII management configuration reg */
+       u32 miimcom;            /* MII management command reg */
+       u32 miimadd;            /* MII management address reg */
+       u32 miimcon;            /* MII management control reg */
+       u32 miimstat;           /* MII management status reg */
+       u32 miimind;            /* MII management indication reg */
+} __attribute__ ((packed)) ucc_mii_mng_t;
+
+typedef struct ucc_geth {
+       ucc_fast_t uccf;
+
+       u32 maccfg1;            /* mac configuration reg. 1 */
+       u32 maccfg2;            /* mac configuration reg. 2 */
+       u32 ipgifg;             /* interframe gap reg.  */
+       u32 hafdup;             /* half-duplex reg.  */
+       u8 res1[0x10];
+       ucc_mii_mng_t miimng;   /* MII management structure */
+       u32 ifctl;              /* interface control reg */
+       u32 ifstat;             /* interface statux reg */
+       u32 macstnaddr1;        /* mac station address part 1 reg */
+       u32 macstnaddr2;        /* mac station address part 2 reg */
+       u8 res2[0x8];
+       u32 uempr;              /* UCC Ethernet Mac parameter reg */
+       u32 utbipar;            /* UCC tbi address reg */
+       u16 uescr;              /* UCC Ethernet statistics control reg */
+       u8 res3[0x180 - 0x15A];
+       u32 tx64;               /* Total number of frames (including bad
+                                  frames) transmitted that were exactly of the
+                                  minimal length (64 for un tagged, 68 for
+                                  tagged, or with length exactly equal to the
+                                  parameter MINLength */
+       u32 tx127;              /* Total number of frames (including bad
+                                  frames) transmitted that were between
+                                  MINLength (Including FCS length==4) and 127
+                                  octets */
+       u32 tx255;              /* Total number of frames (including bad
+                                  frames) transmitted that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 rx64;               /* Total number of frames received including
+                                  bad frames that were exactly of the mninimal
+                                  length (64 bytes) */
+       u32 rx127;              /* Total number of frames (including bad
+                                  frames) received that were between MINLength
+                                  (Including FCS length==4) and 127 octets */
+       u32 rx255;              /* Total number of frames (including bad
+                                  frames) received that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 txok;               /* Total number of octets residing in frames
+                                  that where involved in succesfull
+                                  transmission */
+       u16 txcf;               /* Total number of PAUSE control frames
+                                  transmitted by this MAC */
+       u8 res4[0x2];
+       u32 tmca;               /* Total number of frames that were transmitted
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 tbca;               /* Total number of frames transmitted
+                                  succesfully that had destination address
+                                  field equal to the broadcast address */
+       u32 rxfok;              /* Total number of frames received OK */
+       u32 rxbok;              /* Total number of octets received OK */
+       u32 rbyt;               /* Total number of octets received including
+                                  octets in bad frames. Must be implemented in
+                                  HW because it includes octets in frames that
+                                  never even reach the UCC */
+       u32 rmca;               /* Total number of frames that were received
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 rbca;               /* Total number of frames received succesfully
+                                  that had destination address equal to the
+                                  broadcast address */
+       u32 scar;               /* Statistics carry register */
+       u32 scam;               /* Statistics caryy mask register */
+       u8 res5[0x200 - 0x1c4];
+} __attribute__ ((packed)) ucc_geth_t;
+
+/* UCC GETH TEMODR Register */
+#define TEMODER_TX_RMON_STATISTICS_ENABLE       0x0100 /* enable Tx statistics
+                                                        */
+#define TEMODER_SCHEDULER_ENABLE                0x2000 /* enable scheduler */
+#define TEMODER_IP_CHECKSUM_GENERATE            0x0400 /* generate IPv4
+                                                          checksums */
+#define TEMODER_PERFORMANCE_OPTIMIZATION_MODE1  0x0200 /* enable performance
+                                                          optimization
+                                                          enhancement (mode1) */
+#define TEMODER_RMON_STATISTICS                 0x0100 /* enable tx statistics
+                                                        */
+#define TEMODER_NUM_OF_QUEUES_SHIFT             (15-15)        /* Number of queues <<
+                                                          shift */
+
+/* UCC GETH TEMODR Register */
+#define REMODER_RX_RMON_STATISTICS_ENABLE       0x00001000     /* enable Rx
+                                                                  statistics */
+#define REMODER_RX_EXTENDED_FEATURES            0x80000000     /* enable
+                                                                  extended
+                                                                  features */
+#define REMODER_VLAN_OPERATION_TAGGED_SHIFT     (31-9 )        /* vlan operation
+                                                          tagged << shift */
+#define REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT (31-10)        /* vlan operation non
+                                                          tagged << shift */
+#define REMODER_RX_QOS_MODE_SHIFT               (31-15)        /* rx QoS mode << shift
+                                                        */
+#define REMODER_RMON_STATISTICS                 0x00001000     /* enable rx
+                                                                  statistics */
+#define REMODER_RX_EXTENDED_FILTERING           0x00000800     /* extended
+                                                                  filtering
+                                                                  vs.
+                                                                  mpc82xx-like
+                                                                  filtering */
+#define REMODER_NUM_OF_QUEUES_SHIFT             (31-23)        /* Number of queues <<
+                                                          shift */
+#define REMODER_DYNAMIC_MAX_FRAME_LENGTH        0x00000008     /* enable
+                                                                  dynamic max
+                                                                  frame length
+                                                                */
+#define REMODER_DYNAMIC_MIN_FRAME_LENGTH        0x00000004     /* enable
+                                                                  dynamic min
+                                                                  frame length
+                                                                */
+#define REMODER_IP_CHECKSUM_CHECK               0x00000002     /* check IPv4
+                                                                  checksums */
+#define REMODER_IP_ADDRESS_ALIGNMENT            0x00000001     /* align ip
+                                                                  address to
+                                                                  4-byte
+                                                                  boundary */
+
+/* UCC GETH Event Register */
+#define UCCE_MPD                                0x80000000     /* Magic packet
+                                                                  detection */
+#define UCCE_SCAR                               0x40000000
+#define UCCE_GRA                                0x20000000     /* Tx graceful
+                                                                  stop
+                                                                  complete */
+#define UCCE_CBPR                               0x10000000
+#define UCCE_BSY                                0x08000000
+#define UCCE_RXC                                0x04000000
+#define UCCE_TXC                                0x02000000
+#define UCCE_TXE                                0x01000000
+#define UCCE_TXB7                               0x00800000
+#define UCCE_TXB6                               0x00400000
+#define UCCE_TXB5                               0x00200000
+#define UCCE_TXB4                               0x00100000
+#define UCCE_TXB3                               0x00080000
+#define UCCE_TXB2                               0x00040000
+#define UCCE_TXB1                               0x00020000
+#define UCCE_TXB0                               0x00010000
+#define UCCE_RXB7                               0x00008000
+#define UCCE_RXB6                               0x00004000
+#define UCCE_RXB5                               0x00002000
+#define UCCE_RXB4                               0x00001000
+#define UCCE_RXB3                               0x00000800
+#define UCCE_RXB2                               0x00000400
+#define UCCE_RXB1                               0x00000200
+#define UCCE_RXB0                               0x00000100
+#define UCCE_RXF7                               0x00000080
+#define UCCE_RXF6                               0x00000040
+#define UCCE_RXF5                               0x00000020
+#define UCCE_RXF4                               0x00000010
+#define UCCE_RXF3                               0x00000008
+#define UCCE_RXF2                               0x00000004
+#define UCCE_RXF1                               0x00000002
+#define UCCE_RXF0                               0x00000001
+
+#define UCCE_RXBF_SINGLE_MASK                   (UCCE_RXF0)
+#define UCCE_TXBF_SINGLE_MASK                   (UCCE_TXB0)
+
+#define UCCE_TXB         (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\
+                       UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0)
+#define UCCE_RXB         (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\
+                       UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0)
+#define UCCE_RXF         (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\
+                       UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0)
+#define UCCE_OTHER       (UCCE_SCAR | UCCE_GRA  | UCCE_CBPR | UCCE_BSY  |\
+                       UCCE_RXC  | UCCE_TXC  | UCCE_TXE)
+
+/* UCC GETH UPSMR (Protocol Specific Mode Register) */
+#define UPSMR_ECM                               0x04000000     /* Enable CAM
+                                                                  Miss or
+                                                                  Enable
+                                                                  Filtering
+                                                                  Miss */
+#define UPSMR_HSE                               0x02000000     /* Hardware
+                                                                  Statistics
+                                                                  Enable */
+#define UPSMR_PRO                               0x00400000     /* Promiscuous*/
+#define UPSMR_CAP                               0x00200000     /* CAM polarity
+                                                                */
+#define UPSMR_RSH                               0x00100000     /* Receive
+                                                                  Short Frames
+                                                                */
+#define UPSMR_RPM                               0x00080000     /* Reduced Pin
+                                                                  Mode
+                                                                  interfaces */
+#define UPSMR_R10M                              0x00040000     /* RGMII/RMII
+                                                                  10 Mode */
+#define UPSMR_RLPB                              0x00020000     /* RMII
+                                                                  Loopback
+                                                                  Mode */
+#define UPSMR_TBIM                              0x00010000     /* Ten-bit
+                                                                  Interface
+                                                                  Mode */
+#define UPSMR_RMM                               0x00001000     /* RMII/RGMII
+                                                                  Mode */
+#define UPSMR_CAM                               0x00000400     /* CAM Address
+                                                                  Matching */
+#define UPSMR_BRO                               0x00000200     /* Broadcast
+                                                                  Address */
+#define UPSMR_RES1                              0x00002000     /* Reserved
+                                                                  feild - must
+                                                                  be 1 */
+
+/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
+#define MACCFG1_FLOW_RX                         0x00000020     /* Flow Control
+                                                                  Rx */
+#define MACCFG1_FLOW_TX                         0x00000010     /* Flow Control
+                                                                  Tx */
+#define MACCFG1_ENABLE_SYNCHED_RX               0x00000008     /* Rx Enable
+                                                                  synchronized
+                                                                  to Rx stream
+                                                                */
+#define MACCFG1_ENABLE_RX                       0x00000004     /* Enable Rx */
+#define MACCFG1_ENABLE_SYNCHED_TX               0x00000002     /* Tx Enable
+                                                                  synchronized
+                                                                  to Tx stream
+                                                                */
+#define MACCFG1_ENABLE_TX                       0x00000001     /* Enable Tx */
+
+/* UCC GETH MACCFG2 (MAC Configuration 2 Register) */
+#define MACCFG2_PREL_SHIFT                      (31 - 19)      /* Preamble
+                                                                  Length <<
+                                                                  shift */
+#define MACCFG2_PREL_MASK                       0x0000f000     /* Preamble
+                                                                  Length mask */
+#define MACCFG2_SRP                             0x00000080     /* Soft Receive
+                                                                  Preamble */
+#define MACCFG2_STP                             0x00000040     /* Soft
+                                                                  Transmit
+                                                                  Preamble */
+#define MACCFG2_RESERVED_1                      0x00000020     /* Reserved -
+                                                                  must be set
+                                                                  to 1 */
+#define MACCFG2_LC                              0x00000010     /* Length Check
+                                                                */
+#define MACCFG2_MPE                             0x00000008     /* Magic packet
+                                                                  detect */
+#define MACCFG2_FDX                             0x00000001     /* Full Duplex */
+#define MACCFG2_FDX_MASK                        0x00000001     /* Full Duplex
+                                                                  mask */
+#define MACCFG2_PAD_CRC                         0x00000004
+#define MACCFG2_CRC_EN                          0x00000002
+#define MACCFG2_PAD_AND_CRC_MODE_NONE           0x00000000     /* Neither
+                                                                  Padding
+                                                                  short frames
+                                                                  nor CRC */
+#define MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY       0x00000002     /* Append CRC
+                                                                  only */
+#define MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC    0x00000004
+#define MACCFG2_INTERFACE_MODE_NIBBLE           0x00000100     /* nibble mode
+                                                                  (MII/RMII/RGMII
+                                                                  10/100bps) */
+#define MACCFG2_INTERFACE_MODE_BYTE             0x00000200     /* byte mode
+                                                                  (GMII/TBI/RTB/RGMII
+                                                                  1000bps ) */
+#define MACCFG2_INTERFACE_MODE_MASK             0x00000300     /* mask
+                                                                  covering all
+                                                                  relevant
+                                                                  bits */
+
+/* UCC GETH IPGIFG (Inter-frame Gap / Inter-Frame Gap Register) */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT (31 -  7)      /* Non
+                                                                  back-to-back
+                                                                  inter frame
+                                                                  gap part 1.
+                                                                  << shift */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT (31 - 15)      /* Non
+                                                                  back-to-back
+                                                                  inter frame
+                                                                  gap part 2.
+                                                                  << shift */
+#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT    (31 - 23)      /* Mimimum IFG
+                                                                  Enforcement
+                                                                  << shift */
+#define IPGIFG_BACK_TO_BACK_IFG_SHIFT           (31 - 31)      /* back-to-back
+                                                                  inter frame
+                                                                  gap << shift
+                                                                */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX   127    /* Non back-to-back
+                                                          inter frame gap part
+                                                          1. max val */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX   127    /* Non back-to-back
+                                                          inter frame gap part
+                                                          2. max val */
+#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX      255    /* Mimimum IFG
+                                                          Enforcement max val */
+#define IPGIFG_BACK_TO_BACK_IFG_MAX             127    /* back-to-back inter
+                                                          frame gap max val */
+#define IPGIFG_NBTB_CS_IPG_MASK                 0x7F000000
+#define IPGIFG_NBTB_IPG_MASK                    0x007F0000
+#define IPGIFG_MIN_IFG_MASK                     0x0000FF00
+#define IPGIFG_BTB_IPG_MASK                     0x0000007F
+
+/* UCC GETH HAFDUP (Half Duplex Register) */
+#define HALFDUP_ALT_BEB_TRUNCATION_SHIFT        (31 - 11)      /* Alternate
+                                                                  Binary
+                                                                  Exponential
+                                                                  Backoff
+                                                                  Truncation
+                                                                  << shift */
+#define HALFDUP_ALT_BEB_TRUNCATION_MAX          0xf    /* Alternate Binary
+                                                          Exponential Backoff
+                                                          Truncation max val */
+#define HALFDUP_ALT_BEB                         0x00080000     /* Alternate
+                                                                  Binary
+                                                                  Exponential
+                                                                  Backoff */
+#define HALFDUP_BACK_PRESSURE_NO_BACKOFF        0x00040000     /* Back
+                                                                  pressure no
+                                                                  backoff */
+#define HALFDUP_NO_BACKOFF                      0x00020000     /* No Backoff */
+#define HALFDUP_EXCESSIVE_DEFER                 0x00010000     /* Excessive
+                                                                  Defer */
+#define HALFDUP_MAX_RETRANSMISSION_SHIFT        (31 - 19)      /* Maximum
+                                                                  Retransmission
+                                                                  << shift */
+#define HALFDUP_MAX_RETRANSMISSION_MAX          0xf    /* Maximum
+                                                          Retransmission max
+                                                          val */
+#define HALFDUP_COLLISION_WINDOW_SHIFT          (31 - 31)      /* Collision
+                                                                  Window <<
+                                                                  shift */
+#define HALFDUP_COLLISION_WINDOW_MAX            0x3f   /* Collision Window max
+                                                          val */
+#define HALFDUP_ALT_BEB_TR_MASK                 0x00F00000
+#define HALFDUP_RETRANS_MASK                    0x0000F000
+#define HALFDUP_COL_WINDOW_MASK                 0x0000003F
+
+/* UCC GETH UCCS (Ethernet Status Register) */
+#define UCCS_BPR                                0x02   /* Back pressure (in
+                                                          half duplex mode) */
+#define UCCS_PAU                                0x02   /* Pause state (in full
+                                                          duplex mode) */
+#define UCCS_MPD                                0x01   /* Magic Packet
+                                                          Detected */
+
+/* UCC GETH MIIMCFG (MII Management Configuration Register) */
+#define MIIMCFG_RESET_MANAGEMENT                0x80000000     /* Reset
+                                                                  management */
+#define MIIMCFG_NO_PREAMBLE                     0x00000010     /* Preamble
+                                                                  suppress */
+#define MIIMCFG_CLOCK_DIVIDE_SHIFT              (31 - 31)      /* clock divide
+                                                                  << shift */
+#define MIIMCFG_CLOCK_DIVIDE_MAX                0xf    /* clock divide max val
+                                                        */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2    0x00000000     /* divide by 2 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4    0x00000001     /* divide by 4 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6    0x00000002     /* divide by 6 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8    0x00000003     /* divide by 8 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10   0x00000004     /* divide by 10
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14   0x00000005     /* divide by 14
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16   0x00000008     /* divide by 16
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20   0x00000006     /* divide by 20
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28   0x00000007     /* divide by 28
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32   0x00000009     /* divide by 32
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48   0x0000000a     /* divide by 48
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64   0x0000000b     /* divide by 64
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80   0x0000000c     /* divide by 80
+                                                                */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112  0x0000000d     /* divide by
+                                                                  112 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160  0x0000000e     /* divide by
+                                                                  160 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224  0x0000000f     /* divide by
+                                                                  224 */
+
+/* UCC GETH MIIMCOM (MII Management Command Register) */
+#define MIIMCOM_SCAN_CYCLE                      0x00000002     /* Scan cycle */
+#define MIIMCOM_READ_CYCLE                      0x00000001     /* Read cycle */
+
+/* UCC GETH MIIMADD (MII Management Address Register) */
+#define MIIMADD_PHY_ADDRESS_SHIFT               (31 - 23)      /* PHY Address
+                                                                  << shift */
+#define MIIMADD_PHY_REGISTER_SHIFT              (31 - 31)      /* PHY Register
+                                                                  << shift */
+
+/* UCC GETH MIIMCON (MII Management Control Register) */
+#define MIIMCON_PHY_CONTROL_SHIFT               (31 - 31)      /* PHY Control
+                                                                  << shift */
+#define MIIMCON_PHY_STATUS_SHIFT                (31 - 31)      /* PHY Status
+                                                                  << shift */
+
+/* UCC GETH MIIMIND (MII Management Indicator Register) */
+#define MIIMIND_NOT_VALID                       0x00000004     /* Not valid */
+#define MIIMIND_SCAN                            0x00000002     /* Scan in
+                                                                  progress */
+#define MIIMIND_BUSY                            0x00000001
+
+/* UCC GETH IFSTAT (Interface Status Register) */
+#define IFSTAT_EXCESS_DEFER                     0x00000200     /* Excessive
+                                                                  transmission
+                                                                  defer */
+
+/* UCC GETH MACSTNADDR1 (Station Address Part 1 Register) */
+#define MACSTNADDR1_OCTET_6_SHIFT               (31 -  7)      /* Station
+                                                                  address 6th
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR1_OCTET_5_SHIFT               (31 - 15)      /* Station
+                                                                  address 5th
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR1_OCTET_4_SHIFT               (31 - 23)      /* Station
+                                                                  address 4th
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR1_OCTET_3_SHIFT               (31 - 31)      /* Station
+                                                                  address 3rd
+                                                                  octet <<
+                                                                  shift */
+
+/* UCC GETH MACSTNADDR2 (Station Address Part 2 Register) */
+#define MACSTNADDR2_OCTET_2_SHIFT               (31 -  7)      /* Station
+                                                                  address 2nd
+                                                                  octet <<
+                                                                  shift */
+#define MACSTNADDR2_OCTET_1_SHIFT               (31 - 15)      /* Station
+                                                                  address 1st
+                                                                  octet <<
+                                                                  shift */
+
+/* UCC GETH UEMPR (Ethernet Mac Parameter Register) */
+#define UEMPR_PAUSE_TIME_VALUE_SHIFT            (31 - 15)      /* Pause time
+                                                                  value <<
+                                                                  shift */
+#define UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT   (31 - 31)      /* Extended
+                                                                  pause time
+                                                                  value <<
+                                                                  shift */
+
+/* UCC GETH UTBIPAR (Ten Bit Interface Physical Address Register) */
+#define UTBIPAR_PHY_ADDRESS_SHIFT               (31 - 31)      /* Phy address
+                                                                  << shift */
+#define UTBIPAR_PHY_ADDRESS_MASK                0x0000001f     /* Phy address
+                                                                  mask */
+
+/* UCC GETH UESCR (Ethernet Statistics Control Register) */
+#define UESCR_AUTOZ                             0x8000 /* Automatically zero
+                                                          addressed
+                                                          statistical counter
+                                                          values */
+#define UESCR_CLRCNT                            0x4000 /* Clear all statistics
+                                                          counters */
+#define UESCR_MAXCOV_SHIFT                      (15 -  7)      /* Max
+                                                                  Coalescing
+                                                                  Value <<
+                                                                  shift */
+#define UESCR_SCOV_SHIFT                        (15 - 15)      /* Status
+                                                                  Coalescing
+                                                                  Value <<
+                                                                  shift */
+
+/* UCC GETH UDSR (Data Synchronization Register) */
+#define UDSR_MAGIC                              0x067E
+
+typedef struct ucc_geth_thread_data_tx {
+       u8 res0[104];
+} __attribute__ ((packed)) ucc_geth_thread_data_tx_t;
+
+typedef struct ucc_geth_thread_data_rx {
+       u8 res0[40];
+} __attribute__ ((packed)) ucc_geth_thread_data_rx_t;
+
+/* Send Queue Queue-Descriptor */
+typedef struct ucc_geth_send_queue_qd {
+       u32 bd_ring_base;       /* pointer to BD ring base address */
+       u8 res0[0x8];
+       u32 last_bd_completed_address;/* initialize to last entry in BD ring */
+       u8 res1[0x30];
+} __attribute__ ((packed)) ucc_geth_send_queue_qd_t;
+
+typedef struct ucc_geth_send_queue_mem_region {
+       ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES];
+} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t;
+
+typedef struct ucc_geth_thread_tx_pram {
+       u8 res0[64];
+} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t;
+
+typedef struct ucc_geth_thread_rx_pram {
+       u8 res0[128];
+} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t;
+
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING        64
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8      64
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16     96
+
+typedef struct ucc_geth_scheduler {
+       u16 cpucount0;          /* CPU packet counter */
+       u16 cpucount1;          /* CPU packet counter */
+       u16 cecount0;           /* QE packet counter */
+       u16 cecount1;           /* QE packet counter */
+       u16 cpucount2;          /* CPU packet counter */
+       u16 cpucount3;          /* CPU packet counter */
+       u16 cecount2;           /* QE packet counter */
+       u16 cecount3;           /* QE packet counter */
+       u16 cpucount4;          /* CPU packet counter */
+       u16 cpucount5;          /* CPU packet counter */
+       u16 cecount4;           /* QE packet counter */
+       u16 cecount5;           /* QE packet counter */
+       u16 cpucount6;          /* CPU packet counter */
+       u16 cpucount7;          /* CPU packet counter */
+       u16 cecount6;           /* QE packet counter */
+       u16 cecount7;           /* QE packet counter */
+       u32 weightstatus[NUM_TX_QUEUES];        /* accumulated weight factor */
+       u32 rtsrshadow;         /* temporary variable handled by QE */
+       u32 time;               /* temporary variable handled by QE */
+       u32 ttl;                /* temporary variable handled by QE */
+       u32 mblinterval;        /* max burst length interval */
+       u16 nortsrbytetime;     /* normalized value of byte time in tsr units */
+       u8 fracsiz;             /* radix 2 log value of denom. of
+                                  NorTSRByteTime */
+       u8 res0[1];
+       u8 strictpriorityq;     /* Strict Priority Mask register */
+       u8 txasap;              /* Transmit ASAP register */
+       u8 extrabw;             /* Extra BandWidth register */
+       u8 oldwfqmask;          /* temporary variable handled by QE */
+       u8 weightfactor[NUM_TX_QUEUES];
+                                     /**< weight factor for queues   */
+       u32 minw;               /* temporary variable handled by QE */
+       u8 res1[0x70 - 0x64];
+} __attribute__ ((packed)) ucc_geth_scheduler_t;
+
+typedef struct ucc_geth_tx_firmware_statistics_pram {
+       u32 sicoltx;            /* single collision */
+       u32 mulcoltx;           /* multiple collision */
+       u32 latecoltxfr;        /* late collision */
+       u32 frabortduecol;      /* frames aborted due to transmit collision */
+       u32 frlostinmactxer;    /* frames lost due to internal MAC error
+                                  transmission that are not counted on any
+                                  other counter */
+       u32 carriersenseertx;   /* carrier sense error */
+       u32 frtxok;             /* frames transmitted OK */
+       u32 txfrexcessivedefer; /* frames with defferal time greater than
+                                  specified threshold */
+       u32 txpkts256;          /* total packets (including bad) between 256
+                                  and 511 octets */
+       u32 txpkts512;          /* total packets (including bad) between 512
+                                  and 1023 octets */
+       u32 txpkts1024;         /* total packets (including bad) between 1024
+                                  and 1518 octets */
+       u32 txpktsjumbo;        /* total packets (including bad) between 1024
+                                  and MAXLength octets */
+} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t;
+
+typedef struct ucc_geth_rx_firmware_statistics_pram {
+       u32 frrxfcser;          /* frames with crc error */
+       u32 fraligner;          /* frames with alignment error */
+       u32 inrangelenrxer;     /* in range length error */
+       u32 outrangelenrxer;    /* out of range length error */
+       u32 frtoolong;          /* frame too long */
+       u32 runt;               /* runt */
+       u32 verylongevent;      /* very long event */
+       u32 symbolerror;        /* symbol error */
+       u32 dropbsy;            /* drop because of BD not ready */
+       u8 res0[0x8];
+       u32 mismatchdrop;       /* drop because of MAC filtering (e.g. address
+                                  or type mismatch) */
+       u32 underpkts;          /* total frames less than 64 octets */
+       u32 pkts256;            /* total frames (including bad) between 256 and
+                                  511 octets */
+       u32 pkts512;            /* total frames (including bad) between 512 and
+                                  1023 octets */
+       u32 pkts1024;           /* total frames (including bad) between 1024
+                                  and 1518 octets */
+       u32 pktsjumbo;          /* total frames (including bad) between 1024
+                                  and MAXLength octets */
+       u32 frlossinmacer;      /* frames lost because of internal MAC error
+                                  that is not counted in any other counter */
+       u32 pausefr;            /* pause frames */
+       u8 res1[0x4];
+       u32 removevlan;         /* total frames that had their VLAN tag removed
+                                */
+       u32 replacevlan;        /* total frames that had their VLAN tag
+                                  replaced */
+       u32 insertvlan;         /* total frames that had their VLAN tag
+                                  inserted */
+} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t;
+
+typedef struct ucc_geth_rx_interrupt_coalescing_entry {
+       u32 interruptcoalescingmaxvalue;        /* interrupt coalescing max
+                                                  value */
+       u32 interruptcoalescingcounter; /* interrupt coalescing counter,
+                                          initialize to
+                                          interruptcoalescingmaxvalue */
+} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t;
+
+typedef struct ucc_geth_rx_interrupt_coalescing_table {
+       ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES];
+                                      /**< interrupt coalescing entry */
+} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t;
+
+typedef struct ucc_geth_rx_prefetched_bds {
+       qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS];  /* prefetched bd */
+} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t;
+
+typedef struct ucc_geth_rx_bd_queues_entry {
+       u32 bdbaseptr;          /* BD base pointer */
+       u32 bdptr;              /* BD pointer */
+       u32 externalbdbaseptr;  /* external BD base pointer */
+       u32 externalbdptr;      /* external BD pointer */
+} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t;
+
+typedef struct ucc_geth_tx_global_pram {
+       u16 temoder;
+       u8 res0[0x38 - 0x02];
+       u32 sqptr;              /* a base pointer to send queue memory region */
+       u32 schedulerbasepointer;       /* a base pointer to scheduler memory
+                                          region */
+       u32 txrmonbaseptr;      /* base pointer to Tx RMON statistics counter */
+       u32 tstate;             /* tx internal state. High byte contains
+                                  function code */
+       u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
+       u32 vtagtable[0x8];     /* 8 4-byte VLAN tags */
+       u32 tqptr;              /* a base pointer to the Tx Queues Memory
+                                  Region */
+       u8 res2[0x80 - 0x74];
+} __attribute__ ((packed)) ucc_geth_tx_global_pram_t;
+
+/* structure representing Extended Filtering Global Parameters in PRAM */
+typedef struct ucc_geth_exf_global_pram {
+       u32 l2pcdptr;           /* individual address filter, high */
+       u8 res0[0x10 - 0x04];
+} __attribute__ ((packed)) ucc_geth_exf_global_pram_t;
+
+typedef struct ucc_geth_rx_global_pram {
+       u32 remoder;            /* ethernet mode reg. */
+       u32 rqptr;              /* base pointer to the Rx Queues Memory Region*/
+       u32 res0[0x1];
+       u8 res1[0x20 - 0xC];
+       u16 typeorlen;          /* cutoff point less than which, type/len field
+                                  is considered length */
+       u8 res2[0x1];
+       u8 rxgstpack;           /* acknowledgement on GRACEFUL STOP RX command*/
+       u32 rxrmonbaseptr;      /* base pointer to Rx RMON statistics counter */
+       u8 res3[0x30 - 0x28];
+       u32 intcoalescingptr;   /* Interrupt coalescing table pointer */
+       u8 res4[0x36 - 0x34];
+       u8 rstate;              /* rx internal state. High byte contains
+                                  function code */
+       u8 res5[0x46 - 0x37];
+       u16 mrblr;              /* max receive buffer length reg. */
+       u32 rbdqptr;            /* base pointer to RxBD parameter table
+                                  description */
+       u16 mflr;               /* max frame length reg. */
+       u16 minflr;             /* min frame length reg. */
+       u16 maxd1;              /* max dma1 length reg. */
+       u16 maxd2;              /* max dma2 length reg. */
+       u32 ecamptr;            /* external CAM address */
+       u32 l2qt;               /* VLAN priority mapping table. */
+       u32 l3qt[0x8];          /* IP priority mapping table. */
+       u16 vlantype;           /* vlan type */
+       u16 vlantci;            /* default vlan tci */
+       u8 addressfiltering[64];        /* address filtering data structure */
+       u32 exfGlobalParam;     /* base address for extended filtering global
+                                  parameters */
+       u8 res6[0x100 - 0xC4];  /* Initialize to zero */
+} __attribute__ ((packed)) ucc_geth_rx_global_pram_t;
+
+#define GRACEFUL_STOP_ACKNOWLEDGE_RX            0x01
+
+/* structure representing InitEnet command */
+typedef struct ucc_geth_init_pram {
+       u8 resinit1;
+       u8 resinit2;
+       u8 resinit3;
+       u8 resinit4;
+       u16 resinit5;
+       u8 res1[0x1];
+       u8 largestexternallookupkeysize;
+       u32 rgftgfrxglobal;
+       u32 rxthread[ENET_INIT_PARAM_MAX_ENTRIES_RX];   /* rx threads */
+       u8 res2[0x38 - 0x30];
+       u32 txglobal;           /* tx global */
+       u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX];   /* tx threads */
+       u8 res3[0x1];
+} __attribute__ ((packed)) ucc_geth_init_pram_t;
+
+#define ENET_INIT_PARAM_RGF_SHIFT               (32 - 4)
+#define ENET_INIT_PARAM_TGF_SHIFT               (32 - 8)
+
+#define ENET_INIT_PARAM_RISC_MASK               0x0000003f
+#define ENET_INIT_PARAM_PTR_MASK                0x00ffffc0
+#define ENET_INIT_PARAM_SNUM_MASK               0xff000000
+#define ENET_INIT_PARAM_SNUM_SHIFT              24
+
+#define ENET_INIT_PARAM_MAGIC_RES_INIT1         0x06
+#define ENET_INIT_PARAM_MAGIC_RES_INIT2         0x30
+#define ENET_INIT_PARAM_MAGIC_RES_INIT3         0xff
+#define ENET_INIT_PARAM_MAGIC_RES_INIT4         0x00
+#define ENET_INIT_PARAM_MAGIC_RES_INIT5         0x0400
+
+/* structure representing 82xx Address Filtering Enet Address in PRAM */
+typedef struct ucc_geth_82xx_enet_address {
+       u8 res1[0x2];
+       u16 h;                  /* address (MSB) */
+       u16 m;                  /* address */
+       u16 l;                  /* address (LSB) */
+} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t;
+
+/* structure representing 82xx Address Filtering PRAM */
+typedef struct ucc_geth_82xx_address_filtering_pram {
+       u32 iaddr_h;            /* individual address filter, high */
+       u32 iaddr_l;            /* individual address filter, low */
+       u32 gaddr_h;            /* group address filter, high */
+       u32 gaddr_l;            /* group address filter, low */
+       ucc_geth_82xx_enet_address_t taddr;
+       ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS];
+       u8 res0[0x40 - 0x38];
+} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t;
+
+/* GETH Tx firmware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_tx_firmware_statistics {
+       u32 sicoltx;            /* single collision */
+       u32 mulcoltx;           /* multiple collision */
+       u32 latecoltxfr;        /* late collision */
+       u32 frabortduecol;      /* frames aborted due to transmit collision */
+       u32 frlostinmactxer;    /* frames lost due to internal MAC error
+                                  transmission that are not counted on any
+                                  other counter */
+       u32 carriersenseertx;   /* carrier sense error */
+       u32 frtxok;             /* frames transmitted OK */
+       u32 txfrexcessivedefer; /* frames with defferal time greater than
+                                  specified threshold */
+       u32 txpkts256;          /* total packets (including bad) between 256
+                                  and 511 octets */
+       u32 txpkts512;          /* total packets (including bad) between 512
+                                  and 1023 octets */
+       u32 txpkts1024;         /* total packets (including bad) between 1024
+                                  and 1518 octets */
+       u32 txpktsjumbo;        /* total packets (including bad) between 1024
+                                  and MAXLength octets */
+} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t;
+
+/* GETH Rx firmware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_rx_firmware_statistics {
+       u32 frrxfcser;          /* frames with crc error */
+       u32 fraligner;          /* frames with alignment error */
+       u32 inrangelenrxer;     /* in range length error */
+       u32 outrangelenrxer;    /* out of range length error */
+       u32 frtoolong;          /* frame too long */
+       u32 runt;               /* runt */
+       u32 verylongevent;      /* very long event */
+       u32 symbolerror;        /* symbol error */
+       u32 dropbsy;            /* drop because of BD not ready */
+       u8 res0[0x8];
+       u32 mismatchdrop;       /* drop because of MAC filtering (e.g. address
+                                  or type mismatch) */
+       u32 underpkts;          /* total frames less than 64 octets */
+       u32 pkts256;            /* total frames (including bad) between 256 and
+                                  511 octets */
+       u32 pkts512;            /* total frames (including bad) between 512 and
+                                  1023 octets */
+       u32 pkts1024;           /* total frames (including bad) between 1024
+                                  and 1518 octets */
+       u32 pktsjumbo;          /* total frames (including bad) between 1024
+                                  and MAXLength octets */
+       u32 frlossinmacer;      /* frames lost because of internal MAC error
+                                  that is not counted in any other counter */
+       u32 pausefr;            /* pause frames */
+       u8 res1[0x4];
+       u32 removevlan;         /* total frames that had their VLAN tag removed
+                                */
+       u32 replacevlan;        /* total frames that had their VLAN tag
+                                  replaced */
+       u32 insertvlan;         /* total frames that had their VLAN tag
+                                  inserted */
+} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t;
+
+/* GETH hardware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_hardware_statistics {
+       u32 tx64;               /* Total number of frames (including bad
+                                  frames) transmitted that were exactly of the
+                                  minimal length (64 for un tagged, 68 for
+                                  tagged, or with length exactly equal to the
+                                  parameter MINLength */
+       u32 tx127;              /* Total number of frames (including bad
+                                  frames) transmitted that were between
+                                  MINLength (Including FCS length==4) and 127
+                                  octets */
+       u32 tx255;              /* Total number of frames (including bad
+                                  frames) transmitted that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 rx64;               /* Total number of frames received including
+                                  bad frames that were exactly of the mninimal
+                                  length (64 bytes) */
+       u32 rx127;              /* Total number of frames (including bad
+                                  frames) received that were between MINLength
+                                  (Including FCS length==4) and 127 octets */
+       u32 rx255;              /* Total number of frames (including bad
+                                  frames) received that were between 128
+                                  (Including FCS length==4) and 255 octets */
+       u32 txok;               /* Total number of octets residing in frames
+                                  that where involved in succesfull
+                                  transmission */
+       u16 txcf;               /* Total number of PAUSE control frames
+                                  transmitted by this MAC */
+       u32 tmca;               /* Total number of frames that were transmitted
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 tbca;               /* Total number of frames transmitted
+                                  succesfully that had destination address
+                                  field equal to the broadcast address */
+       u32 rxfok;              /* Total number of frames received OK */
+       u32 rxbok;              /* Total number of octets received OK */
+       u32 rbyt;               /* Total number of octets received including
+                                  octets in bad frames. Must be implemented in
+                                  HW because it includes octets in frames that
+                                  never even reach the UCC */
+       u32 rmca;               /* Total number of frames that were received
+                                  succesfully with the group address bit set
+                                  that are not broadcast frames */
+       u32 rbca;               /* Total number of frames received succesfully
+                                  that had destination address equal to the
+                                  broadcast address */
+} __attribute__ ((packed)) ucc_geth_hardware_statistics_t;
+
+/* UCC GETH Tx errors returned via TxConf callback */
+#define TX_ERRORS_DEF      0x0200
+#define TX_ERRORS_EXDEF    0x0100
+#define TX_ERRORS_LC       0x0080
+#define TX_ERRORS_RL       0x0040
+#define TX_ERRORS_RC_MASK  0x003C
+#define TX_ERRORS_RC_SHIFT 2
+#define TX_ERRORS_UN       0x0002
+#define TX_ERRORS_CSL      0x0001
+
+/* UCC GETH Rx errors returned via RxStore callback */
+#define RX_ERRORS_CMR      0x0200
+#define RX_ERRORS_M        0x0100
+#define RX_ERRORS_BC       0x0080
+#define RX_ERRORS_MC       0x0040
+
+/* Transmit BD. These are in addition to values defined in uccf. */
+#define T_VID      0x003c0000  /* insert VLAN id index mask. */
+#define T_DEF      (((u32) TX_ERRORS_DEF     ) << 16)
+#define T_EXDEF    (((u32) TX_ERRORS_EXDEF   ) << 16)
+#define T_LC       (((u32) TX_ERRORS_LC      ) << 16)
+#define T_RL       (((u32) TX_ERRORS_RL      ) << 16)
+#define T_RC_MASK  (((u32) TX_ERRORS_RC_MASK ) << 16)
+#define T_UN       (((u32) TX_ERRORS_UN      ) << 16)
+#define T_CSL      (((u32) TX_ERRORS_CSL     ) << 16)
+#define T_ERRORS_REPORT  (T_DEF | T_EXDEF | T_LC | T_RL | T_RC_MASK \
+               | T_UN | T_CSL) /* transmit errors to report */
+
+/* Receive BD. These are in addition to values defined in uccf. */
+#define R_LG    0x00200000     /* Frame length violation.  */
+#define R_NO    0x00100000     /* Non-octet aligned frame.  */
+#define R_SH    0x00080000     /* Short frame.  */
+#define R_CR    0x00040000     /* CRC error.  */
+#define R_OV    0x00020000     /* Overrun.  */
+#define R_IPCH  0x00010000     /* IP checksum check failed. */
+#define R_CMR   (((u32) RX_ERRORS_CMR  ) << 16)
+#define R_M     (((u32) RX_ERRORS_M    ) << 16)
+#define R_BC    (((u32) RX_ERRORS_BC   ) << 16)
+#define R_MC    (((u32) RX_ERRORS_MC   ) << 16)
+#define R_ERRORS_REPORT (R_CMR | R_M | R_BC | R_MC)    /* receive errors to
+                                                          report */
+#define R_ERRORS_FATAL  (R_LG  | R_NO | R_SH | R_CR | \
+               R_OV | R_IPCH)  /* receive errors to discard */
+
+/* Alignments */
+#define UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT      256
+#define UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT       128
+#define UCC_GETH_THREAD_RX_PRAM_ALIGNMENT       128
+#define UCC_GETH_THREAD_TX_PRAM_ALIGNMENT       64
+#define UCC_GETH_THREAD_DATA_ALIGNMENT          256    /* spec gives values
+                                                          based on num of
+                                                          threads, but always
+                                                          using the maximum is
+                                                          easier */
+#define UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT 32
+#define UCC_GETH_SCHEDULER_ALIGNMENT           4       /* This is a guess */
+#define UCC_GETH_TX_STATISTICS_ALIGNMENT       4       /* This is a guess */
+#define UCC_GETH_RX_STATISTICS_ALIGNMENT       4       /* This is a guess */
+#define UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT     4       /* This is a
+                                                                  guess */
+#define UCC_GETH_RX_BD_QUEUES_ALIGNMENT                8       /* This is a guess */
+#define UCC_GETH_RX_PREFETCHED_BDS_ALIGNMENT   128     /* This is a guess */
+#define UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT 4   /* This
+                                                                          is a
+                                                                          guess
+                                                                        */
+#define UCC_GETH_RX_BD_RING_ALIGNMENT          32
+#define UCC_GETH_TX_BD_RING_ALIGNMENT          32
+#define UCC_GETH_MRBLR_ALIGNMENT               128
+#define UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT     4
+#define UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT      32
+#define UCC_GETH_RX_DATA_BUF_ALIGNMENT         64
+
+#define UCC_GETH_TAD_EF                         0x80
+#define UCC_GETH_TAD_V                          0x40
+#define UCC_GETH_TAD_REJ                        0x20
+#define UCC_GETH_TAD_VTAG_OP_RIGHT_SHIFT        2
+#define UCC_GETH_TAD_VTAG_OP_SHIFT              6
+#define UCC_GETH_TAD_V_NON_VTAG_OP              0x20
+#define UCC_GETH_TAD_RQOS_SHIFT                 0
+#define UCC_GETH_TAD_V_PRIORITY_SHIFT           5
+#define UCC_GETH_TAD_CFI                        0x10
+
+#define UCC_GETH_VLAN_PRIORITY_MAX              8
+#define UCC_GETH_IP_PRIORITY_MAX                64
+#define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX        8
+#define UCC_GETH_RX_BD_RING_SIZE_MIN            8
+#define UCC_GETH_TX_BD_RING_SIZE_MIN            2
+
+#define UCC_GETH_SIZE_OF_BD                     QE_SIZEOF_BD
+
+/* Driver definitions */
+#define TX_BD_RING_LEN                          0x10
+#define RX_BD_RING_LEN                          0x10
+#define UCC_GETH_DEV_WEIGHT                     TX_BD_RING_LEN
+
+#define TX_RING_MOD_MASK(size)                  (size-1)
+#define RX_RING_MOD_MASK(size)                  (size-1)
+
+#define ENET_NUM_OCTETS_PER_ADDRESS             6
+#define ENET_GROUP_ADDR                         0x01   /* Group address mask
+                                                          for ethernet
+                                                          addresses */
+
+#define TX_TIMEOUT                              (1*HZ)
+#define SKB_ALLOC_TIMEOUT                       100000
+#define PHY_INIT_TIMEOUT                        100000
+#define PHY_CHANGE_TIME                         2
+
+/* Fast Ethernet (10/100 Mbps) */
+#define UCC_GETH_URFS_INIT                      512    /* Rx virtual FIFO size
+                                                        */
+#define UCC_GETH_URFET_INIT                     256    /* 1/2 urfs */
+#define UCC_GETH_URFSET_INIT                    384    /* 3/4 urfs */
+#define UCC_GETH_UTFS_INIT                      512    /* Tx virtual FIFO size
+                                                        */
+#define UCC_GETH_UTFET_INIT                     256    /* 1/2 utfs */
+#define UCC_GETH_UTFTT_INIT                     128
+/* Gigabit Ethernet (1000 Mbps) */
+#define UCC_GETH_URFS_GIGA_INIT                 4096/*2048*/   /* Rx virtual
+                                                                  FIFO size */
+#define UCC_GETH_URFET_GIGA_INIT                2048/*1024*/   /* 1/2 urfs */
+#define UCC_GETH_URFSET_GIGA_INIT               3072/*1536*/   /* 3/4 urfs */
+#define UCC_GETH_UTFS_GIGA_INIT                 8192/*2048*/   /* Tx virtual
+                                                                  FIFO size */
+#define UCC_GETH_UTFET_GIGA_INIT                4096/*1024*/   /* 1/2 utfs */
+#define UCC_GETH_UTFTT_GIGA_INIT                0x400/*0x40*/  /* */
+
+#define UCC_GETH_REMODER_INIT                   0      /* bits that must be
+                                                          set */
+#define UCC_GETH_TEMODER_INIT                   0xC000 /* bits that must */
+#define UCC_GETH_UPSMR_INIT                     (UPSMR_RES1)   /* Start value
+                                                                  for this
+                                                                  register */
+#define UCC_GETH_MACCFG1_INIT                   0
+#define UCC_GETH_MACCFG2_INIT                   (MACCFG2_RESERVED_1)
+#define UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT    \
+                               (MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112)
+
+/* Ethernet speed */
+typedef enum enet_speed {
+       ENET_SPEED_10BT,        /* 10 Base T */
+       ENET_SPEED_100BT,       /* 100 Base T */
+       ENET_SPEED_1000BT       /* 1000 Base T */
+} enet_speed_e;
+
+/* Ethernet Address Type. */
+typedef enum enet_addr_type {
+       ENET_ADDR_TYPE_INDIVIDUAL,
+       ENET_ADDR_TYPE_GROUP,
+       ENET_ADDR_TYPE_BROADCAST
+} enet_addr_type_e;
+
+/* TBI / MII Set Register */
+typedef enum enet_tbi_mii_reg {
+       ENET_TBI_MII_CR = 0x00, /* Control (CR ) */
+       ENET_TBI_MII_SR = 0x01, /* Status (SR ) */
+       ENET_TBI_MII_ANA = 0x04,        /* AN advertisement (ANA ) */
+       ENET_TBI_MII_ANLPBPA = 0x05,    /* AN link partner base page ability
+                                          (ANLPBPA) */
+       ENET_TBI_MII_ANEX = 0x06,       /* AN expansion (ANEX ) */
+       ENET_TBI_MII_ANNPT = 0x07,      /* AN next page transmit (ANNPT ) */
+       ENET_TBI_MII_ANLPANP = 0x08,    /* AN link partner ability next page
+                                          (ANLPANP) */
+       ENET_TBI_MII_EXST = 0x0F,       /* Extended status (EXST ) */
+       ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics (JD ) */
+       ENET_TBI_MII_TBICON = 0x11      /* TBI control (TBICON ) */
+} enet_tbi_mii_reg_e;
+
+/* UCC GETH 82xx Ethernet Address Recognition Location */
+typedef enum ucc_geth_enet_address_recognition_location {
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station
+                                                                     address */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST, /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr1 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR2,      /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr2 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR3,      /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr3 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_LAST,  /* additional
+                                                                  station
+                                                                  address
+                                                                  paddr4 */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH,  /* group hash */
+       UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual
+                                                                     hash */
+} ucc_geth_enet_address_recognition_location_e;
+
+/* UCC GETH vlan operation tagged */
+typedef enum ucc_geth_vlan_operation_tagged {
+       UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0,       /* Tagged - nop */
+       UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG
+               = 0x1,  /* Tagged - replace vid portion of q tag */
+       UCC_GETH_VLAN_OPERATION_TAGGED_IF_VID0_REPLACE_VID_WITH_DEFAULT_VALUE
+               = 0x2,  /* Tagged - if vid0 replace vid with default value  */
+       UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME
+               = 0x3   /* Tagged - extract q tag from frame */
+} ucc_geth_vlan_operation_tagged_e;
+
+/* UCC GETH vlan operation non-tagged */
+typedef enum ucc_geth_vlan_operation_non_tagged {
+       UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0,   /* Non tagged - nop */
+       UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1   /* Non tagged -
+                                                                  q tag insert
+                                                                */
+} ucc_geth_vlan_operation_non_tagged_e;
+
+/* UCC GETH Rx Quality of Service Mode */
+typedef enum ucc_geth_qos_mode {
+       UCC_GETH_QOS_MODE_DEFAULT = 0x0,        /* default queue */
+       UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1,     /* queue
+                                                                  determined
+                                                                  by L2
+                                                                  criteria */
+       UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L3_CRITERIA = 0x2      /* queue
+                                                                  determined
+                                                                  by L3
+                                                                  criteria */
+} ucc_geth_qos_mode_e;
+
+/* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together
+   for combined functionality */
+typedef enum ucc_geth_statistics_gathering_mode {
+       UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000,   /* No
+                                                                  statistics
+                                                                  gathering */
+       UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE = 0x00000001,/* Enable
+                                                                   hardware
+                                                                   statistics
+                                                                   gathering
+                                                                 */
+       UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX = 0x00000004,/*Enable
+                                                                     firmware
+                                                                     tx
+                                                                     statistics
+                                                                     gathering
+                                                                    */
+       UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX = 0x00000008/* Enable
+                                                                     firmware
+                                                                     rx
+                                                                     statistics
+                                                                     gathering
+                                                                   */
+} ucc_geth_statistics_gathering_mode_e;
+
+/* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */
+typedef enum ucc_geth_maccfg2_pad_and_crc_mode {
+       UCC_GETH_PAD_AND_CRC_MODE_NONE
+               = MACCFG2_PAD_AND_CRC_MODE_NONE,        /* Neither Padding
+                                                          short frames
+                                                          nor CRC */
+       UCC_GETH_PAD_AND_CRC_MODE_CRC_ONLY
+               = MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY,    /* Append
+                                                          CRC only */
+       UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC =
+           MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC
+} ucc_geth_maccfg2_pad_and_crc_mode_e;
+
+/* UCC GETH upsmr Flow Control Mode */
+typedef enum ucc_geth_flow_control_mode {
+       UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000,    /* No automatic
+                                                                  flow control
+                                                                */
+       UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY
+               = 0x00004000    /* Send pause frame when RxFIFO reaches its
+                                  emergency threshold */
+} ucc_geth_flow_control_mode_e;
+
+/* UCC GETH number of threads */
+typedef enum ucc_geth_num_of_threads {
+       UCC_GETH_NUM_OF_THREADS_1 = 0x1,        /* 1 */
+       UCC_GETH_NUM_OF_THREADS_2 = 0x2,        /* 2 */
+       UCC_GETH_NUM_OF_THREADS_4 = 0x0,        /* 4 */
+       UCC_GETH_NUM_OF_THREADS_6 = 0x3,        /* 6 */
+       UCC_GETH_NUM_OF_THREADS_8 = 0x4 /* 8 */
+} ucc_geth_num_of_threads_e;
+
+/* UCC GETH number of station addresses */
+typedef enum ucc_geth_num_of_station_addresses {
+       UCC_GETH_NUM_OF_STATION_ADDRESSES_1,    /* 1 */
+       UCC_GETH_NUM_OF_STATION_ADDRESSES_5     /* 5 */
+} ucc_geth_num_of_station_addresses_e;
+
+typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS];
+
+/* UCC GETH 82xx Ethernet Address Container */
+typedef struct enet_addr_container {
+       enet_addr_t address;    /* ethernet address */
+       ucc_geth_enet_address_recognition_location_e location;  /* location in
+                                                                  82xx address
+                                                                  recognition
+                                                                  hardware */
+       struct list_head node;
+} enet_addr_container_t;
+
+#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node)
+
+/* UCC GETH Termination Action Descriptor (TAD) structure. */
+typedef struct ucc_geth_tad_params {
+       int rx_non_dynamic_extended_features_mode;
+       int reject_frame;
+       ucc_geth_vlan_operation_tagged_e vtag_op;
+       ucc_geth_vlan_operation_non_tagged_e vnontag_op;
+       ucc_geth_qos_mode_e rqos;
+       u8 vpri;
+       u16 vid;
+} ucc_geth_tad_params_t;
+
+/* GETH protocol initialization structure */
+typedef struct ucc_geth_info {
+       ucc_fast_info_t uf_info;
+       u8 numQueuesTx;
+       u8 numQueuesRx;
+       int ipCheckSumCheck;
+       int ipCheckSumGenerate;
+       int rxExtendedFiltering;
+       u32 extendedFilteringChainPointer;
+       u16 typeorlen;
+       int dynamicMaxFrameLength;
+       int dynamicMinFrameLength;
+       u8 nonBackToBackIfgPart1;
+       u8 nonBackToBackIfgPart2;
+       u8 miminumInterFrameGapEnforcement;
+       u8 backToBackInterFrameGap;
+       int ipAddressAlignment;
+       int lengthCheckRx;
+       u32 mblinterval;
+       u16 nortsrbytetime;
+       u8 fracsiz;
+       u8 strictpriorityq;
+       u8 txasap;
+       u8 extrabw;
+       int miiPreambleSupress;
+       u8 altBebTruncation;
+       int altBeb;
+       int backPressureNoBackoff;
+       int noBackoff;
+       int excessDefer;
+       u8 maxRetransmission;
+       u8 collisionWindow;
+       int pro;
+       int cap;
+       int rsh;
+       int rlpb;
+       int cam;
+       int bro;
+       int ecm;
+       int receiveFlowControl;
+       u8 maxGroupAddrInHash;
+       u8 maxIndAddrInHash;
+       u8 prel;
+       u16 maxFrameLength;
+       u16 minFrameLength;
+       u16 maxD1Length;
+       u16 maxD2Length;
+       u16 vlantype;
+       u16 vlantci;
+       u32 ecamptr;
+       u32 eventRegMask;
+       u16 pausePeriod;
+       u16 extensionField;
+       u8 phy_address;
+       u32 board_flags;
+       u32 phy_interrupt;
+       u8 weightfactor[NUM_TX_QUEUES];
+       u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
+       u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
+       u8 l3qt[UCC_GETH_IP_PRIORITY_MAX];
+       u32 vtagtable[UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX];
+       u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
+       u16 bdRingLenTx[NUM_TX_QUEUES];
+       u16 bdRingLenRx[NUM_RX_QUEUES];
+       enet_interface_e enet_interface;
+       ucc_geth_num_of_station_addresses_e numStationAddresses;
+        qe_fltr_largest_external_tbl_lookup_key_size_e
+           largestexternallookupkeysize;
+       ucc_geth_statistics_gathering_mode_e statisticsMode;
+       ucc_geth_vlan_operation_tagged_e vlanOperationTagged;
+       ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged;
+       ucc_geth_qos_mode_e rxQoSMode;
+       ucc_geth_flow_control_mode_e aufc;
+       ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc;
+       ucc_geth_num_of_threads_e numThreadsTx;
+       ucc_geth_num_of_threads_e numThreadsRx;
+       qe_risc_allocation_e riscTx;
+       qe_risc_allocation_e riscRx;
+} ucc_geth_info_t;
+
+/* structure representing UCC GETH */
+typedef struct ucc_geth_private {
+       ucc_geth_info_t *ug_info;
+       ucc_fast_private_t *uccf;
+       struct net_device *dev;
+       struct net_device_stats stats;  /* linux network statistics */
+       ucc_geth_t *ug_regs;
+       ucc_geth_init_pram_t *p_init_enet_param_shadow;
+       ucc_geth_exf_global_pram_t *p_exf_glbl_param;
+       u32 exf_glbl_param_offset;
+       ucc_geth_rx_global_pram_t *p_rx_glbl_pram;
+       u32 rx_glbl_pram_offset;
+       ucc_geth_tx_global_pram_t *p_tx_glbl_pram;
+       u32 tx_glbl_pram_offset;
+       ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg;
+       u32 send_q_mem_reg_offset;
+       ucc_geth_thread_data_tx_t *p_thread_data_tx;
+       u32 thread_dat_tx_offset;
+       ucc_geth_thread_data_rx_t *p_thread_data_rx;
+       u32 thread_dat_rx_offset;
+       ucc_geth_scheduler_t *p_scheduler;
+       u32 scheduler_offset;
+       ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+       u32 tx_fw_statistics_pram_offset;
+       ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+       u32 rx_fw_statistics_pram_offset;
+       ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl;
+       u32 rx_irq_coalescing_tbl_offset;
+       ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl;
+       u32 rx_bd_qs_tbl_offset;
+       u8 *p_tx_bd_ring[NUM_TX_QUEUES];
+       u32 tx_bd_ring_offset[NUM_TX_QUEUES];
+       u8 *p_rx_bd_ring[NUM_RX_QUEUES];
+       u32 rx_bd_ring_offset[NUM_RX_QUEUES];
+       u8 *confBd[NUM_TX_QUEUES];
+       u8 *txBd[NUM_TX_QUEUES];
+       u8 *rxBd[NUM_RX_QUEUES];
+       int badFrame[NUM_RX_QUEUES];
+       u16 cpucount[NUM_TX_QUEUES];
+       volatile u16 *p_cpucount[NUM_TX_QUEUES];
+       int indAddrRegUsed[NUM_OF_PADDRS];
+       enet_addr_t paddr[NUM_OF_PADDRS];
+       u8 numGroupAddrInHash;
+       u8 numIndAddrInHash;
+       u8 numIndAddrInReg;
+       int rx_extended_features;
+       int rx_non_dynamic_extended_features;
+       struct list_head conf_skbs;
+       struct list_head group_hash_q;
+       struct list_head ind_hash_q;
+       u32 saved_uccm;
+       spinlock_t lock;
+       /* pointers to arrays of skbuffs for tx and rx */
+       struct sk_buff **tx_skbuff[NUM_TX_QUEUES];
+       struct sk_buff **rx_skbuff[NUM_RX_QUEUES];
+       /* indices pointing to the next free sbk in skb arrays */
+       u16 skb_curtx[NUM_TX_QUEUES];
+       u16 skb_currx[NUM_RX_QUEUES];
+       /* index of the first skb which hasn't been transmitted yet. */
+       u16 skb_dirtytx[NUM_TX_QUEUES];
+
+       struct work_struct tq;
+       struct timer_list phy_info_timer;
+       struct ugeth_mii_info *mii_info;
+       int oldspeed;
+       int oldduplex;
+       int oldlink;
+} ucc_geth_private_t;
+
+#endif                         /* __UCC_GETH_H__ */
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
new file mode 100644 (file)
index 0000000..f91028c
--- /dev/null
@@ -0,0 +1,801 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * UCC GETH Driver -- PHY handling
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_phy.h"
+#include <platforms/83xx/mpc8360e_pb.h>
+
+#define ugphy_printk(level, format, arg...)  \
+        printk(level format "\n", ## arg)
+
+#define ugphy_dbg(format, arg...)            \
+        ugphy_printk(KERN_DEBUG, format , ## arg)
+#define ugphy_err(format, arg...)            \
+        ugphy_printk(KERN_ERR, format , ## arg)
+#define ugphy_info(format, arg...)           \
+        ugphy_printk(KERN_INFO, format , ## arg)
+#define ugphy_warn(format, arg...)           \
+        ugphy_printk(KERN_WARNING, format , ## arg)
+
+#ifdef UGETH_VERBOSE_DEBUG
+#define ugphy_vdbg ugphy_dbg
+#else
+#define ugphy_vdbg(fmt, args...) do { } while (0)
+#endif                         /* UGETH_VERBOSE_DEBUG */
+
+static void config_genmii_advert(struct ugeth_mii_info *mii_info);
+static void genmii_setup_forced(struct ugeth_mii_info *mii_info);
+static void genmii_restart_aneg(struct ugeth_mii_info *mii_info);
+static int gbit_config_aneg(struct ugeth_mii_info *mii_info);
+static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
+static int genmii_update_link(struct ugeth_mii_info *mii_info);
+static int genmii_read_status(struct ugeth_mii_info *mii_info);
+u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum);
+void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val);
+
+static u8 *bcsr_regs = NULL;
+
+/* Write value to the PHY for this device to the register at regnum, */
+/* waiting until the write is done before it returns.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_mii_mng_t *mii_regs;
+       enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+       u32 tmp_reg;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irq(&ugeth->lock);
+
+       mii_regs = ugeth->mii_info->mii_regs;
+
+       /* Set this UCC to be the master of the MII managment */
+       ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
+
+       /* Stop the MII management read cycle */
+       out_be32(&mii_regs->miimcom, 0);
+       /* Setting up the MII Mangement Address Register */
+       tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
+       out_be32(&mii_regs->miimadd, tmp_reg);
+
+       /* Setting up the MII Mangement Control Register with the value */
+       out_be32(&mii_regs->miimcon, (u32) value);
+
+       /* Wait till MII management write is complete */
+       while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
+               cpu_relax();
+
+       spin_unlock_irq(&ugeth->lock);
+
+       udelay(10000);
+}
+
+/* Reads from register regnum in the PHY for device dev, */
+/* returning the value.  Clears miimcom first.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
+{
+       ucc_geth_private_t *ugeth = netdev_priv(dev);
+       ucc_mii_mng_t *mii_regs;
+       enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+       u32 tmp_reg;
+       u16 value;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irq(&ugeth->lock);
+
+       mii_regs = ugeth->mii_info->mii_regs;
+
+       /* Setting up the MII Mangement Address Register */
+       tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
+       out_be32(&mii_regs->miimadd, tmp_reg);
+
+       /* Perform an MII management read cycle */
+       out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE);
+
+       /* Wait till MII management write is complete */
+       while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
+               cpu_relax();
+
+       udelay(10000);
+
+       /* Read MII management status  */
+       value = (u16) in_be32(&mii_regs->miimstat);
+       out_be32(&mii_regs->miimcom, 0);
+       if (value == 0xffff)
+               ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x",
+                          mii_id, mii_reg, (u32) & (mii_regs->miimcfg));
+
+       spin_unlock_irq(&ugeth->lock);
+
+       return (value);
+}
+
+void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->phyinfo->ack_interrupt)
+               mii_info->phyinfo->ack_interrupt(mii_info);
+}
+
+void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
+                                u32 interrupts)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       mii_info->interrupts = interrupts;
+       if (mii_info->phyinfo->config_intr)
+               mii_info->phyinfo->config_intr(mii_info);
+}
+
+/* Writes MII_ADVERTISE with the appropriate values, after
+ * sanitizing advertise to make sure only supported features
+ * are advertised
+ */
+static void config_genmii_advert(struct ugeth_mii_info *mii_info)
+{
+       u32 advertise;
+       u16 adv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Only allow advertising what this PHY supports */
+       mii_info->advertising &= mii_info->phyinfo->features;
+       advertise = mii_info->advertising;
+
+       /* Setup standard advertisement */
+       adv = phy_read(mii_info, MII_ADVERTISE);
+       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+       if (advertise & ADVERTISED_10baseT_Half)
+               adv |= ADVERTISE_10HALF;
+       if (advertise & ADVERTISED_10baseT_Full)
+               adv |= ADVERTISE_10FULL;
+       if (advertise & ADVERTISED_100baseT_Half)
+               adv |= ADVERTISE_100HALF;
+       if (advertise & ADVERTISED_100baseT_Full)
+               adv |= ADVERTISE_100FULL;
+       phy_write(mii_info, MII_ADVERTISE, adv);
+}
+
+static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
+{
+       u16 ctrl;
+       u32 features = mii_info->phyinfo->features;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       ctrl = phy_read(mii_info, MII_BMCR);
+
+       ctrl &=
+           ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
+       ctrl |= BMCR_RESET;
+
+       switch (mii_info->speed) {
+       case SPEED_1000:
+               if (features & (SUPPORTED_1000baseT_Half
+                               | SUPPORTED_1000baseT_Full)) {
+                       ctrl |= BMCR_SPEED1000;
+                       break;
+               }
+               mii_info->speed = SPEED_100;
+       case SPEED_100:
+               if (features & (SUPPORTED_100baseT_Half
+                               | SUPPORTED_100baseT_Full)) {
+                       ctrl |= BMCR_SPEED100;
+                       break;
+               }
+               mii_info->speed = SPEED_10;
+       case SPEED_10:
+               if (features & (SUPPORTED_10baseT_Half
+                               | SUPPORTED_10baseT_Full))
+                       break;
+       default:                /* Unsupported speed! */
+               ugphy_err("%s: Bad speed!", mii_info->dev->name);
+               break;
+       }
+
+       phy_write(mii_info, MII_BMCR, ctrl);
+}
+
+/* Enable and Restart Autonegotiation */
+static void genmii_restart_aneg(struct ugeth_mii_info *mii_info)
+{
+       u16 ctl;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       ctl = phy_read(mii_info, MII_BMCR);
+       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+       phy_write(mii_info, MII_BMCR, ctl);
+}
+
+static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       u16 adv;
+       u32 advertise;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->autoneg) {
+               /* Configure the ADVERTISE register */
+               config_genmii_advert(mii_info);
+               advertise = mii_info->advertising;
+
+               adv = phy_read(mii_info, MII_1000BASETCONTROL);
+               adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+                        MII_1000BASETCONTROL_HALFDUPLEXCAP);
+               if (advertise & SUPPORTED_1000baseT_Half)
+                       adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+               if (advertise & SUPPORTED_1000baseT_Full)
+                       adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+               phy_write(mii_info, MII_1000BASETCONTROL, adv);
+
+               /* Start/Restart aneg */
+               genmii_restart_aneg(mii_info);
+       } else
+               genmii_setup_forced(mii_info);
+
+       return 0;
+}
+
+static int genmii_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->autoneg) {
+               config_genmii_advert(mii_info);
+               genmii_restart_aneg(mii_info);
+       } else
+               genmii_setup_forced(mii_info);
+
+       return 0;
+}
+
+static int genmii_update_link(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Do a fake read */
+       phy_read(mii_info, MII_BMSR);
+
+       /* Read link and autonegotiation status */
+       status = phy_read(mii_info, MII_BMSR);
+       if ((status & BMSR_LSTATUS) == 0)
+               mii_info->link = 0;
+       else
+               mii_info->link = 1;
+
+       /* If we are autonegotiating, and not done,
+        * return an error */
+       if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
+               return -EAGAIN;
+
+       return 0;
+}
+
+static int genmii_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       if (mii_info->autoneg) {
+               status = phy_read(mii_info, MII_LPA);
+
+               if (status & (LPA_10FULL | LPA_100FULL))
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+               if (status & (LPA_100FULL | LPA_100HALF))
+                       mii_info->speed = SPEED_100;
+               else
+                       mii_info->speed = SPEED_10;
+               mii_info->pause = 0;
+       }
+       /* On non-aneg, we assume what we put in BMCR is the speed,
+        * though magic-aneg shouldn't prevent this case from occurring
+        */
+
+       return 0;
+}
+
+static int marvell_init(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       phy_write(mii_info, 0x14, 0x0cd2);
+       phy_write(mii_info, MII_BMCR,
+                 phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+       msleep(4000);
+
+       return 0;
+}
+
+static int marvell_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* The Marvell PHY has an errata which requires
+        * that certain registers get written in order
+        * to restart autonegotiation */
+       phy_write(mii_info, MII_BMCR, BMCR_RESET);
+
+       phy_write(mii_info, 0x1d, 0x1f);
+       phy_write(mii_info, 0x1e, 0x200c);
+       phy_write(mii_info, 0x1d, 0x5);
+       phy_write(mii_info, 0x1e, 0);
+       phy_write(mii_info, 0x1e, 0x100);
+
+       gbit_config_aneg(mii_info);
+
+       return 0;
+}
+
+static int marvell_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       /* If the link is up, read the speed and duplex */
+       /* If we aren't autonegotiating, assume speeds
+        * are as set */
+       if (mii_info->autoneg && mii_info->link) {
+               int speed;
+               status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+
+               /* Get the duplexity */
+               if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+
+               /* Get the speed */
+               speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
+               switch (speed) {
+               case MII_M1011_PHY_SPEC_STATUS_1000:
+                       mii_info->speed = SPEED_1000;
+                       break;
+               case MII_M1011_PHY_SPEC_STATUS_100:
+                       mii_info->speed = SPEED_100;
+                       break;
+               default:
+                       mii_info->speed = SPEED_10;
+                       break;
+               }
+               mii_info->pause = 0;
+       }
+
+       return 0;
+}
+
+static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Clear the interrupts by reading the reg */
+       phy_read(mii_info, MII_M1011_IEVENT);
+
+       return 0;
+}
+
+static int marvell_config_intr(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+               phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+       else
+               phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+       return 0;
+}
+
+static int cis820x_init(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
+                 MII_CIS8201_AUXCONSTAT_INIT);
+       phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
+
+       return 0;
+}
+
+static int cis820x_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       /* If the link is up, read the speed and duplex */
+       /* If we aren't autonegotiating, assume speeds
+        * are as set */
+       if (mii_info->autoneg && mii_info->link) {
+               int speed;
+
+               status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+               if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+
+               speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
+
+               switch (speed) {
+               case MII_CIS8201_AUXCONSTAT_GBIT:
+                       mii_info->speed = SPEED_1000;
+                       break;
+               case MII_CIS8201_AUXCONSTAT_100:
+                       mii_info->speed = SPEED_100;
+                       break;
+               default:
+                       mii_info->speed = SPEED_10;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       phy_read(mii_info, MII_CIS8201_ISTAT);
+
+       return 0;
+}
+
+static int cis820x_config_intr(struct ugeth_mii_info *mii_info)
+{
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+               phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+       else
+               phy_write(mii_info, MII_CIS8201_IMASK, 0);
+
+       return 0;
+}
+
+#define DM9161_DELAY 10
+
+static int dm9161_read_status(struct ugeth_mii_info *mii_info)
+{
+       u16 status;
+       int err;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Update the link, but return if there
+        * was an error */
+       err = genmii_update_link(mii_info);
+       if (err)
+               return err;
+
+       /* If the link is up, read the speed and duplex */
+       /* If we aren't autonegotiating, assume speeds
+        * are as set */
+       if (mii_info->autoneg && mii_info->link) {
+               status = phy_read(mii_info, MII_DM9161_SCSR);
+               if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
+                       mii_info->speed = SPEED_100;
+               else
+                       mii_info->speed = SPEED_10;
+
+               if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
+                       mii_info->duplex = DUPLEX_FULL;
+               else
+                       mii_info->duplex = DUPLEX_HALF;
+       }
+
+       return 0;
+}
+
+static int dm9161_config_aneg(struct ugeth_mii_info *mii_info)
+{
+       struct dm9161_private *priv = mii_info->priv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (0 == priv->resetdone)
+               return -EAGAIN;
+
+       return 0;
+}
+
+static void dm9161_timer(unsigned long data)
+{
+       struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
+       struct dm9161_private *priv = mii_info->priv;
+       u16 status = phy_read(mii_info, MII_BMSR);
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (status & BMSR_ANEGCOMPLETE) {
+               priv->resetdone = 1;
+       } else
+               mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+}
+
+static int dm9161_init(struct ugeth_mii_info *mii_info)
+{
+       struct dm9161_private *priv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Allocate the private data structure */
+       priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
+
+       if (NULL == priv)
+               return -ENOMEM;
+
+       mii_info->priv = priv;
+
+       /* Reset is not done yet */
+       priv->resetdone = 0;
+
+       phy_write(mii_info, MII_BMCR,
+                 phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+
+       phy_write(mii_info, MII_BMCR,
+                 phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
+
+       config_genmii_advert(mii_info);
+       /* Start/Restart aneg */
+       genmii_config_aneg(mii_info);
+
+       /* Start a timer for DM9161_DELAY seconds to wait
+        * for the PHY to be ready */
+       init_timer(&priv->timer);
+       priv->timer.function = &dm9161_timer;
+       priv->timer.data = (unsigned long)mii_info;
+       mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+
+       return 0;
+}
+
+static void dm9161_close(struct ugeth_mii_info *mii_info)
+{
+       struct dm9161_private *priv = mii_info->priv;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       del_timer_sync(&priv->timer);
+       kfree(priv);
+}
+
+static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+/* FIXME: This lines are for BUG fixing in the mpc8325.
+Remove this from here when it's fixed */
+       if (bcsr_regs == NULL)
+               bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+       bcsr_regs[14] |= 0x40;
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Clear the interrupts by reading the reg */
+       phy_read(mii_info, MII_DM9161_INTR);
+
+
+       return 0;
+}
+
+static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
+{
+/* FIXME: This lines are for BUG fixing in the mpc8325.
+Remove this from here when it's fixed */
+       if (bcsr_regs == NULL) {
+               bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+               bcsr_regs[14] &= ~0x40;
+       }
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+               phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
+       else
+               phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
+
+       return 0;
+}
+
+/* Cicada 820x */
+static struct phy_info phy_info_cis820x = {
+       .phy_id = 0x000fc440,
+       .name = "Cicada Cis8204",
+       .phy_id_mask = 0x000fffc0,
+       .features = MII_GBIT_FEATURES,
+       .init = &cis820x_init,
+       .config_aneg = &gbit_config_aneg,
+       .read_status = &cis820x_read_status,
+       .ack_interrupt = &cis820x_ack_interrupt,
+       .config_intr = &cis820x_config_intr,
+};
+
+static struct phy_info phy_info_dm9161 = {
+       .phy_id = 0x0181b880,
+       .phy_id_mask = 0x0ffffff0,
+       .name = "Davicom DM9161E",
+       .init = dm9161_init,
+       .config_aneg = dm9161_config_aneg,
+       .read_status = dm9161_read_status,
+       .close = dm9161_close,
+};
+
+static struct phy_info phy_info_dm9161a = {
+       .phy_id = 0x0181b8a0,
+       .phy_id_mask = 0x0ffffff0,
+       .name = "Davicom DM9161A",
+       .features = MII_BASIC_FEATURES,
+       .init = dm9161_init,
+       .config_aneg = dm9161_config_aneg,
+       .read_status = dm9161_read_status,
+       .ack_interrupt = dm9161_ack_interrupt,
+       .config_intr = dm9161_config_intr,
+       .close = dm9161_close,
+};
+
+static struct phy_info phy_info_marvell = {
+       .phy_id = 0x01410c00,
+       .phy_id_mask = 0xffffff00,
+       .name = "Marvell 88E11x1",
+       .features = MII_GBIT_FEATURES,
+       .init = &marvell_init,
+       .config_aneg = &marvell_config_aneg,
+       .read_status = &marvell_read_status,
+       .ack_interrupt = &marvell_ack_interrupt,
+       .config_intr = &marvell_config_intr,
+};
+
+static struct phy_info phy_info_genmii = {
+       .phy_id = 0x00000000,
+       .phy_id_mask = 0x00000000,
+       .name = "Generic MII",
+       .features = MII_BASIC_FEATURES,
+       .config_aneg = genmii_config_aneg,
+       .read_status = genmii_read_status,
+};
+
+static struct phy_info *phy_info[] = {
+       &phy_info_cis820x,
+       &phy_info_marvell,
+       &phy_info_dm9161,
+       &phy_info_dm9161a,
+       &phy_info_genmii,
+       NULL
+};
+
+u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
+{
+       u16 retval;
+       unsigned long flags;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irqsave(&mii_info->mdio_lock, flags);
+       retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+       spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+       return retval;
+}
+
+void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
+{
+       unsigned long flags;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       spin_lock_irqsave(&mii_info->mdio_lock, flags);
+       mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
+       spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
+
+/* Use the PHY ID registers to determine what type of PHY is attached
+ * to device dev.  return a struct phy_info structure describing that PHY
+ */
+struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info)
+{
+       u16 phy_reg;
+       u32 phy_ID;
+       int i;
+       struct phy_info *theInfo = NULL;
+       struct net_device *dev = mii_info->dev;
+
+       ugphy_vdbg("%s: IN", __FUNCTION__);
+
+       /* Grab the bits from PHYIR1, and put them in the upper half */
+       phy_reg = phy_read(mii_info, MII_PHYSID1);
+       phy_ID = (phy_reg & 0xffff) << 16;
+
+       /* Grab the bits from PHYIR2, and put them in the lower half */
+       phy_reg = phy_read(mii_info, MII_PHYSID2);
+       phy_ID |= (phy_reg & 0xffff);
+
+       /* loop through all the known PHY types, and find one that */
+       /* matches the ID we read from the PHY. */
+       for (i = 0; phy_info[i]; i++)
+               if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){
+                       theInfo = phy_info[i];
+                       break;
+               }
+
+       /* This shouldn't happen, as we have generic PHY support */
+       if (theInfo == NULL) {
+               ugphy_info("%s: PHY id %x is not supported!", dev->name,
+                          phy_ID);
+               return NULL;
+       } else {
+               ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name,
+                          phy_ID);
+       }
+
+       return theInfo;
+}
diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h
new file mode 100644 (file)
index 0000000..2f98b8f
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * UCC GETH Driver -- PHY handling
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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 __UCC_GETH_PHY_H__
+#define __UCC_GETH_PHY_H__
+
+#define MII_end ((u32)-2)
+#define MII_read ((u32)-1)
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define UGETH_AN_TIMEOUT        2000
+
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL                  0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP    0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP    0x0100
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1        0x17
+#define MII_CIS8201_EXTCON1_INIT    0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK           0x19
+#define MII_CIS8201_IMASK_IEN       0x8000
+#define MII_CIS8201_IMASK_SPEED     0x4000
+#define MII_CIS8201_IMASK_LINK      0x2000
+#define MII_CIS8201_IMASK_DUPLEX    0x1000
+#define MII_CIS8201_IMASK_MASK      0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT           0x1a
+#define MII_CIS8201_ISTAT_STATUS    0x8000
+#define MII_CIS8201_ISTAT_SPEED     0x4000
+#define MII_CIS8201_ISTAT_LINK      0x2000
+#define MII_CIS8201_ISTAT_DUPLEX    0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT        0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
+#define MII_CIS8201_AUXCONSTAT_100     0x0008
+
+/* 88E1011 PHY Status Register */
+#define MII_M1011_PHY_SPEC_STATUS               0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000          0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100           0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK      0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX    0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED      0x0800
+#define MII_M1011_PHY_SPEC_STATUS_LINK          0x0400
+
+#define MII_M1011_IEVENT                0x13
+#define MII_M1011_IEVENT_CLEAR          0x0000
+
+#define MII_M1011_IMASK                 0x12
+#define MII_M1011_IMASK_INIT            0x6400
+#define MII_M1011_IMASK_CLEAR           0x0000
+
+#define MII_DM9161_SCR                  0x10
+#define MII_DM9161_SCR_INIT             0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MII_DM9161_SCSR                 0x11
+#define MII_DM9161_SCSR_100F            0x8000
+#define MII_DM9161_SCSR_100H            0x4000
+#define MII_DM9161_SCSR_10F             0x2000
+#define MII_DM9161_SCSR_10H             0x1000
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR                 0x15
+#define MII_DM9161_INTR_PEND            0x8000
+#define MII_DM9161_INTR_DPLX_MASK       0x0800
+#define MII_DM9161_INTR_SPD_MASK        0x0400
+#define MII_DM9161_INTR_LINK_MASK       0x0200
+#define MII_DM9161_INTR_MASK            0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE     0x0010
+#define MII_DM9161_INTR_SPD_CHANGE      0x0008
+#define MII_DM9161_INTR_LINK_CHANGE     0x0004
+#define MII_DM9161_INTR_INIT            0x0000
+#define MII_DM9161_INTR_STOP    \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR              0x12
+#define MII_DM9161_10BTCSR_INIT         0x7800
+
+#define MII_BASIC_FEATURES    (SUPPORTED_10baseT_Half | \
+                 SUPPORTED_10baseT_Full | \
+                 SUPPORTED_100baseT_Half | \
+                 SUPPORTED_100baseT_Full | \
+                 SUPPORTED_Autoneg | \
+                 SUPPORTED_TP | \
+                 SUPPORTED_MII)
+
+#define MII_GBIT_FEATURES    (MII_BASIC_FEATURES | \
+                 SUPPORTED_1000baseT_Half | \
+                 SUPPORTED_1000baseT_Full)
+
+#define MII_READ_COMMAND                0x00000001
+
+#define MII_INTERRUPT_DISABLED          0x0
+#define MII_INTERRUPT_ENABLED           0x1
+/* Taken from mii_if_info and sungem_phy.h */
+struct ugeth_mii_info {
+       /* Information about the PHY type */
+       /* And management functions */
+       struct phy_info *phyinfo;
+
+       ucc_mii_mng_t *mii_regs;
+
+       /* forced speed & duplex (no autoneg)
+        * partner speed & duplex & pause (autoneg)
+        */
+       int speed;
+       int duplex;
+       int pause;
+
+       /* The most recently read link state */
+       int link;
+
+       /* Enabled Interrupts */
+       u32 interrupts;
+
+       u32 advertising;
+       int autoneg;
+       int mii_id;
+
+       /* private data pointer */
+       /* For use by PHYs to maintain extra state */
+       void *priv;
+
+       /* Provided by host chip */
+       struct net_device *dev;
+
+       /* A lock to ensure that only one thing can read/write
+        * the MDIO bus at a time */
+       spinlock_t mdio_lock;
+
+       /* Provided by ethernet driver */
+       int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
+       void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
+                           int val);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be ANDed with phy_id_mask to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ * There are 6 commands which take a ugeth_mii_info structure.
+ * Each PHY must declare config_aneg, and read_status.
+ */
+struct phy_info {
+       u32 phy_id;
+       char *name;
+       unsigned int phy_id_mask;
+       u32 features;
+
+       /* Called to initialize the PHY */
+       int (*init) (struct ugeth_mii_info * mii_info);
+
+       /* Called to suspend the PHY for power */
+       int (*suspend) (struct ugeth_mii_info * mii_info);
+
+       /* Reconfigures autonegotiation (or disables it) */
+       int (*config_aneg) (struct ugeth_mii_info * mii_info);
+
+       /* Determines the negotiated speed and duplex */
+       int (*read_status) (struct ugeth_mii_info * mii_info);
+
+       /* Clears any pending interrupts */
+       int (*ack_interrupt) (struct ugeth_mii_info * mii_info);
+
+       /* Enables or disables interrupts */
+       int (*config_intr) (struct ugeth_mii_info * mii_info);
+
+       /* Clears up any memory if needed */
+       void (*close) (struct ugeth_mii_info * mii_info);
+};
+
+struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info);
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
+void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info);
+void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
+                                u32 interrupts);
+
+struct dm9161_private {
+       struct timer_list timer;
+       int resetdone;
+};
+
+#endif                         /* __UCC_GETH_PHY_H__ */
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h
new file mode 100644 (file)
index 0000000..be1abea
--- /dev/null
@@ -0,0 +1,104 @@
+/* orinoco_pci.h
+ * 
+ * Common code for all Orinoco drivers for PCI devices, including
+ * both native PCI and PCMCIA-to-PCI bridges.
+ *
+ * Copyright (C) 2005, Pavel Roskin.
+ * See orinoco.c for license.
+ */
+
+#ifndef _ORINOCO_PCI_H
+#define _ORINOCO_PCI_H
+
+#include <linux/netdevice.h>
+
+/* Driver specific data */
+struct orinoco_pci_card {
+       void __iomem *bridge_io;
+       void __iomem *attr_io;
+};
+
+#ifdef CONFIG_PM
+static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct orinoco_private *priv = netdev_priv(dev);
+       unsigned long flags;
+       int err;
+
+       err = orinoco_lock(priv, &flags);
+       if (err) {
+               printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
+                      dev->name);
+               return err;
+       }
+
+       err = __orinoco_down(dev);
+       if (err)
+               printk(KERN_WARNING "%s: error %d bringing interface down "
+                      "for suspend\n", dev->name, err);
+       
+       netif_device_detach(dev);
+
+       priv->hw_unavailable++;
+       
+       orinoco_unlock(priv, &flags);
+
+       free_irq(pdev->irq, dev);
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return 0;
+}
+
+static int orinoco_pci_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct orinoco_private *priv = netdev_priv(dev);
+       unsigned long flags;
+       int err;
+
+       pci_set_power_state(pdev, 0);
+       pci_enable_device(pdev);
+       pci_restore_state(pdev);
+
+       err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
+                         dev->name, dev);
+       if (err) {
+               printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
+                      dev->name);
+               pci_disable_device(pdev);
+               return -EBUSY;
+       }
+
+       err = orinoco_reinit_firmware(dev);
+       if (err) {
+               printk(KERN_ERR "%s: error %d re-initializing firmware "
+                      "on resume\n", dev->name, err);
+               return err;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       netif_device_attach(dev);
+
+       priv->hw_unavailable--;
+
+       if (priv->open && (! priv->hw_unavailable)) {
+               err = __orinoco_up(dev);
+               if (err)
+                       printk(KERN_ERR "%s: Error %d restarting card on resume\n",
+                              dev->name, err);
+       }
+       
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+#else
+#define orinoco_pci_suspend NULL
+#define orinoco_pci_resume NULL
+#endif
+
+#endif /* _ORINOCO_PCI_H */
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
new file mode 100644 (file)
index 0000000..c52e9bc
--- /dev/null
@@ -0,0 +1,1931 @@
+/*
+ *     Driver for ZyDAS zd1201 based wireless USB devices.
+ *
+ *     Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     Parts of this driver have been derived from a wlan-ng version
+ *     modified by ZyDAS. They also made documentation available, thanks!
+ *     Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/string.h>
+#include <linux/if_arp.h>
+#include <linux/firmware.h>
+#include <net/ieee80211.h>
+#include "zd1201.h"
+
+static struct usb_device_id zd1201_table[] = {
+       {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
+       {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
+       {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb  adapter */
+       {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb  adapter */
+       {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */
+       {}
+};
+
+static int ap; /* Are we an AP or a normal station? */
+
+#define ZD1201_VERSION "0.15"
+
+MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
+MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters");
+MODULE_VERSION(ZD1201_VERSION);
+MODULE_LICENSE("GPL");
+module_param(ap, int, 0);
+MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded");
+MODULE_DEVICE_TABLE(usb, zd1201_table);
+
+
+static int zd1201_fw_upload(struct usb_device *dev, int apfw)
+{
+       const struct firmware *fw_entry;
+       char *data;
+       unsigned long len;
+       int err;
+       unsigned char ret;
+       char *buf;
+       char *fwfile;
+
+       if (apfw)
+               fwfile = "zd1201-ap.fw";
+       else
+               fwfile = "zd1201.fw";
+
+       err = request_firmware(&fw_entry, fwfile, &dev->dev);
+       if (err) {
+               dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
+               dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
+               dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
+               return err;
+       }
+
+       data = fw_entry->data;
+        len = fw_entry->size;
+
+       buf = kmalloc(1024, GFP_ATOMIC);
+       if (!buf)
+               goto exit;
+       
+       while (len > 0) {
+               int translen = (len > 1024) ? 1024 : len;
+               memcpy(buf, data, translen);
+
+               err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+                   USB_DIR_OUT | 0x40, 0, 0, buf, translen,
+                   ZD1201_FW_TIMEOUT);
+               if (err < 0)
+                       goto exit;
+
+               len -= translen;
+               data += translen;
+       }
+                                        
+       err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2,
+           USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
+       if (err < 0)
+               goto exit;
+
+       err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
+           USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+       if (err < 0)
+               goto exit;
+
+       if (ret & 0x80) {
+               err = -EIO;
+               goto exit;
+       }
+
+       err = 0;
+exit:
+       kfree(buf);
+       release_firmware(fw_entry);
+       return err;
+}
+
+static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
+{
+       struct zd1201 *zd = urb->context;
+
+       switch(urb->status) {
+               case -EILSEQ:
+               case -ENODEV:
+               case -ETIMEDOUT:
+               case -ENOENT:
+               case -EPIPE:
+               case -EOVERFLOW:
+               case -ESHUTDOWN:
+                       dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", 
+                           zd->dev->name, urb->status);
+       }
+
+       kfree(urb->transfer_buffer);
+       usb_free_urb(urb);
+       return;
+}
+
+/* cmdreq message: 
+       u32 type
+       u16 cmd
+       u16 parm0
+       u16 parm1
+       u16 parm2
+       u8  pad[4]
+
+       total: 4 + 2 + 2 + 2 + 2 + 4 = 16
+*/
+static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
+                       int parm1, int parm2)
+{
+       unsigned char *command;
+       int ret;
+       struct urb *urb;
+
+       command = kmalloc(16, GFP_ATOMIC);
+       if (!command)
+               return -ENOMEM;
+
+       *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ);
+       *((__le16*)&command[4]) = cpu_to_le16(cmd);
+       *((__le16*)&command[6]) = cpu_to_le16(parm0);
+       *((__le16*)&command[8]) = cpu_to_le16(parm1);
+       *((__le16*)&command[10])= cpu_to_le16(parm2);
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               kfree(command);
+               return -ENOMEM;
+       }
+       usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+                         command, 16, zd1201_usbfree, zd);
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret) {
+               kfree(command);
+               usb_free_urb(urb);
+       }
+
+       return ret;
+}
+
+/* Callback after sending out a packet */
+static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
+{
+       struct zd1201 *zd = urb->context;
+       netif_wake_queue(zd->dev);
+       return;
+}
+
+/* Incoming data */
+static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
+{
+       struct zd1201 *zd = urb->context;
+       int free = 0;
+       unsigned char *data = urb->transfer_buffer;
+       struct sk_buff *skb;
+       unsigned char type;
+
+       if (!zd) {
+               free = 1;
+               goto exit;
+       }
+
+       switch(urb->status) {
+               case -EILSEQ:
+               case -ENODEV:
+               case -ETIMEDOUT:
+               case -ENOENT:
+               case -EPIPE:
+               case -EOVERFLOW:
+               case -ESHUTDOWN:
+                       dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n",
+                           zd->dev->name, urb->status);
+                       free = 1;
+                       goto exit;
+       }
+       
+       if (urb->status != 0 || urb->actual_length == 0)
+               goto resubmit;
+
+       type = data[0];
+       if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) {
+               memcpy(zd->rxdata, data, urb->actual_length);
+               zd->rxlen = urb->actual_length;
+               zd->rxdatas = 1;
+               wake_up(&zd->rxdataq);
+       }
+       /* Info frame */
+       if (type == ZD1201_PACKET_INQUIRE) {
+               int i = 0;
+               unsigned short infotype, framelen, copylen;
+               framelen = le16_to_cpu(*(__le16*)&data[4]);
+               infotype = le16_to_cpu(*(__le16*)&data[6]);
+
+               if (infotype == ZD1201_INF_LINKSTATUS) {
+                       short linkstatus;
+
+                       linkstatus = le16_to_cpu(*(__le16*)&data[8]);
+                       switch(linkstatus) {
+                               case 1:
+                                       netif_carrier_on(zd->dev);
+                                       break;
+                               case 2:
+                                       netif_carrier_off(zd->dev);
+                                       break;
+                               case 3:
+                                       netif_carrier_off(zd->dev);
+                                       break;
+                               case 4:
+                                       netif_carrier_on(zd->dev);
+                                       break;
+                               default:
+                                       netif_carrier_off(zd->dev);
+                       }
+                       goto resubmit;
+               }
+               if (infotype == ZD1201_INF_ASSOCSTATUS) {
+                       short status = le16_to_cpu(*(__le16*)(data+8));
+                       int event;
+                       union iwreq_data wrqu;
+
+                       switch (status) {
+                               case ZD1201_ASSOCSTATUS_STAASSOC:
+                               case ZD1201_ASSOCSTATUS_REASSOC:
+                                       event = IWEVREGISTERED;
+                                       break;
+                               case ZD1201_ASSOCSTATUS_DISASSOC:
+                               case ZD1201_ASSOCSTATUS_ASSOCFAIL:
+                               case ZD1201_ASSOCSTATUS_AUTHFAIL:
+                               default:
+                                       event = IWEVEXPIRED;
+                       }
+                       memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN);
+                       wrqu.addr.sa_family = ARPHRD_ETHER;
+
+                       /* Send event to user space */
+                       wireless_send_event(zd->dev, event, &wrqu, NULL);
+
+                       goto resubmit;
+               }
+               if (infotype == ZD1201_INF_AUTHREQ) {
+                       union iwreq_data wrqu;
+
+                       memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN);
+                       wrqu.addr.sa_family = ARPHRD_ETHER;
+                       /* There isn't a event that trully fits this request.
+                          We assume that userspace will be smart enough to
+                          see a new station being expired and sends back a
+                          authstation ioctl to authorize it. */
+                       wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL);
+                       goto resubmit;
+               }
+               /* Other infotypes are handled outside this handler */
+               zd->rxlen = 0;
+               while (i < urb->actual_length) {
+                       copylen = le16_to_cpu(*(__le16*)&data[i+2]);
+                       /* Sanity check, sometimes we get junk */
+                       if (copylen+zd->rxlen > sizeof(zd->rxdata))
+                               break;
+                       memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen);
+                       zd->rxlen += copylen;
+                       i += 64;
+               }
+               if (i >= urb->actual_length) {
+                       zd->rxdatas = 1;
+                       wake_up(&zd->rxdataq);
+               }
+               goto  resubmit;
+       }
+       /* Actual data */
+       if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) {
+               int datalen = urb->actual_length-1;
+               unsigned short len, fc, seq;
+               struct hlist_node *node;
+
+               len = ntohs(*(__be16 *)&data[datalen-2]);
+               if (len>datalen)
+                       len=datalen;
+               fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
+               seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
+
+               if (zd->monitor) {
+                       if (datalen < 24)
+                               goto resubmit;
+                       if (!(skb = dev_alloc_skb(datalen+24)))
+                               goto resubmit;
+                       
+                       memcpy(skb_put(skb, 2), &data[datalen-16], 2);
+                       memcpy(skb_put(skb, 2), &data[datalen-2], 2);
+                       memcpy(skb_put(skb, 6), &data[datalen-14], 6);
+                       memcpy(skb_put(skb, 6), &data[datalen-22], 6);
+                       memcpy(skb_put(skb, 6), &data[datalen-8], 6);
+                       memcpy(skb_put(skb, 2), &data[datalen-24], 2);
+                       memcpy(skb_put(skb, len), data, len);
+                       skb->dev = zd->dev;
+                       skb->dev->last_rx = jiffies;
+                       skb->protocol = eth_type_trans(skb, zd->dev);
+                       zd->stats.rx_packets++;
+                       zd->stats.rx_bytes += skb->len;
+                       netif_rx(skb);
+                       goto resubmit;
+               }
+                       
+               if ((seq & IEEE80211_SCTL_FRAG) ||
+                   (fc & IEEE80211_FCTL_MOREFRAGS)) {
+                       struct zd1201_frag *frag = NULL;
+                       char *ptr;
+
+                       if (datalen<14)
+                               goto resubmit;
+                       if ((seq & IEEE80211_SCTL_FRAG) == 0) {
+                               frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
+                               if (!frag)
+                                       goto resubmit;
+                               skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
+                               if (!skb) {
+                                       kfree(frag);
+                                       goto resubmit;
+                               }
+                               frag->skb = skb;
+                               frag->seq = seq & IEEE80211_SCTL_SEQ;
+                               skb_reserve(skb, 2);
+                               memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+                               memcpy(skb_put(skb, 2), &data[6], 2);
+                               memcpy(skb_put(skb, len), data+8, len);
+                               hlist_add_head(&frag->fnode, &zd->fraglist);
+                               goto resubmit;
+                       }
+                       hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
+                               if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
+                                       break;
+                       if (!frag)
+                               goto resubmit;
+                       skb = frag->skb;
+                       ptr = skb_put(skb, len);
+                       if (ptr)
+                               memcpy(ptr, data+8, len);
+                       if (fc & IEEE80211_FCTL_MOREFRAGS)
+                               goto resubmit;
+                       hlist_del_init(&frag->fnode);
+                       kfree(frag);
+               } else {
+                       if (datalen<14)
+                               goto resubmit;
+                       skb = dev_alloc_skb(len + 14 + 2);
+                       if (!skb)
+                               goto resubmit;
+                       skb_reserve(skb, 2);
+                       memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+                       memcpy(skb_put(skb, 2), &data[6], 2);
+                       memcpy(skb_put(skb, len), data+8, len);
+               }
+               skb->dev = zd->dev;
+               skb->dev->last_rx = jiffies;
+               skb->protocol = eth_type_trans(skb, zd->dev);
+               zd->stats.rx_packets++;
+               zd->stats.rx_bytes += skb->len;
+               netif_rx(skb);
+       }
+resubmit:
+       memset(data, 0, ZD1201_RXSIZE);
+
+       urb->status = 0;
+       urb->dev = zd->usb;
+       if(usb_submit_urb(urb, GFP_ATOMIC))
+               free = 1;
+
+exit:
+       if (free) {
+               zd->rxlen = 0;
+               zd->rxdatas = 1;
+               wake_up(&zd->rxdataq);
+               kfree(urb->transfer_buffer);
+       }
+       return;
+}
+
+static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
+       unsigned int riddatalen)
+{
+       int err;
+       int i = 0;
+       int code;
+       int rid_fid;
+       int length;
+       unsigned char *pdata;
+
+       zd->rxdatas = 0;
+       err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
+       if (err)
+               return err;
+
+       wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+       if (!zd->rxlen)
+               return -EIO;
+
+       code = le16_to_cpu(*(__le16*)(&zd->rxdata[4]));
+       rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6]));
+       length = le16_to_cpu(*(__le16*)(&zd->rxdata[8]));
+       if (length > zd->rxlen)
+               length = zd->rxlen-6;
+
+       /* If access bit is not on, then error */
+       if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid )
+               return -EINVAL;
+
+       /* Not enough buffer for allocating data */
+       if (riddatalen != (length - 4)) {
+               dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n",
+                   riddatalen, zd->rxlen, length, rid, rid_fid);
+               return -ENODATA;
+       }
+
+       zd->rxdatas = 0;
+       /* Issue SetRxRid commnd */                     
+       err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length);
+       if (err)
+               return err;
+
+       /* Receive RID record from resource packets */
+       wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+       if (!zd->rxlen)
+               return -EIO;
+
+       if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) {
+               dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n",
+                   zd->rxdata[zd->rxlen-1]);
+               return -EINVAL;
+       }
+
+       /* Set the data pointer and received data length */
+       pdata = zd->rxdata;
+       length = zd->rxlen;
+
+       do {
+               int actual_length;
+
+               actual_length = (length > 64) ? 64 : length;
+
+               if (pdata[0] != 0x3) {
+                       dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
+                           pdata[0]);
+                       return -EINVAL;
+               }
+
+               if (actual_length != 64) {
+                       /* Trim the last packet type byte */
+                       actual_length--;
+               }
+
+               /* Skip the 4 bytes header (RID length and RID) */
+               if (i == 0) {
+                       pdata += 8;
+                       actual_length -= 8;
+               } else {
+                       pdata += 4;
+                       actual_length -= 4;
+               }
+               
+               memcpy(riddata, pdata, actual_length);
+               riddata += actual_length;
+               pdata += actual_length;
+               length -= 64;
+               i++;
+       } while (length > 0);
+
+       return 0;
+}
+
+/*
+ *     resreq:
+ *             byte    type
+ *             byte    sequence
+ *             u16     reserved
+ *             byte    data[12]
+ *     total: 16
+ */
+static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait)
+{
+       int err;
+       unsigned char *request;
+       int reqlen;
+       char seq=0;
+       struct urb *urb;
+       gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+
+       len += 4;                       /* first 4 are for header */
+
+       zd->rxdatas = 0;
+       zd->rxlen = 0;
+       for (seq=0; len > 0; seq++) {
+               request = kmalloc(16, gfp_mask);
+               if (!request)
+                       return -ENOMEM;
+               urb = usb_alloc_urb(0, gfp_mask);
+               if (!urb) {
+                       kfree(request);
+                       return -ENOMEM;
+               }
+               memset(request, 0, 16);
+               reqlen = len>12 ? 12 : len;
+               request[0] = ZD1201_USB_RESREQ;
+               request[1] = seq;
+               request[2] = 0;
+               request[3] = 0;
+               if (request[1] == 0) {
+                       /* add header */
+                       *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2);
+                       *(__le16*)&request[6] = cpu_to_le16(rid);
+                       memcpy(request+8, buf, reqlen-4);
+                       buf += reqlen-4;
+               } else {
+                       memcpy(request+4, buf, reqlen);
+                       buf += reqlen;
+               }
+
+               len -= reqlen;
+
+               usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb,
+                   zd->endp_out2), request, 16, zd1201_usbfree, zd);
+               err = usb_submit_urb(urb, gfp_mask);
+               if (err)
+                       goto err;
+       }
+
+       request = kmalloc(16, gfp_mask);
+       if (!request)
+               return -ENOMEM;
+       urb = usb_alloc_urb(0, gfp_mask);
+       if (!urb) {
+               kfree(request);
+               return -ENOMEM;
+       }
+       *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ);
+       *((__le16*)&request[4]) = 
+           cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT);
+       *((__le16*)&request[6]) = cpu_to_le16(rid);
+       *((__le16*)&request[8]) = cpu_to_le16(0);
+       *((__le16*)&request[10]) = cpu_to_le16(0);
+       usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+            request, 16, zd1201_usbfree, zd);
+       err = usb_submit_urb(urb, gfp_mask);
+       if (err)
+               goto err;
+       
+       if (wait) {
+               wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+               if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) {
+                       dev_dbg(&zd->usb->dev, "wrong or no RID received\n");
+               }
+       }
+
+       return 0;
+err:
+       kfree(request);
+       usb_free_urb(urb);
+       return err;
+}
+
+static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val)
+{
+       int err;
+       __le16 zdval;
+
+       err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16));
+       if (err)
+               return err;
+       *val = le16_to_cpu(zdval);
+       return 0;
+}
+
+static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val)
+{
+       __le16 zdval = cpu_to_le16(val);
+       return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));
+}
+
+static int zd1201_drvr_start(struct zd1201 *zd)
+{
+       int err, i;
+       short max;
+       __le16 zdmax;
+       unsigned char *buffer;
+
+       buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       usb_fill_bulk_urb(zd->rx_urb, zd->usb, 
+           usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE,
+           zd1201_usbrx, zd);
+
+       err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
+       if (err)
+               goto err_buffer;
+
+       err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+       if (err)
+               goto err_urb;
+
+       err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax,
+           sizeof(__le16));
+       if (err)
+               goto err_urb;
+
+       max = le16_to_cpu(zdmax);
+       for (i=0; i<max; i++) {
+               err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0);
+               if (err)
+                       goto err_urb;
+       }
+
+       return 0;
+
+err_urb:
+       usb_kill_urb(zd->rx_urb);
+       return err;
+err_buffer:
+       kfree(buffer);
+       return err;
+}
+
+/*     Magic alert: The firmware doesn't seem to like the MAC state being
+ *     toggled in promisc (aka monitor) mode.
+ *     (It works a number of times, but will halt eventually)
+ *     So we turn it of before disabling and on after enabling if needed.
+ */
+static int zd1201_enable(struct zd1201 *zd)
+{
+       int err;
+
+       if (zd->mac_enabled)
+               return 0;
+
+       err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
+       if (!err)
+               zd->mac_enabled = 1;
+
+       if (zd->monitor)
+               err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1);
+
+       return err;
+}
+
+static int zd1201_disable(struct zd1201 *zd)
+{
+       int err;
+
+       if (!zd->mac_enabled)
+               return 0;
+       if (zd->monitor) {
+               err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+               if (err)
+                       return err;
+       }
+
+       err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0);
+       if (!err)
+               zd->mac_enabled = 0;
+       return err;
+}
+
+static int zd1201_mac_reset(struct zd1201 *zd)
+{
+       if (!zd->mac_enabled)
+               return 0;
+       zd1201_disable(zd);
+       return zd1201_enable(zd);
+}
+
+static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen)
+{
+       int err, val;
+       char buf[IW_ESSID_MAX_SIZE+2];
+
+       err = zd1201_disable(zd);
+       if (err)
+               return err;
+
+       val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+       val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val);
+       if (err)
+               return err;
+
+       *(__le16 *)buf = cpu_to_le16(essidlen);
+       memcpy(buf+2, essid, essidlen);
+       if (!zd->ap) {  /* Normal station */
+               err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+                   IW_ESSID_MAX_SIZE+2, 1);
+               if (err)
+                       return err;
+       } else {        /* AP */
+               err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf,
+                   IW_ESSID_MAX_SIZE+2, 1);
+               if (err)
+                       return err;
+       }
+
+       err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+           zd->dev->dev_addr, zd->dev->addr_len, 1);
+       if (err)
+               return err;
+
+       err = zd1201_enable(zd);
+       if (err)
+               return err;
+
+       msleep(100);
+       return 0;
+}
+
+static int zd1201_net_open(struct net_device *dev)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       /* Start MAC with wildcard if no essid set */
+       if (!zd->mac_enabled)
+               zd1201_join(zd, zd->essid, zd->essidlen);
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+static int zd1201_net_stop(struct net_device *dev)
+{
+       netif_stop_queue(dev);
+       return 0;
+}
+
+/*
+       RFC 1042 encapsulates Ethernet frames in 802.11 frames
+       by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0
+       (0x00, 0x00, 0x00). Zd requires an additional padding, copy
+       of ethernet addresses, length of the standard RFC 1042 packet
+       and a command byte (which is nul for tx).
+       
+       tx frame (from Wlan NG):
+       RFC 1042:
+               llc             0xAA 0xAA 0x03 (802.2 LLC)
+               snap            0x00 0x00 0x00 (Ethernet encapsulated)
+               type            2 bytes, Ethernet type field
+               payload         (minus eth header)
+       Zydas specific:
+               padding         1B if (skb->len+8+1)%64==0
+               Eth MAC addr    12 bytes, Ethernet MAC addresses
+               length          2 bytes, RFC 1042 packet length 
+                               (llc+snap+type+payload)
+               zd              1 null byte, zd1201 packet type
+ */
+static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       unsigned char *txbuf = zd->txdata;
+       int txbuflen, pad = 0, err;
+       struct urb *urb = zd->tx_urb;
+
+       if (!zd->mac_enabled || zd->monitor) {
+               zd->stats.tx_dropped++;
+               kfree_skb(skb);
+               return 0;
+       }
+       netif_stop_queue(dev);
+
+       txbuflen = skb->len + 8 + 1;
+       if (txbuflen%64 == 0) {
+               pad = 1;
+               txbuflen++;
+       }
+       txbuf[0] = 0xAA;
+       txbuf[1] = 0xAA;
+       txbuf[2] = 0x03;
+       txbuf[3] = 0x00;        /* rfc1042 */
+       txbuf[4] = 0x00;
+       txbuf[5] = 0x00;
+
+       memcpy(txbuf+6, skb->data+12, skb->len-12);
+       if (pad)
+               txbuf[skb->len-12+6]=0;
+       memcpy(txbuf+skb->len-12+6+pad, skb->data, 12);
+       *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6);
+       txbuf[txbuflen-1] = 0;
+
+       usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out),
+           txbuf, txbuflen, zd1201_usbtx, zd);
+
+       err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC);
+       if (err) {
+               zd->stats.tx_errors++;
+               netif_start_queue(dev);
+               return err;
+       }
+       zd->stats.tx_packets++;
+       zd->stats.tx_bytes += skb->len;
+       dev->trans_start = jiffies;
+       kfree_skb(skb);
+
+       return 0;
+}
+
+static void zd1201_tx_timeout(struct net_device *dev)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       if (!zd)
+               return;
+       dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
+           dev->name);
+       usb_unlink_urb(zd->tx_urb);
+       zd->stats.tx_errors++;
+       /* Restart the timeout to quiet the watchdog: */
+       dev->trans_start = jiffies;
+}
+
+static int zd1201_set_mac_address(struct net_device *dev, void *p)
+{
+       struct sockaddr *addr = p;
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       int err;
+
+       if (!zd)
+               return -ENODEV;
+
+       err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+           addr->sa_data, dev->addr_len, 1);
+       if (err)
+               return err;
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+       return zd1201_mac_reset(zd);
+}
+
+static struct net_device_stats *zd1201_get_stats(struct net_device *dev)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       return &zd->stats;
+}
+
+static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       return &zd->iwstats;
+}
+
+static void zd1201_set_multicast(struct net_device *dev)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       struct dev_mc_list *mc = dev->mc_list;
+       unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI];
+       int i;
+
+       if (dev->mc_count > ZD1201_MAXMULTI)
+               return;
+
+       for (i=0; i<dev->mc_count; i++) {
+               memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN);
+               mc = mc->next;
+       }
+       zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf,
+           dev->mc_count*ETH_ALEN, 0);
+       
+}
+
+static int zd1201_config_commit(struct net_device *dev, 
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_name(struct net_device *dev,
+    struct iw_request_info *info, char *name, char *extra)
+{
+       strcpy(name, "IEEE 802.11b");
+       return 0;
+}
+
+static int zd1201_set_freq(struct net_device *dev,
+    struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short channel = 0;
+       int err;
+
+       if (freq->e == 0)
+               channel = freq->m;
+       else {
+               if (freq->m >= 2482)
+                       channel = 14;
+               if (freq->m >= 2407)
+                       channel = (freq->m-2407)/5;
+       }
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
+       if (err)
+               return err;
+
+       zd1201_mac_reset(zd);
+
+       return 0;
+}
+
+static int zd1201_get_freq(struct net_device *dev,
+    struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short channel;
+       int err;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel);
+       if (err)
+               return err;
+       freq->e = 0;
+       freq->m = channel;
+
+       return 0;
+}
+
+static int zd1201_set_mode(struct net_device *dev,
+    struct iw_request_info *info, __u32 *mode, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short porttype, monitor = 0;
+       unsigned char buffer[IW_ESSID_MAX_SIZE+2];
+       int err;
+
+       if (zd->ap) {
+               if (*mode != IW_MODE_MASTER)
+                       return -EINVAL;
+               return 0;
+       }
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+       if (err)
+               return err;
+       zd->dev->type = ARPHRD_ETHER;
+       switch(*mode) {
+               case IW_MODE_MONITOR:
+                       monitor = 1;
+                       zd->dev->type = ARPHRD_IEEE80211;
+                       /* Make sure we are no longer associated with by
+                          setting an 'impossible' essid.
+                          (otherwise we mess up firmware)
+                        */
+                       zd1201_join(zd, "\0-*#\0", 5);
+                       /* Put port in pIBSS */
+               case 8: /* No pseudo-IBSS in wireless extensions (yet) */
+                       porttype = ZD1201_PORTTYPE_PSEUDOIBSS;
+                       break;
+               case IW_MODE_ADHOC:
+                       porttype = ZD1201_PORTTYPE_IBSS;
+                       break;
+               case IW_MODE_INFRA:
+                       porttype = ZD1201_PORTTYPE_BSS;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+       if (err)
+               return err;
+       if (zd->monitor && !monitor) {
+                       zd1201_disable(zd);
+                       *(__le16 *)buffer = cpu_to_le16(zd->essidlen);
+                       memcpy(buffer+2, zd->essid, zd->essidlen);
+                       err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID,
+                           buffer, IW_ESSID_MAX_SIZE+2, 1);
+                       if (err)
+                               return err;
+       }
+       zd->monitor = monitor;
+       /* If monitor mode is set we don't actually turn it on here since it
+        * is done during mac reset anyway (see zd1201_mac_enable).
+        */
+       zd1201_mac_reset(zd);
+
+       return 0;
+}
+
+static int zd1201_get_mode(struct net_device *dev,
+    struct iw_request_info *info, __u32 *mode, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short porttype;
+       int err;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype);
+       if (err)
+               return err;
+       switch(porttype) {
+               case ZD1201_PORTTYPE_IBSS:
+                       *mode = IW_MODE_ADHOC;
+                       break;
+               case ZD1201_PORTTYPE_BSS:
+                       *mode = IW_MODE_INFRA;
+                       break;
+               case ZD1201_PORTTYPE_WDS:
+                       *mode = IW_MODE_REPEAT;
+                       break;
+               case ZD1201_PORTTYPE_PSEUDOIBSS:
+                       *mode = 8;/* No Pseudo-IBSS... */
+                       break;
+               case ZD1201_PORTTYPE_AP:
+                       *mode = IW_MODE_MASTER;
+                       break;
+               default:
+                       dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n",
+                           porttype);
+                       *mode = IW_MODE_AUTO;
+       }
+       if (zd->monitor)
+               *mode = IW_MODE_MONITOR;
+
+       return 0;
+}
+
+static int zd1201_get_range(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *wrq, char *extra)
+{
+       struct iw_range *range = (struct iw_range *)extra;
+
+       wrq->length = sizeof(struct iw_range);
+       memset(range, 0, sizeof(struct iw_range));
+       range->we_version_compiled = WIRELESS_EXT;
+       range->we_version_source = WIRELESS_EXT;
+
+       range->max_qual.qual = 128;
+       range->max_qual.level = 128;
+       range->max_qual.noise = 128;
+       range->max_qual.updated = 7;
+
+       range->encoding_size[0] = 5;
+       range->encoding_size[1] = 13;
+       range->num_encoding_sizes = 2;
+       range->max_encoding_tokens = ZD1201_NUMKEYS;
+
+       range->num_bitrates = 4;
+       range->bitrate[0] = 1000000;
+       range->bitrate[1] = 2000000;
+       range->bitrate[2] = 5500000;
+       range->bitrate[3] = 11000000;
+
+       range->min_rts = 0;
+       range->min_frag = ZD1201_FRAGMIN;
+       range->max_rts = ZD1201_RTSMAX;
+       range->min_frag = ZD1201_FRAGMAX;
+
+       return 0;
+}
+
+/*     Little bit of magic here: we only get the quality if we poll
+ *     for it, and we never get an actual request to trigger such
+ *     a poll. Therefore we 'assume' that the user will soon ask for
+ *     the stats after asking the bssid.
+ */
+static int zd1201_get_wap(struct net_device *dev,
+    struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       unsigned char buffer[6];
+
+       if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
+               /* Unfortunately the quality and noise reported is useless.
+                  they seem to be accumulators that increase until you
+                  read them, unless we poll on a fixed interval we can't
+                  use them
+                */
+               /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/
+               zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]);
+               /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/
+               zd->iwstats.qual.updated = 2;
+       }
+
+       return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6);
+}
+
+static int zd1201_set_scan(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+       /* We do everything in get_scan */
+       return 0;
+}
+
+static int zd1201_get_scan(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       int err, i, j, enabled_save;
+       struct iw_event iwe;
+       char *cev = extra;
+       char *end_buf = extra + IW_SCAN_MAX_DATA;
+
+       /* No scanning in AP mode */
+       if (zd->ap)
+               return -EOPNOTSUPP;
+
+       /* Scan doesn't seem to work if disabled */
+       enabled_save = zd->mac_enabled;
+       zd1201_enable(zd);
+
+       zd->rxdatas = 0;
+       err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, 
+            ZD1201_INQ_SCANRESULTS, 0, 0);
+       if (err)
+               return err;
+
+       wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+       if (!zd->rxlen)
+               return -EIO;
+
+       if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS)
+               return -EIO;
+
+       for(i=8; i<zd->rxlen; i+=62) {
+               iwe.cmd = SIOCGIWAP;
+               iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+               memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
+               cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+               iwe.cmd = SIOCGIWESSID;
+               iwe.u.data.length = zd->rxdata[i+16];
+               iwe.u.data.flags = 1;
+               cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
+
+               iwe.cmd = SIOCGIWMODE;
+               if (zd->rxdata[i+14]&0x01)
+                       iwe.u.mode = IW_MODE_MASTER;
+               else
+                       iwe.u.mode = IW_MODE_ADHOC;
+               cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+               
+               iwe.cmd = SIOCGIWFREQ;
+               iwe.u.freq.m = zd->rxdata[i+0];
+               iwe.u.freq.e = 0;
+               cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+               
+               iwe.cmd = SIOCGIWRATE;
+               iwe.u.bitrate.fixed = 0;
+               iwe.u.bitrate.disabled = 0;
+               for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
+                       iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
+                       cev=iwe_stream_add_event(cev, end_buf, &iwe,
+                           IW_EV_PARAM_LEN);
+               }
+               
+               iwe.cmd = SIOCGIWENCODE;
+               iwe.u.data.length = 0;
+               if (zd->rxdata[i+14]&0x10)
+                       iwe.u.data.flags = IW_ENCODE_ENABLED;
+               else
+                       iwe.u.data.flags = IW_ENCODE_DISABLED;
+               cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+               
+               iwe.cmd = IWEVQUAL;
+               iwe.u.qual.qual = zd->rxdata[i+4];
+               iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
+               iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
+               iwe.u.qual.updated = 7;
+               cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+       }
+
+       if (!enabled_save)
+               zd1201_disable(zd);
+
+       srq->length = cev - extra;
+       srq->flags = 0;
+
+       return 0;
+}
+
+static int zd1201_set_essid(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       if (data->length > IW_ESSID_MAX_SIZE)
+               return -EINVAL;
+       if (data->length < 1)
+               data->length = 1;
+       zd->essidlen = data->length-1;
+       memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
+       memcpy(zd->essid, essid, data->length);
+       return zd1201_join(zd, zd->essid, zd->essidlen);
+}
+
+static int zd1201_get_essid(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       memcpy(essid, zd->essid, zd->essidlen);
+       data->flags = 1;
+       data->length = zd->essidlen;
+
+       return 0;
+}
+
+static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info,
+    struct iw_point *data, char *nick)
+{
+       strcpy(nick, "zd1201");
+       data->flags = 1;
+       data->length = strlen(nick);
+       return 0;
+}
+
+static int zd1201_set_rate(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short rate;
+       int err;
+
+       switch (rrq->value) {
+               case 1000000:
+                       rate = ZD1201_RATEB1;
+                       break;
+               case 2000000:
+                       rate = ZD1201_RATEB2;
+                       break;
+               case 5500000:
+                       rate = ZD1201_RATEB5;
+                       break;
+               case 11000000:
+               default:
+                       rate = ZD1201_RATEB11;
+                       break;
+       }
+       if (!rrq->fixed) { /* Also enable all lower bitrates */
+               rate |= rate-1;
+       }
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
+       if (err)
+               return err;
+
+       return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rate(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short rate;
+       int err;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate);
+       if (err)
+               return err;
+
+       switch(rate) {
+               case 1:
+                       rrq->value = 1000000;
+                       break;
+               case 2:
+                       rrq->value = 2000000;
+                       break;
+               case 5:
+                       rrq->value = 5500000;
+                       break;
+               case 11:
+                       rrq->value = 11000000;
+                       break;
+               default:
+                       rrq->value = 0;
+       }
+       rrq->fixed = 0;
+       rrq->disabled = 0;
+
+       return 0;
+}
+
+static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *rts, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       int err;
+       short val = rts->value;
+
+       if (rts->disabled || !rts->fixed)
+               val = ZD1201_RTSMAX;
+       if (val > ZD1201_RTSMAX)
+               return -EINVAL;
+       if (val < 0)
+               return -EINVAL;
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val);
+       if (err)
+               return err;
+       return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *rts, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short rtst;
+       int err;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst);
+       if (err)
+               return err;
+       rts->value = rtst;
+       rts->disabled = (rts->value == ZD1201_RTSMAX);
+       rts->fixed = 1;
+
+       return 0;
+}
+
+static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *frag, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       int err;
+       short val = frag->value;
+
+       if (frag->disabled || !frag->fixed)
+               val = ZD1201_FRAGMAX;
+       if (val > ZD1201_FRAGMAX)
+               return -EINVAL;
+       if (val < ZD1201_FRAGMIN)
+               return -EINVAL;
+       if (val & 1)
+               return -EINVAL;
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val);
+       if (err)
+               return err;
+       return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *frag, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short fragt;
+       int err;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt);
+       if (err)
+               return err;
+       frag->value = fragt;
+       frag->disabled = (frag->value == ZD1201_FRAGMAX);
+       frag->fixed = 1;
+
+       return 0;
+}
+
+static int zd1201_set_retry(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       return 0;
+}
+
+static int zd1201_get_retry(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       return 0;
+}
+
+static int zd1201_set_encode(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short i;
+       int err, rid;
+
+       if (erq->length > ZD1201_MAXKEYLEN)
+               return -EINVAL;
+
+       i = (erq->flags & IW_ENCODE_INDEX)-1;
+       if (i == -1) {
+               err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i);
+               if (err)
+                       return err;
+       } else {
+               err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i);
+               if (err)
+                       return err;
+       }
+
+       if (i < 0 || i >= ZD1201_NUMKEYS)
+               return -EINVAL;
+
+       rid = ZD1201_RID_CNFDEFAULTKEY0 + i;
+       err = zd1201_setconfig(zd, rid, key, erq->length, 1);
+       if (err)
+               return err;
+       zd->encode_keylen[i] = erq->length;
+       memcpy(zd->encode_keys[i], key, erq->length);
+
+       i=0;
+       if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) {
+               i |= 0x01;
+               zd->encode_enabled = 1;
+       } else
+               zd->encode_enabled = 0;
+       if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) {
+               i |= 0x02;
+               zd->encode_restricted = 1;
+       } else
+               zd->encode_restricted = 0;
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i);
+       if (err)
+               return err;
+
+       if (zd->encode_enabled)
+               i = ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+       else
+               i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i);
+       if (err)
+               return err;
+
+       return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_encode(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short i;
+       int err;
+
+       if (zd->encode_enabled)
+               erq->flags = IW_ENCODE_ENABLED;
+       else
+               erq->flags = IW_ENCODE_DISABLED;
+       if (zd->encode_restricted)
+               erq->flags |= IW_ENCODE_RESTRICTED;
+       else
+               erq->flags |= IW_ENCODE_OPEN;
+
+       i = (erq->flags & IW_ENCODE_INDEX) -1;
+       if (i == -1) {
+               err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i);
+               if (err)
+                       return err;
+       }
+       if (i<0 || i>= ZD1201_NUMKEYS)
+               return -EINVAL;
+
+       erq->flags |= i+1;
+
+       erq->length = zd->encode_keylen[i];
+       memcpy(key, zd->encode_keys[i], erq->length);
+
+       return 0;
+}
+
+static int zd1201_set_power(struct net_device *dev, 
+    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short enabled, duration, level;
+       int err;
+
+       enabled = vwrq->disabled ? 0 : 1;
+       if (enabled) {
+               if (vwrq->flags & IW_POWER_PERIOD) {
+                       duration = vwrq->value;
+                       err = zd1201_setconfig16(zd, 
+                           ZD1201_RID_CNFMAXSLEEPDURATION, duration);
+                       if (err)
+                               return err;
+                       goto out;
+               }
+               if (vwrq->flags & IW_POWER_TIMEOUT) {
+                       err = zd1201_getconfig16(zd, 
+                           ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+                       if (err)
+                               return err;
+                       level = vwrq->value * 4 / duration;
+                       if (level > 4)
+                               level = 4;
+                       if (level < 0)
+                               level = 0;
+                       err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS,
+                           level);
+                       if (err)
+                               return err;
+                       goto out;
+               }
+               return -EINVAL;
+       }
+out:
+       return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
+}
+
+static int zd1201_get_power(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short enabled, level, duration;
+       int err;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled);
+       if (err)
+               return err;
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level);
+       if (err)
+               return err;
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+       if (err)
+               return err;
+       vwrq->disabled = enabled ? 0 : 1;
+       if (vwrq->flags & IW_POWER_TYPE) {
+               if (vwrq->flags & IW_POWER_PERIOD) {
+                       vwrq->value = duration;
+                       vwrq->flags = IW_POWER_PERIOD;
+               } else {
+                       vwrq->value = duration * level / 4;
+                       vwrq->flags = IW_POWER_TIMEOUT;
+               }
+       }
+       if (vwrq->flags & IW_POWER_MODE) {
+               if (enabled && level)
+                       vwrq->flags = IW_POWER_UNICAST_R;
+               else
+                       vwrq->flags = IW_POWER_ALL_R;
+       }
+
+       return 0;
+}
+
+
+static const iw_handler zd1201_iw_handler[] =
+{
+       (iw_handler) zd1201_config_commit,      /* SIOCSIWCOMMIT */
+       (iw_handler) zd1201_get_name,           /* SIOCGIWNAME */
+       (iw_handler) NULL,                      /* SIOCSIWNWID */
+       (iw_handler) NULL,                      /* SIOCGIWNWID */
+       (iw_handler) zd1201_set_freq,           /* SIOCSIWFREQ */
+       (iw_handler) zd1201_get_freq,           /* SIOCGIWFREQ */
+       (iw_handler) zd1201_set_mode,           /* SIOCSIWMODE */
+       (iw_handler) zd1201_get_mode,           /* SIOCGIWMODE */
+       (iw_handler) NULL,                      /* SIOCSIWSENS */
+       (iw_handler) NULL,                      /* SIOCGIWSENS */
+       (iw_handler) NULL,                      /* SIOCSIWRANGE */
+       (iw_handler) zd1201_get_range,           /* SIOCGIWRANGE */
+       (iw_handler) NULL,                      /* SIOCSIWPRIV */
+       (iw_handler) NULL,                      /* SIOCGIWPRIV */
+       (iw_handler) NULL,                      /* SIOCSIWSTATS */
+       (iw_handler) NULL,                      /* SIOCGIWSTATS */
+       (iw_handler) NULL,                      /* SIOCSIWSPY */
+       (iw_handler) NULL,                      /* SIOCGIWSPY */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL/*zd1201_set_wap*/,            /* SIOCSIWAP */
+       (iw_handler) zd1201_get_wap,            /* SIOCGIWAP */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* SIOCGIWAPLIST */
+       (iw_handler) zd1201_set_scan,           /* SIOCSIWSCAN */
+       (iw_handler) zd1201_get_scan,           /* SIOCGIWSCAN */
+       (iw_handler) zd1201_set_essid,          /* SIOCSIWESSID */
+       (iw_handler) zd1201_get_essid,          /* SIOCGIWESSID */
+       (iw_handler) NULL,                      /* SIOCSIWNICKN */
+       (iw_handler) zd1201_get_nick,           /* SIOCGIWNICKN */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) zd1201_set_rate,           /* SIOCSIWRATE */
+       (iw_handler) zd1201_get_rate,           /* SIOCGIWRATE */
+       (iw_handler) zd1201_set_rts,            /* SIOCSIWRTS */
+       (iw_handler) zd1201_get_rts,            /* SIOCGIWRTS */
+       (iw_handler) zd1201_set_frag,           /* SIOCSIWFRAG */
+       (iw_handler) zd1201_get_frag,           /* SIOCGIWFRAG */
+       (iw_handler) NULL,                      /* SIOCSIWTXPOW */
+       (iw_handler) NULL,                      /* SIOCGIWTXPOW */
+       (iw_handler) zd1201_set_retry,          /* SIOCSIWRETRY */
+       (iw_handler) zd1201_get_retry,          /* SIOCGIWRETRY */
+       (iw_handler) zd1201_set_encode,         /* SIOCSIWENCODE */
+       (iw_handler) zd1201_get_encode,         /* SIOCGIWENCODE */
+       (iw_handler) zd1201_set_power,          /* SIOCSIWPOWER */
+       (iw_handler) zd1201_get_power,          /* SIOCGIWPOWER */
+};
+
+static int zd1201_set_hostauth(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+       if (!zd->ap)
+               return -EOPNOTSUPP;
+
+       return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
+}
+
+static int zd1201_get_hostauth(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short hostauth;
+       int err;
+
+       if (!zd->ap)
+               return -EOPNOTSUPP;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth);
+       if (err)
+               return err;
+       rrq->value = hostauth;
+       rrq->fixed = 1;
+
+       return 0;
+}
+
+static int zd1201_auth_sta(struct net_device *dev,
+    struct iw_request_info *info, struct sockaddr *sta, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       unsigned char buffer[10];
+
+       if (!zd->ap)
+               return -EOPNOTSUPP;
+
+       memcpy(buffer, sta->sa_data, ETH_ALEN);
+       *(short*)(buffer+6) = 0;        /* 0==success, 1==failure */
+       *(short*)(buffer+8) = 0;
+
+       return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1);
+}
+
+static int zd1201_set_maxassoc(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       int err;
+
+       if (!zd->ap)
+               return -EOPNOTSUPP;
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value);
+       if (err)
+               return err;
+       return 0;
+}
+
+static int zd1201_get_maxassoc(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+       struct zd1201 *zd = (struct zd1201 *)dev->priv;
+       short maxassoc;
+       int err;
+
+       if (!zd->ap)
+               return -EOPNOTSUPP;
+
+       err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc);
+       if (err)
+               return err;
+       rrq->value = maxassoc;
+       rrq->fixed = 1;
+
+       return 0;
+}
+
+static const iw_handler zd1201_private_handler[] = {
+       (iw_handler) zd1201_set_hostauth,       /* ZD1201SIWHOSTAUTH */
+       (iw_handler) zd1201_get_hostauth,       /* ZD1201GIWHOSTAUTH */
+       (iw_handler) zd1201_auth_sta,           /* ZD1201SIWAUTHSTA */
+       (iw_handler) NULL,                      /* nothing to get */
+       (iw_handler) zd1201_set_maxassoc,       /* ZD1201SIMAXASSOC */
+       (iw_handler) zd1201_get_maxassoc,       /* ZD1201GIMAXASSOC */
+};
+
+static const struct iw_priv_args zd1201_private_args[] = {
+       { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+           IW_PRIV_TYPE_NONE, "sethostauth" },
+       { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
+           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
+       { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
+           IW_PRIV_TYPE_NONE, "authstation" },
+       { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+           IW_PRIV_TYPE_NONE, "setmaxassoc" },
+       { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE,
+           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" },
+};
+
+static const struct iw_handler_def zd1201_iw_handlers = {
+       .num_standard           = ARRAY_SIZE(zd1201_iw_handler),
+       .num_private            = ARRAY_SIZE(zd1201_private_handler),
+       .num_private_args       = ARRAY_SIZE(zd1201_private_args),
+       .standard               = (iw_handler *)zd1201_iw_handler,
+       .private                = (iw_handler *)zd1201_private_handler,
+       .private_args           = (struct iw_priv_args *) zd1201_private_args,
+       .get_wireless_stats     = zd1201_get_wireless_stats,
+};
+
+static int zd1201_probe(struct usb_interface *interface,
+                       const struct usb_device_id *id)
+{
+       struct zd1201 *zd;
+       struct usb_device *usb;
+       int err;
+       short porttype;
+       char buf[IW_ESSID_MAX_SIZE+2];
+
+       usb = interface_to_usbdev(interface);
+
+       zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL);
+       if (!zd)
+               return -ENOMEM;
+       zd->ap = ap;
+       zd->usb = usb;
+       zd->removed = 0;
+       init_waitqueue_head(&zd->rxdataq);
+       INIT_HLIST_HEAD(&zd->fraglist);
+       
+       err = zd1201_fw_upload(usb, zd->ap);
+       if (err) {
+               dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err);
+               goto err_zd;
+       }
+       
+       zd->endp_in = 1;
+       zd->endp_out = 1;
+       zd->endp_out2 = 2;
+       zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!zd->rx_urb || !zd->tx_urb)
+               goto err_zd;
+
+       mdelay(100);
+       err = zd1201_drvr_start(zd);
+       if (err)
+               goto err_zd;
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312);
+       if (err)
+               goto err_start;
+
+       err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL,
+           ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11);
+       if (err)
+               goto err_start;
+
+       zd->dev = alloc_etherdev(0);
+       if (!zd->dev)
+               goto err_start;
+
+       zd->dev->priv = zd;
+       zd->dev->open = zd1201_net_open;
+       zd->dev->stop = zd1201_net_stop;
+       zd->dev->get_stats = zd1201_get_stats;
+       zd->dev->wireless_handlers =
+           (struct iw_handler_def *)&zd1201_iw_handlers;
+       zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
+       zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
+       zd->dev->tx_timeout = zd1201_tx_timeout;
+       zd->dev->set_multicast_list = zd1201_set_multicast;
+       zd->dev->set_mac_address = zd1201_set_mac_address;
+       strcpy(zd->dev->name, "wlan%d");
+
+       err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+           zd->dev->dev_addr, zd->dev->addr_len);
+       if (err)
+               goto err_net;
+
+       /* Set wildcard essid to match zd->essid */
+       *(__le16 *)buf = cpu_to_le16(0);
+       err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+           IW_ESSID_MAX_SIZE+2, 1);
+       if (err)
+               goto err_net;
+
+       if (zd->ap)
+               porttype = ZD1201_PORTTYPE_AP;
+       else
+               porttype = ZD1201_PORTTYPE_BSS;
+       err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+       if (err)
+               goto err_net;
+
+       SET_NETDEV_DEV(zd->dev, &usb->dev);
+
+       err = register_netdev(zd->dev);
+       if (err)
+               goto err_net;
+       dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
+           zd->dev->name);
+
+       usb_set_intfdata(interface, zd);
+       zd1201_enable(zd);      /* zd1201 likes to startup enabled, */
+       zd1201_disable(zd);     /* interfering with all the wifis in range */
+       return 0;
+
+err_net:
+       free_netdev(zd->dev);
+err_start:
+       /* Leave the device in reset state */
+       zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+err_zd:
+       if (zd->tx_urb)
+               usb_free_urb(zd->tx_urb);
+       if (zd->rx_urb)
+               usb_free_urb(zd->rx_urb);
+       kfree(zd);
+       return err;
+}
+
+static void zd1201_disconnect(struct usb_interface *interface)
+{
+       struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface);
+       struct hlist_node *node, *node2;
+       struct zd1201_frag *frag;
+
+       if (!zd)
+               return;
+       usb_set_intfdata(interface, NULL);
+       if (zd->dev) {
+               unregister_netdev(zd->dev);
+               free_netdev(zd->dev);
+       }
+
+       hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) {
+               hlist_del_init(&frag->fnode);
+               kfree_skb(frag->skb);
+               kfree(frag);
+       }
+
+       if (zd->tx_urb) {
+               usb_kill_urb(zd->tx_urb);
+               usb_free_urb(zd->tx_urb);
+       }
+       if (zd->rx_urb) {
+               usb_kill_urb(zd->rx_urb);
+               usb_free_urb(zd->rx_urb);
+       }
+       kfree(zd);
+}
+
+#ifdef CONFIG_PM
+
+static int zd1201_suspend(struct usb_interface *interface,
+                          pm_message_t message)
+{
+       struct zd1201 *zd = usb_get_intfdata(interface);
+
+       netif_device_detach(zd->dev);
+
+       zd->was_enabled = zd->mac_enabled;
+
+       if (zd->was_enabled)
+               return zd1201_disable(zd);
+       else
+               return 0;
+}
+
+static int zd1201_resume(struct usb_interface *interface)
+{
+       struct zd1201 *zd = usb_get_intfdata(interface);
+
+       if (!zd || !zd->dev)
+               return -ENODEV;
+
+       netif_device_attach(zd->dev);
+
+       if (zd->was_enabled)
+               return zd1201_enable(zd);
+       else
+               return 0;
+}
+
+#else
+
+#define zd1201_suspend NULL
+#define zd1201_resume  NULL
+
+#endif
+
+static struct usb_driver zd1201_usb = {
+       .name = "zd1201",
+       .probe = zd1201_probe,
+       .disconnect = zd1201_disconnect,
+       .id_table = zd1201_table,
+       .suspend = zd1201_suspend,
+       .resume = zd1201_resume,
+};
+
+static int __init zd1201_init(void)
+{
+       return usb_register(&zd1201_usb);
+}
+
+static void __exit zd1201_cleanup(void)
+{
+       usb_deregister(&zd1201_usb);
+}
+
+module_init(zd1201_init);
+module_exit(zd1201_cleanup);
diff --git a/drivers/net/wireless/zd1201.h b/drivers/net/wireless/zd1201.h
new file mode 100644 (file)
index 0000000..235f0ee
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ *     Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     Parts of this driver have been derived from a wlan-ng version
+ *     modified by ZyDAS.
+ *     Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ */
+
+#ifndef _INCLUDE_ZD1201_H_
+#define _INCLUDE_ZD1201_H_
+
+#define ZD1201_NUMKEYS         4
+#define ZD1201_MAXKEYLEN       13
+#define ZD1201_MAXMULTI                16
+#define ZD1201_FRAGMAX         2500
+#define ZD1201_FRAGMIN         256
+#define ZD1201_RTSMAX          2500
+
+#define ZD1201_RXSIZE          3000
+
+struct zd1201 {
+       struct usb_device       *usb;
+       int                     removed;
+       struct net_device       *dev;
+       struct net_device_stats stats;
+       struct iw_statistics    iwstats;
+
+       int                     endp_in;
+       int                     endp_out;
+       int                     endp_out2;
+       struct urb              *rx_urb;
+       struct urb              *tx_urb;
+
+       unsigned char           rxdata[ZD1201_RXSIZE];
+       int                     rxlen;
+       wait_queue_head_t       rxdataq;
+       int                     rxdatas;
+       struct hlist_head       fraglist;
+       unsigned char           txdata[ZD1201_RXSIZE];
+
+       int                     ap;
+       char                    essid[IW_ESSID_MAX_SIZE+1];
+       int                     essidlen;
+       int                     mac_enabled;
+       int                     was_enabled;
+       int                     monitor;
+       int                     encode_enabled;
+       int                     encode_restricted;
+       unsigned char           encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN];
+       int                     encode_keylen[ZD1201_NUMKEYS];
+};
+
+struct zd1201_frag {
+       struct hlist_node       fnode;
+       int                     seq;
+       struct sk_buff          *skb;
+};
+
+#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV
+#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1
+#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2
+#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4
+#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1
+
+#define ZD1201_FW_TIMEOUT      (1000)
+
+#define ZD1201_TX_TIMEOUT      (2000)
+
+#define ZD1201_USB_CMDREQ      0
+#define ZD1201_USB_RESREQ      1
+
+#define        ZD1201_CMDCODE_INIT     0x00
+#define ZD1201_CMDCODE_ENABLE  0x01
+#define ZD1201_CMDCODE_DISABLE 0x02
+#define ZD1201_CMDCODE_ALLOC   0x0a
+#define ZD1201_CMDCODE_INQUIRE 0x11
+#define ZD1201_CMDCODE_SETRXRID        0x17
+#define ZD1201_CMDCODE_ACCESS  0x21
+
+#define ZD1201_PACKET_EVENTSTAT        0x0
+#define ZD1201_PACKET_RXDATA   0x1
+#define ZD1201_PACKET_INQUIRE  0x2
+#define ZD1201_PACKET_RESOURCE 0x3
+
+#define ZD1201_ACCESSBIT       0x0100
+
+#define ZD1201_RID_CNFPORTTYPE         0xfc00
+#define ZD1201_RID_CNFOWNMACADDR       0xfc01
+#define ZD1201_RID_CNFDESIREDSSID      0xfc02
+#define ZD1201_RID_CNFOWNCHANNEL       0xfc03
+#define ZD1201_RID_CNFOWNSSID          0xfc04
+#define ZD1201_RID_CNFMAXDATALEN       0xfc07
+#define ZD1201_RID_CNFPMENABLED                0xfc09
+#define ZD1201_RID_CNFPMEPS            0xfc0a
+#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c
+#define ZD1201_RID_CNFDEFAULTKEYID     0xfc23
+#define ZD1201_RID_CNFDEFAULTKEY0      0xfc24
+#define ZD1201_RID_CNFDEFAULTKEY1      0xfc25
+#define ZD1201_RID_CNFDEFAULTKEY2      0xfc26
+#define ZD1201_RID_CNFDEFAULTKEY3      0xfc27
+#define ZD1201_RID_CNFWEBFLAGS         0xfc28
+#define ZD1201_RID_CNFAUTHENTICATION   0xfc2a
+#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b
+#define ZD1201_RID_CNFHOSTAUTH         0xfc2e
+#define ZD1201_RID_CNFGROUPADDRESS     0xfc80
+#define ZD1201_RID_CNFFRAGTHRESHOLD    0xfc82
+#define ZD1201_RID_CNFRTSTHRESHOLD     0xfc83
+#define ZD1201_RID_TXRATECNTL          0xfc84
+#define ZD1201_RID_PROMISCUOUSMODE     0xfc85
+#define ZD1201_RID_CNFBASICRATES       0xfcb3
+#define ZD1201_RID_AUTHENTICATESTA     0xfce3
+#define ZD1201_RID_CURRENTBSSID                0xfd42
+#define ZD1201_RID_COMMSQUALITY                0xfd43
+#define ZD1201_RID_CURRENTTXRATE       0xfd44
+#define ZD1201_RID_CNFMAXTXBUFFERNUMBER        0xfda0
+#define ZD1201_RID_CURRENTCHANNEL      0xfdc1
+
+#define ZD1201_INQ_SCANRESULTS         0xf101
+
+#define ZD1201_INF_LINKSTATUS          0xf200
+#define ZD1201_INF_ASSOCSTATUS         0xf201
+#define ZD1201_INF_AUTHREQ             0xf202
+
+#define ZD1201_ASSOCSTATUS_STAASSOC    0x1
+#define ZD1201_ASSOCSTATUS_REASSOC     0x2
+#define ZD1201_ASSOCSTATUS_DISASSOC    0x3
+#define ZD1201_ASSOCSTATUS_ASSOCFAIL   0x4
+#define ZD1201_ASSOCSTATUS_AUTHFAIL    0x5
+
+#define ZD1201_PORTTYPE_IBSS           0
+#define ZD1201_PORTTYPE_BSS            1
+#define ZD1201_PORTTYPE_WDS            2
+#define ZD1201_PORTTYPE_PSEUDOIBSS     3
+#define ZD1201_PORTTYPE_AP             6
+
+#define ZD1201_RATEB1  1
+#define ZD1201_RATEB2  2
+#define ZD1201_RATEB5  4       /* 5.5 really, but 5 is shorter :) */
+#define ZD1201_RATEB11 8
+
+#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM    0x0001
+#define ZD1201_CNFAUTHENTICATION_SHAREDKEY     0x0002
+
+#endif /* _INCLUDE_ZD1201_H_ */
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig
new file mode 100644 (file)
index 0000000..66ed55b
--- /dev/null
@@ -0,0 +1,19 @@
+config ZD1211RW
+       tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
+       depends on USB && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
+       select FW_LOADER
+       ---help---
+         This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
+         chip, present in many USB-wireless adapters.
+
+         Device firmware is required alongside this driver. You can download the
+         firmware distribution from http://zd1211.ath.cx/get-firmware
+
+config ZD1211RW_DEBUG
+       bool "ZyDAS ZD1211 debugging"
+       depends on ZD1211RW
+       ---help---
+         ZD1211 debugging messages. Choosing Y will result in additional debug
+         messages being saved to your kernel logs, which may help debug any
+         problems.
+
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
new file mode 100644 (file)
index 0000000..500314f
--- /dev/null
@@ -0,0 +1,11 @@
+obj-$(CONFIG_ZD1211RW) += zd1211rw.o
+
+zd1211rw-objs := zd_chip.o zd_ieee80211.o \
+               zd_mac.o zd_netdev.o \
+               zd_rf_al2230.o zd_rf_rf2959.o \
+               zd_rf.o zd_usb.o zd_util.o
+
+ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
new file mode 100644 (file)
index 0000000..4b971a9
--- /dev/null
@@ -0,0 +1,1646 @@
+/* zd_chip.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This file implements all the hardware specific functions for the ZD1211
+ * and ZD1211B chips. Support for the ZD1211B was possible after Timothy
+ * Legge sent me a ZD1211B device. Thank you Tim. -- Uli
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include "zd_def.h"
+#include "zd_chip.h"
+#include "zd_ieee80211.h"
+#include "zd_mac.h"
+#include "zd_rf.h"
+#include "zd_util.h"
+
+void zd_chip_init(struct zd_chip *chip,
+                struct net_device *netdev,
+                struct usb_interface *intf)
+{
+       memset(chip, 0, sizeof(*chip));
+       mutex_init(&chip->mutex);
+       zd_usb_init(&chip->usb, netdev, intf);
+       zd_rf_init(&chip->rf);
+}
+
+void zd_chip_clear(struct zd_chip *chip)
+{
+       mutex_lock(&chip->mutex);
+       zd_usb_clear(&chip->usb);
+       zd_rf_clear(&chip->rf);
+       mutex_unlock(&chip->mutex);
+       mutex_destroy(&chip->mutex);
+       memset(chip, 0, sizeof(*chip));
+}
+
+static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
+{
+       return scnprintf(buffer, size, "%02x-%02x-%02x",
+                        addr[0], addr[1], addr[2]);
+}
+
+/* Prints an identifier line, which will support debugging. */
+static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
+{
+       int i = 0;
+
+       i = scnprintf(buffer, size, "zd1211%s chip ",
+                     chip->is_zd1211b ? "b" : "");
+       i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
+       i += scnprintf(buffer+i, size-i, " ");
+       i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
+       i += scnprintf(buffer+i, size-i, " ");
+       i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
+       i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type,
+               chip->patch_cck_gain ? 'g' : '-',
+               chip->patch_cr157 ? '7' : '-',
+               chip->patch_6m_band_edge ? '6' : '-');
+       return i;
+}
+
+static void print_id(struct zd_chip *chip)
+{
+       char buffer[80];
+
+       scnprint_id(chip, buffer, sizeof(buffer));
+       buffer[sizeof(buffer)-1] = 0;
+       dev_info(zd_chip_dev(chip), "%s\n", buffer);
+}
+
+/* Read a variable number of 32-bit values. Parameter count is not allowed to
+ * exceed USB_MAX_IOREAD32_COUNT.
+ */
+int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr,
+                unsigned int count)
+{
+       int r;
+       int i;
+       zd_addr_t *a16 = (zd_addr_t *)NULL;
+       u16 *v16;
+       unsigned int count16;
+
+       if (count > USB_MAX_IOREAD32_COUNT)
+               return -EINVAL;
+
+       /* Allocate a single memory block for values and addresses. */
+       count16 = 2*count;
+       a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
+                                  GFP_NOFS);
+       if (!a16) {
+               dev_dbg_f(zd_chip_dev(chip),
+                         "error ENOMEM in allocation of a16\n");
+               r = -ENOMEM;
+               goto out;
+       }
+       v16 = (u16 *)(a16 + count16);
+
+       for (i = 0; i < count; i++) {
+               int j = 2*i;
+               /* We read the high word always first. */
+               a16[j] = zd_inc_word(addr[i]);
+               a16[j+1] = addr[i];
+       }
+
+       r = zd_ioread16v_locked(chip, v16, a16, count16);
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                         "error: zd_ioread16v_locked. Error number %d\n", r);
+               goto out;
+       }
+
+       for (i = 0; i < count; i++) {
+               int j = 2*i;
+               values[i] = (v16[j] << 16) | v16[j+1];
+       }
+
+out:
+       kfree((void *)a16);
+       return r;
+}
+
+int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                  unsigned int count)
+{
+       int i, j, r;
+       struct zd_ioreq16 *ioreqs16;
+       unsigned int count16;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+
+       if (count == 0)
+               return 0;
+       if (count > USB_MAX_IOWRITE32_COUNT)
+               return -EINVAL;
+
+       /* Allocate a single memory block for values and addresses. */
+       count16 = 2*count;
+       ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_NOFS);
+       if (!ioreqs16) {
+               r = -ENOMEM;
+               dev_dbg_f(zd_chip_dev(chip),
+                         "error %d in ioreqs16 allocation\n", r);
+               goto out;
+       }
+
+       for (i = 0; i < count; i++) {
+               j = 2*i;
+               /* We write the high word always first. */
+               ioreqs16[j].value   = ioreqs[i].value >> 16;
+               ioreqs16[j].addr    = zd_inc_word(ioreqs[i].addr);
+               ioreqs16[j+1].value = ioreqs[i].value;
+               ioreqs16[j+1].addr  = ioreqs[i].addr;
+       }
+
+       r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16);
+#ifdef DEBUG
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                         "error %d in zd_usb_write16v\n", r);
+       }
+#endif /* DEBUG */
+out:
+       kfree(ioreqs16);
+       return r;
+}
+
+int zd_iowrite16a_locked(struct zd_chip *chip,
+                  const struct zd_ioreq16 *ioreqs, unsigned int count)
+{
+       int r;
+       unsigned int i, j, t, max;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       for (i = 0; i < count; i += j + t) {
+               t = 0;
+               max = count-i;
+               if (max > USB_MAX_IOWRITE16_COUNT)
+                       max = USB_MAX_IOWRITE16_COUNT;
+               for (j = 0; j < max; j++) {
+                       if (!ioreqs[i+j].addr) {
+                               t = 1;
+                               break;
+                       }
+               }
+
+               r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j);
+               if (r) {
+                       dev_dbg_f(zd_chip_dev(chip),
+                                 "error zd_usb_iowrite16v. Error number %d\n",
+                                 r);
+                       return r;
+               }
+       }
+
+       return 0;
+}
+
+/* Writes a variable number of 32 bit registers. The functions will split
+ * that in several USB requests. A split can be forced by inserting an IO
+ * request with an zero address field.
+ */
+int zd_iowrite32a_locked(struct zd_chip *chip,
+                 const struct zd_ioreq32 *ioreqs, unsigned int count)
+{
+       int r;
+       unsigned int i, j, t, max;
+
+       for (i = 0; i < count; i += j + t) {
+               t = 0;
+               max = count-i;
+               if (max > USB_MAX_IOWRITE32_COUNT)
+                       max = USB_MAX_IOWRITE32_COUNT;
+               for (j = 0; j < max; j++) {
+                       if (!ioreqs[i+j].addr) {
+                               t = 1;
+                               break;
+                       }
+               }
+
+               r = _zd_iowrite32v_locked(chip, &ioreqs[i], j);
+               if (r) {
+                       dev_dbg_f(zd_chip_dev(chip),
+                               "error _zd_iowrite32v_locked."
+                               " Error number %d\n", r);
+                       return r;
+               }
+       }
+
+       return 0;
+}
+
+int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
+{
+       int r;
+
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       mutex_lock(&chip->mutex);
+       r = zd_ioread16_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value)
+{
+       int r;
+
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value)
+{
+       int r;
+
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite16_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value)
+{
+       int r;
+
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
+                 u32 *values, unsigned int count)
+{
+       int r;
+
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32v_locked(chip, values, addresses, count);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                 unsigned int count)
+{
+       int r;
+
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32a_locked(chip, ioreqs, count);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int read_pod(struct zd_chip *chip, u8 *rf_type)
+{
+       int r;
+       u32 value;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &value, E2P_POD);
+       if (r)
+               goto error;
+       dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value);
+
+       /* FIXME: AL2230 handling (Bit 7 in POD) */
+       *rf_type = value & 0x0f;
+       chip->pa_type = (value >> 16) & 0x0f;
+       chip->patch_cck_gain = (value >> 8) & 0x1;
+       chip->patch_cr157 = (value >> 13) & 0x1;
+       chip->patch_6m_band_edge = (value >> 21) & 0x1;
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
+               "patch 6M %d\n",
+               zd_rf_name(*rf_type), *rf_type,
+               chip->pa_type, chip->patch_cck_gain,
+               chip->patch_cr157, chip->patch_6m_band_edge);
+       return 0;
+error:
+       *rf_type = 0;
+       chip->pa_type = 0;
+       chip->patch_cck_gain = 0;
+       chip->patch_cr157 = 0;
+       chip->patch_6m_band_edge = 0;
+       return r;
+}
+
+static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr,
+                         const zd_addr_t *addr)
+{
+       int r;
+       u32 parts[2];
+
+       r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2);
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                       "error: couldn't read e2p macs. Error number %d\n", r);
+               return r;
+       }
+
+       mac_addr[0] = parts[0];
+       mac_addr[1] = parts[0] >>  8;
+       mac_addr[2] = parts[0] >> 16;
+       mac_addr[3] = parts[0] >> 24;
+       mac_addr[4] = parts[1];
+       mac_addr[5] = parts[1] >>  8;
+
+       return 0;
+}
+
+static int read_e2p_mac_addr(struct zd_chip *chip)
+{
+       static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 };
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr);
+}
+
+/* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and
+ *              CR_MAC_ADDR_P2 must be overwritten
+ */
+void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr)
+{
+       mutex_lock(&chip->mutex);
+       memcpy(mac_addr, chip->e2p_mac, ETH_ALEN);
+       mutex_unlock(&chip->mutex);
+}
+
+static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
+{
+       static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 };
+       return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr);
+}
+
+int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
+{
+       int r;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       mutex_lock(&chip->mutex);
+       r = read_mac_addr(chip, mac_addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+{
+       int r;
+       struct zd_ioreq32 reqs[2] = {
+               [0] = { .addr = CR_MAC_ADDR_P1 },
+               [1] = { .addr = CR_MAC_ADDR_P2 },
+       };
+
+       reqs[0].value = (mac_addr[3] << 24)
+                     | (mac_addr[2] << 16)
+                     | (mac_addr[1] <<  8)
+                     |  mac_addr[0];
+       reqs[1].value = (mac_addr[5] <<  8)
+                     |  mac_addr[4];
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "mac addr " MAC_FMT "\n", MAC_ARG(mac_addr));
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
+#ifdef DEBUG
+       {
+               u8 tmp[ETH_ALEN];
+               read_mac_addr(chip, tmp);
+       }
+#endif /* DEBUG */
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
+{
+       int r;
+       u32 value;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32_locked(chip, &value, E2P_SUBID);
+       mutex_unlock(&chip->mutex);
+       if (r)
+               return r;
+
+       *regdomain = value >> 16;
+       dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain);
+
+       return 0;
+}
+
+static int read_values(struct zd_chip *chip, u8 *values, size_t count,
+                      zd_addr_t e2p_addr, u32 guard)
+{
+       int r;
+       int i;
+       u32 v;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       for (i = 0;;) {
+               r = zd_ioread32_locked(chip, &v, e2p_addr+i/2);
+               if (r)
+                       return r;
+               v -= guard;
+               if (i+4 < count) {
+                       values[i++] = v;
+                       values[i++] = v >>  8;
+                       values[i++] = v >> 16;
+                       values[i++] = v >> 24;
+                       continue;
+               }
+               for (;i < count; i++)
+                       values[i] = v >> (8*(i%3));
+               return 0;
+       }
+}
+
+static int read_pwr_cal_values(struct zd_chip *chip)
+{
+       return read_values(chip, chip->pwr_cal_values,
+                       E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1,
+                       0);
+}
+
+static int read_pwr_int_values(struct zd_chip *chip)
+{
+       return read_values(chip, chip->pwr_int_values,
+                       E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1,
+                       E2P_PWR_INT_GUARD);
+}
+
+static int read_ofdm_cal_values(struct zd_chip *chip)
+{
+       int r;
+       int i;
+       static const zd_addr_t addresses[] = {
+               E2P_36M_CAL_VALUE1,
+               E2P_48M_CAL_VALUE1,
+               E2P_54M_CAL_VALUE1,
+       };
+
+       for (i = 0; i < 3; i++) {
+               r = read_values(chip, chip->ofdm_cal_values[i],
+                               E2P_CHANNEL_COUNT, addresses[i], 0);
+               if (r)
+                       return r;
+       }
+       return 0;
+}
+
+static int read_cal_int_tables(struct zd_chip *chip)
+{
+       int r;
+
+       r = read_pwr_cal_values(chip);
+       if (r)
+               return r;
+       r = read_pwr_int_values(chip);
+       if (r)
+               return r;
+       r = read_ofdm_cal_values(chip);
+       if (r)
+               return r;
+       return 0;
+}
+
+/* phy means physical registers */
+int zd_chip_lock_phy_regs(struct zd_chip *chip)
+{
+       int r;
+       u32 tmp;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &tmp, CR_REG1);
+       if (r) {
+               dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r);
+               return r;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp & ~UNLOCK_PHY_REGS);
+       tmp &= ~UNLOCK_PHY_REGS;
+
+       r = zd_iowrite32_locked(chip, tmp, CR_REG1);
+       if (r)
+               dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
+       return r;
+}
+
+int zd_chip_unlock_phy_regs(struct zd_chip *chip)
+{
+       int r;
+       u32 tmp;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &tmp, CR_REG1);
+       if (r) {
+               dev_err(zd_chip_dev(chip),
+                       "error ioread32(CR_REG1): %d\n", r);
+               return r;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp | UNLOCK_PHY_REGS);
+       tmp |= UNLOCK_PHY_REGS;
+
+       r = zd_iowrite32_locked(chip, tmp, CR_REG1);
+       if (r)
+               dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
+       return r;
+}
+
+/* CR157 can be optionally patched by the EEPROM */
+static int patch_cr157(struct zd_chip *chip)
+{
+       int r;
+       u32 value;
+
+       if (!chip->patch_cr157)
+               return 0;
+
+       r = zd_ioread32_locked(chip, &value, E2P_PHY_REG);
+       if (r)
+               return r;
+
+       dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8);
+       return zd_iowrite32_locked(chip, value >> 8, CR157);
+}
+
+/*
+ * 6M band edge can be optionally overwritten for certain RF's
+ * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge
+ * bit (for AL2230, AL2230S)
+ */
+static int patch_6m_band_edge(struct zd_chip *chip, int channel)
+{
+       struct zd_ioreq16 ioreqs[] = {
+               { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+               { CR47,  0x1e },
+       };
+
+       if (!chip->patch_6m_band_edge || !chip->rf.patch_6m_band_edge)
+               return 0;
+
+       /* FIXME: Channel 11 is not the edge for all regulatory domains. */
+       if (channel == 1 || channel == 11)
+               ioreqs[0].value = 0x12;
+
+       dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel);
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211_hw_reset_phy(struct zd_chip *chip)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR0,   0x0a }, { CR1,   0x06 }, { CR2,   0x26 },
+               { CR3,   0x38 }, { CR4,   0x80 }, { CR9,   0xa0 },
+               { CR10,  0x81 }, { CR11,  0x00 }, { CR12,  0x7f },
+               { CR13,  0x8c }, { CR14,  0x80 }, { CR15,  0x3d },
+               { CR16,  0x20 }, { CR17,  0x1e }, { CR18,  0x0a },
+               { CR19,  0x48 }, { CR20,  0x0c }, { CR21,  0x0c },
+               { CR22,  0x23 }, { CR23,  0x90 }, { CR24,  0x14 },
+               { CR25,  0x40 }, { CR26,  0x10 }, { CR27,  0x19 },
+               { CR28,  0x7f }, { CR29,  0x80 }, { CR30,  0x4b },
+               { CR31,  0x60 }, { CR32,  0x43 }, { CR33,  0x08 },
+               { CR34,  0x06 }, { CR35,  0x0a }, { CR36,  0x00 },
+               { CR37,  0x00 }, { CR38,  0x38 }, { CR39,  0x0c },
+               { CR40,  0x84 }, { CR41,  0x2a }, { CR42,  0x80 },
+               { CR43,  0x10 }, { CR44,  0x12 }, { CR46,  0xff },
+               { CR47,  0x1E }, { CR48,  0x26 }, { CR49,  0x5b },
+               { CR64,  0xd0 }, { CR65,  0x04 }, { CR66,  0x58 },
+               { CR67,  0xc9 }, { CR68,  0x88 }, { CR69,  0x41 },
+               { CR70,  0x23 }, { CR71,  0x10 }, { CR72,  0xff },
+               { CR73,  0x32 }, { CR74,  0x30 }, { CR75,  0x65 },
+               { CR76,  0x41 }, { CR77,  0x1b }, { CR78,  0x30 },
+               { CR79,  0x68 }, { CR80,  0x64 }, { CR81,  0x64 },
+               { CR82,  0x00 }, { CR83,  0x00 }, { CR84,  0x00 },
+               { CR85,  0x02 }, { CR86,  0x00 }, { CR87,  0x00 },
+               { CR88,  0xff }, { CR89,  0xfc }, { CR90,  0x00 },
+               { CR91,  0x00 }, { CR92,  0x00 }, { CR93,  0x08 },
+               { CR94,  0x00 }, { CR95,  0x00 }, { CR96,  0xff },
+               { CR97,  0xe7 }, { CR98,  0x00 }, { CR99,  0x00 },
+               { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 },
+               { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 },
+               { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a },
+               { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 },
+               { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e },
+               { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 },
+               { },
+               { CR5,   0x00 }, { CR6,   0x00 }, { CR7,   0x00 },
+               { CR8,   0x00 }, { CR9,   0x20 }, { CR12,  0xf0 },
+               { CR20,  0x0e }, { CR21,  0x0e }, { CR27,  0x10 },
+               { CR44,  0x33 }, { CR47,  0x1E }, { CR83,  0x24 },
+               { CR84,  0x04 }, { CR85,  0x00 }, { CR86,  0x0C },
+               { CR87,  0x12 }, { CR88,  0x0C }, { CR89,  0x00 },
+               { CR90,  0x10 }, { CR91,  0x08 }, { CR93,  0x00 },
+               { CR94,  0x01 }, { CR95,  0x00 }, { CR96,  0x50 },
+               { CR97,  0x37 }, { CR98,  0x35 }, { CR101, 0x13 },
+               { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 },
+               { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 },
+               { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 },
+               { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 },
+               { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f },
+               { CR123, 0x27 }, { CR125, 0xaa }, { CR127, 0x03 },
+               { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+               { CR131, 0x0C }, { CR136, 0xdf }, { CR137, 0x40 },
+               { CR138, 0xa0 }, { CR139, 0xb0 }, { CR140, 0x99 },
+               { CR141, 0x82 }, { CR142, 0x54 }, { CR143, 0x1c },
+               { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x4c },
+               { CR149, 0x50 }, { CR150, 0x0e }, { CR151, 0x18 },
+               { CR160, 0xfe }, { CR161, 0xee }, { CR162, 0xaa },
+               { CR163, 0xfa }, { CR164, 0xfa }, { CR165, 0xea },
+               { CR166, 0xbe }, { CR167, 0xbe }, { CR168, 0x6a },
+               { CR169, 0xba }, { CR170, 0xba }, { CR171, 0xba },
+               /* Note: CR204 must lead the CR203 */
+               { CR204, 0x7d },
+               { },
+               { CR203, 0x30 },
+       };
+
+       int r, t;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               goto out;
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               goto unlock;
+
+       r = patch_cr157(chip);
+unlock:
+       t = zd_chip_unlock_phy_regs(chip);
+       if (t && !r)
+               r = t;
+out:
+       return r;
+}
+
+static int zd1211b_hw_reset_phy(struct zd_chip *chip)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR0,   0x14 }, { CR1,   0x06 }, { CR2,   0x26 },
+               { CR3,   0x38 }, { CR4,   0x80 }, { CR9,   0xe0 },
+               { CR10,  0x81 },
+               /* power control { { CR11,  1 << 6 }, */
+               { CR11,  0x00 },
+               { CR12,  0xf0 }, { CR13,  0x8c }, { CR14,  0x80 },
+               { CR15,  0x3d }, { CR16,  0x20 }, { CR17,  0x1e },
+               { CR18,  0x0a }, { CR19,  0x48 },
+               { CR20,  0x10 }, /* Org:0x0E, ComTrend:RalLink AP */
+               { CR21,  0x0e }, { CR22,  0x23 }, { CR23,  0x90 },
+               { CR24,  0x14 }, { CR25,  0x40 }, { CR26,  0x10 },
+               { CR27,  0x10 }, { CR28,  0x7f }, { CR29,  0x80 },
+               { CR30,  0x4b }, /* ASIC/FWT, no jointly decoder */
+               { CR31,  0x60 }, { CR32,  0x43 }, { CR33,  0x08 },
+               { CR34,  0x06 }, { CR35,  0x0a }, { CR36,  0x00 },
+               { CR37,  0x00 }, { CR38,  0x38 }, { CR39,  0x0c },
+               { CR40,  0x84 }, { CR41,  0x2a }, { CR42,  0x80 },
+               { CR43,  0x10 }, { CR44,  0x33 }, { CR46,  0xff },
+               { CR47,  0x1E }, { CR48,  0x26 }, { CR49,  0x5b },
+               { CR64,  0xd0 }, { CR65,  0x04 }, { CR66,  0x58 },
+               { CR67,  0xc9 }, { CR68,  0x88 }, { CR69,  0x41 },
+               { CR70,  0x23 }, { CR71,  0x10 }, { CR72,  0xff },
+               { CR73,  0x32 }, { CR74,  0x30 }, { CR75,  0x65 },
+               { CR76,  0x41 }, { CR77,  0x1b }, { CR78,  0x30 },
+               { CR79,  0xf0 }, { CR80,  0x64 }, { CR81,  0x64 },
+               { CR82,  0x00 }, { CR83,  0x24 }, { CR84,  0x04 },
+               { CR85,  0x00 }, { CR86,  0x0c }, { CR87,  0x12 },
+               { CR88,  0x0c }, { CR89,  0x00 }, { CR90,  0x58 },
+               { CR91,  0x04 }, { CR92,  0x00 }, { CR93,  0x00 },
+               { CR94,  0x01 },
+               { CR95,  0x20 }, /* ZD1211B */
+               { CR96,  0x50 }, { CR97,  0x37 }, { CR98,  0x35 },
+               { CR99,  0x00 }, { CR100, 0x01 }, { CR101, 0x13 },
+               { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 },
+               { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 },
+               { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 },
+               { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 },
+               { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 },
+               { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e },
+               { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 },
+               { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+               { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 },
+               { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 },
+               { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c },
+               { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 },
+               { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */
+               { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */
+               { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe },
+               { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa },
+               { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe },
+               { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba },
+               { CR170, 0xba }, { CR171, 0xba },
+               /* Note: CR204 must lead the CR203 */
+               { CR204, 0x7d },
+               {},
+               { CR203, 0x30 },
+       };
+
+       int r, t;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               goto out;
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               goto unlock;
+
+       r = patch_cr157(chip);
+unlock:
+       t = zd_chip_unlock_phy_regs(chip);
+       if (t && !r)
+               r = t;
+out:
+       return r;
+}
+
+static int hw_reset_phy(struct zd_chip *chip)
+{
+       return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) :
+                                 zd1211_hw_reset_phy(chip);
+}
+
+static int zd1211_hw_init_hmac(struct zd_chip *chip)
+{
+       static const struct zd_ioreq32 ioreqs[] = {
+               { CR_ACK_TIMEOUT_EXT,           0x20 },
+               { CR_ADDA_MBIAS_WARMTIME,       0x30000808 },
+               { CR_ZD1211_RETRY_MAX,          0x2 },
+               { CR_SNIFFER_ON,                0 },
+               { CR_RX_FILTER,                 STA_RX_FILTER },
+               { CR_GROUP_HASH_P1,             0x00 },
+               { CR_GROUP_HASH_P2,             0x80000000 },
+               { CR_REG1,                      0xa4 },
+               { CR_ADDA_PWR_DWN,              0x7f },
+               { CR_BCN_PLCP_CFG,              0x00f00401 },
+               { CR_PHY_DELAY,                 0x00 },
+               { CR_ACK_TIMEOUT_EXT,           0x80 },
+               { CR_ADDA_PWR_DWN,              0x00 },
+               { CR_ACK_TIME_80211,            0x100 },
+               { CR_IFS_VALUE,                 0x547c032 },
+               { CR_RX_PE_DELAY,               0x70 },
+               { CR_PS_CTRL,                   0x10000000 },
+               { CR_RTS_CTS_RATE,              0x02030203 },
+               { CR_RX_THRESHOLD,              0x000c0640 },
+               { CR_AFTER_PNP,                 0x1 },
+               { CR_WEP_PROTECT,               0x114 },
+       };
+
+       int r;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+#ifdef DEBUG
+       if (r) {
+               dev_err(zd_chip_dev(chip),
+                       "error in zd_iowrite32a_locked. Error number %d\n", r);
+       }
+#endif /* DEBUG */
+       return r;
+}
+
+static int zd1211b_hw_init_hmac(struct zd_chip *chip)
+{
+       static const struct zd_ioreq32 ioreqs[] = {
+               { CR_ACK_TIMEOUT_EXT,           0x20 },
+               { CR_ADDA_MBIAS_WARMTIME,       0x30000808 },
+               { CR_ZD1211B_RETRY_MAX,         0x02020202 },
+               { CR_ZD1211B_TX_PWR_CTL4,       0x007f003f },
+               { CR_ZD1211B_TX_PWR_CTL3,       0x007f003f },
+               { CR_ZD1211B_TX_PWR_CTL2,       0x003f001f },
+               { CR_ZD1211B_TX_PWR_CTL1,       0x001f000f },
+               { CR_ZD1211B_AIFS_CTL1,         0x00280028 },
+               { CR_ZD1211B_AIFS_CTL2,         0x008C003C },
+               { CR_ZD1211B_TXOP,              0x01800824 },
+               { CR_SNIFFER_ON,                0 },
+               { CR_RX_FILTER,                 STA_RX_FILTER },
+               { CR_GROUP_HASH_P1,             0x00 },
+               { CR_GROUP_HASH_P2,             0x80000000 },
+               { CR_REG1,                      0xa4 },
+               { CR_ADDA_PWR_DWN,              0x7f },
+               { CR_BCN_PLCP_CFG,              0x00f00401 },
+               { CR_PHY_DELAY,                 0x00 },
+               { CR_ACK_TIMEOUT_EXT,           0x80 },
+               { CR_ADDA_PWR_DWN,              0x00 },
+               { CR_ACK_TIME_80211,            0x100 },
+               { CR_IFS_VALUE,                 0x547c032 },
+               { CR_RX_PE_DELAY,               0x70 },
+               { CR_PS_CTRL,                   0x10000000 },
+               { CR_RTS_CTS_RATE,              0x02030203 },
+               { CR_RX_THRESHOLD,              0x000c0640 },
+               { CR_AFTER_PNP,                 0x1 },
+               { CR_WEP_PROTECT,               0x114 },
+       };
+
+       int r;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                       "error in zd_iowrite32a_locked. Error number %d\n", r);
+       }
+       return r;
+}
+
+static int hw_init_hmac(struct zd_chip *chip)
+{
+       return chip->is_zd1211b ?
+               zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
+}
+
+struct aw_pt_bi {
+       u32 atim_wnd_period;
+       u32 pre_tbtt;
+       u32 beacon_interval;
+};
+
+static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
+{
+       int r;
+       static const zd_addr_t aw_pt_bi_addr[] =
+               { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL };
+       u32 values[3];
+
+       r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr,
+                        ARRAY_SIZE(aw_pt_bi_addr));
+       if (r) {
+               memset(s, 0, sizeof(*s));
+               return r;
+       }
+
+       s->atim_wnd_period = values[0];
+       s->pre_tbtt = values[1];
+       s->beacon_interval = values[2];
+       dev_dbg_f(zd_chip_dev(chip), "aw %u pt %u bi %u\n",
+               s->atim_wnd_period, s->pre_tbtt, s->beacon_interval);
+       return 0;
+}
+
+static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
+{
+       struct zd_ioreq32 reqs[3];
+
+       if (s->beacon_interval <= 5)
+               s->beacon_interval = 5;
+       if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval)
+               s->pre_tbtt = s->beacon_interval - 1;
+       if (s->atim_wnd_period >= s->pre_tbtt)
+               s->atim_wnd_period = s->pre_tbtt - 1;
+
+       reqs[0].addr = CR_ATIM_WND_PERIOD;
+       reqs[0].value = s->atim_wnd_period;
+       reqs[1].addr = CR_PRE_TBTT;
+       reqs[1].value = s->pre_tbtt;
+       reqs[2].addr = CR_BCN_INTERVAL;
+       reqs[2].value = s->beacon_interval;
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "aw %u pt %u bi %u\n", s->atim_wnd_period, s->pre_tbtt,
+                                      s->beacon_interval);
+       return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
+}
+
+
+static int set_beacon_interval(struct zd_chip *chip, u32 interval)
+{
+       int r;
+       struct aw_pt_bi s;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = get_aw_pt_bi(chip, &s);
+       if (r)
+               return r;
+       s.beacon_interval = interval;
+       return set_aw_pt_bi(chip, &s);
+}
+
+int zd_set_beacon_interval(struct zd_chip *chip, u32 interval)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = set_beacon_interval(chip, interval);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int hw_init(struct zd_chip *chip)
+{
+       int r;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = hw_reset_phy(chip);
+       if (r)
+               return r;
+
+       r = hw_init_hmac(chip);
+       if (r)
+               return r;
+       r = set_beacon_interval(chip, 100);
+       if (r)
+               return r;
+       return 0;
+}
+
+#ifdef DEBUG
+static int dump_cr(struct zd_chip *chip, const zd_addr_t addr,
+                  const char *addr_string)
+{
+       int r;
+       u32 value;
+
+       r = zd_ioread32_locked(chip, &value, addr);
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                       "error reading %s. Error number %d\n", addr_string, r);
+               return r;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n",
+               addr_string, (unsigned int)value);
+       return 0;
+}
+
+static int test_init(struct zd_chip *chip)
+{
+       int r;
+
+       r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP");
+       if (r)
+               return r;
+       r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN");
+       if (r)
+               return r;
+       return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT");
+}
+
+static void dump_fw_registers(struct zd_chip *chip)
+{
+       static const zd_addr_t addr[4] = {
+               FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE,
+               FW_LINK_STATUS
+       };
+
+       int r;
+       u16 values[4];
+
+       r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr,
+                        ARRAY_SIZE(addr));
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n",
+                        r);
+               return;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]);
+       dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]);
+       dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]);
+       dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]);
+}
+#endif /* DEBUG */
+
+static int print_fw_version(struct zd_chip *chip)
+{
+       int r;
+       u16 version;
+
+       r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER);
+       if (r)
+               return r;
+
+       dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version);
+       return 0;
+}
+
+static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
+{
+       u32 rates;
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       /* This sets the mandatory rates, which only depend from the standard
+        * that the device is supporting. Until further notice we should try
+        * to support 802.11g also for full speed USB.
+        */
+       switch (std) {
+       case IEEE80211B:
+               rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
+               break;
+       case IEEE80211G:
+               rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
+                       CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
+}
+
+int zd_chip_enable_hwint(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int disable_hwint(struct zd_chip *chip)
+{
+       return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT);
+}
+
+int zd_chip_disable_hwint(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = disable_hwint(chip);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
+{
+       int r;
+       u8 rf_type;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+
+       mutex_lock(&chip->mutex);
+       chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0;
+
+#ifdef DEBUG
+       r = test_init(chip);
+       if (r)
+               goto out;
+#endif
+       r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP);
+       if (r)
+               goto out;
+
+       r = zd_usb_init_hw(&chip->usb);
+       if (r)
+               goto out;
+
+       /* GPI is always disabled, also in the other driver.
+        */
+       r = zd_iowrite32_locked(chip, 0, CR_GPI_EN);
+       if (r)
+               goto out;
+       r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX);
+       if (r)
+               goto out;
+       /* Currently we support IEEE 802.11g for full and high speed USB.
+        * It might be discussed, whether we should suppport pure b mode for
+        * full speed USB.
+        */
+       r = set_mandatory_rates(chip, IEEE80211G);
+       if (r)
+               goto out;
+       /* Disabling interrupts is certainly a smart thing here.
+        */
+       r = disable_hwint(chip);
+       if (r)
+               goto out;
+       r = read_pod(chip, &rf_type);
+       if (r)
+               goto out;
+       r = hw_init(chip);
+       if (r)
+               goto out;
+       r = zd_rf_init_hw(&chip->rf, rf_type);
+       if (r)
+               goto out;
+
+       r = print_fw_version(chip);
+       if (r)
+               goto out;
+
+#ifdef DEBUG
+       dump_fw_registers(chip);
+       r = test_init(chip);
+       if (r)
+               goto out;
+#endif /* DEBUG */
+
+       r = read_e2p_mac_addr(chip);
+       if (r)
+               goto out;
+
+       r = read_cal_int_tables(chip);
+       if (r)
+               goto out;
+
+       print_id(chip);
+out:
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int update_pwr_int(struct zd_chip *chip, u8 channel)
+{
+       u8 value = chip->pwr_int_values[channel - 1];
+       dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n",
+                channel, value);
+       return zd_iowrite32_locked(chip, value, CR31);
+}
+
+static int update_pwr_cal(struct zd_chip *chip, u8 channel)
+{
+       u8 value = chip->pwr_cal_values[channel-1];
+       dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n",
+                channel, value);
+       return zd_iowrite32_locked(chip, value, CR68);
+}
+
+static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
+{
+       struct zd_ioreq32 ioreqs[3];
+
+       ioreqs[0].addr = CR67;
+       ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1];
+       ioreqs[1].addr = CR66;
+       ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1];
+       ioreqs[2].addr = CR65;
+       ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1];
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n",
+               channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value);
+       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int update_channel_integration_and_calibration(struct zd_chip *chip,
+                                                     u8 channel)
+{
+       int r;
+
+       r = update_pwr_int(chip, channel);
+       if (r)
+               return r;
+       if (chip->is_zd1211b) {
+               static const struct zd_ioreq32 ioreqs[] = {
+                       { CR69, 0x28 },
+                       {},
+                       { CR69, 0x2a },
+               };
+
+               r = update_ofdm_cal(chip, channel);
+               if (r)
+                       return r;
+               r = update_pwr_cal(chip, channel);
+               if (r)
+                       return r;
+               r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+/* The CCK baseband gain can be optionally patched by the EEPROM */
+static int patch_cck_gain(struct zd_chip *chip)
+{
+       int r;
+       u32 value;
+
+       if (!chip->patch_cck_gain)
+               return 0;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &value, E2P_PHY_REG);
+       if (r)
+               return r;
+       dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff);
+       return zd_iowrite32_locked(chip, value & 0xff, CR47);
+}
+
+int zd_chip_set_channel(struct zd_chip *chip, u8 channel)
+{
+       int r, t;
+
+       mutex_lock(&chip->mutex);
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               goto out;
+       r = zd_rf_set_channel(&chip->rf, channel);
+       if (r)
+               goto unlock;
+       r = update_channel_integration_and_calibration(chip, channel);
+       if (r)
+               goto unlock;
+       r = patch_cck_gain(chip);
+       if (r)
+               goto unlock;
+       r = patch_6m_band_edge(chip, channel);
+       if (r)
+               goto unlock;
+       r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS);
+unlock:
+       t = zd_chip_unlock_phy_regs(chip);
+       if (t && !r)
+               r = t;
+out:
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+u8 zd_chip_get_channel(struct zd_chip *chip)
+{
+       u8 channel;
+
+       mutex_lock(&chip->mutex);
+       channel = chip->rf.channel;
+       mutex_unlock(&chip->mutex);
+       return channel;
+}
+
+static u16 led_mask(int led)
+{
+       switch (led) {
+       case 1:
+               return LED1;
+       case 2:
+               return LED2;
+       default:
+               return 0;
+       }
+}
+
+static int read_led_reg(struct zd_chip *chip, u16 *status)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_ioread16_locked(chip, status, CR_LED);
+}
+
+static int write_led_reg(struct zd_chip *chip, u16 status)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_iowrite16_locked(chip, status, CR_LED);
+}
+
+int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status)
+{
+       int r, ret;
+       u16 mask = led_mask(led);
+       u16 reg;
+
+       if (!mask)
+               return -EINVAL;
+       mutex_lock(&chip->mutex);
+       r = read_led_reg(chip, &reg);
+       if (r)
+               return r;
+       switch (status) {
+       case LED_STATUS:
+               return (reg & mask) ? LED_ON : LED_OFF;
+       case LED_OFF:
+               reg &= ~mask;
+               ret = LED_OFF;
+               break;
+       case LED_FLIP:
+               reg ^= mask;
+               ret = (reg&mask) ? LED_ON : LED_OFF;
+               break;
+       case LED_ON:
+               reg |= mask;
+               ret = LED_ON;
+               break;
+       default:
+               return -EINVAL;
+       }
+       r = write_led_reg(chip, reg);
+       if (r) {
+               ret = r;
+               goto out;
+       }
+out:
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_led_flip(struct zd_chip *chip, int led,
+       const unsigned int *phases_msecs, unsigned int count)
+{
+       int i, r;
+       enum led_status status;
+
+       r = zd_chip_led_status(chip, led, LED_STATUS);
+       if (r)
+               return r;
+       status = r;
+       for (i = 0; i < count; i++) {
+               r = zd_chip_led_status(chip, led, LED_FLIP);
+               if (r < 0)
+                       goto out;
+               msleep(phases_msecs[i]);
+       }
+
+out:
+       zd_chip_led_status(chip, led, status);
+       return r;
+}
+
+int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
+{
+       int r;
+
+       if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size)
+{
+       static const u16 constants[] = {
+               715, 655, 585, 540, 470, 410, 360, 315,
+               270, 235, 205, 175, 150, 125, 105,  85,
+                65,  50,  40,  25,  15
+       };
+
+       int i;
+       u32 x;
+
+       /* It seems that their quality parameter is somehow per signal
+        * and is now transferred per bit.
+        */
+       switch (rate) {
+       case ZD_OFDM_RATE_6M:
+       case ZD_OFDM_RATE_12M:
+       case ZD_OFDM_RATE_24M:
+               size *= 2;
+               break;
+       case ZD_OFDM_RATE_9M:
+       case ZD_OFDM_RATE_18M:
+       case ZD_OFDM_RATE_36M:
+       case ZD_OFDM_RATE_54M:
+               size *= 4;
+               size /= 3;
+               break;
+       case ZD_OFDM_RATE_48M:
+               size *= 3;
+               size /= 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       x = (10000 * status_quality)/size;
+       for (i = 0; i < ARRAY_SIZE(constants); i++) {
+               if (x > constants[i])
+                       break;
+       }
+
+       switch (rate) {
+       case ZD_OFDM_RATE_6M:
+       case ZD_OFDM_RATE_9M:
+               i += 3;
+               break;
+       case ZD_OFDM_RATE_12M:
+       case ZD_OFDM_RATE_18M:
+               i += 5;
+               break;
+       case ZD_OFDM_RATE_24M:
+       case ZD_OFDM_RATE_36M:
+               i += 9;
+               break;
+       case ZD_OFDM_RATE_48M:
+       case ZD_OFDM_RATE_54M:
+               i += 15;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return i;
+}
+
+static int ofdm_qual_percent(u8 status_quality, u8 rate, unsigned int size)
+{
+       int r;
+
+       r = ofdm_qual_db(status_quality, rate, size);
+       ZD_ASSERT(r >= 0);
+       if (r < 0)
+               r = 0;
+
+       r = (r * 100)/29;
+       return r <= 100 ? r : 100;
+}
+
+static unsigned int log10times100(unsigned int x)
+{
+       static const u8 log10[] = {
+                 0,
+                 0,   30,   47,   60,   69,   77,   84,   90,   95,  100,
+               104,  107,  111,  114,  117,  120,  123,  125,  127,  130,
+               132,  134,  136,  138,  139,  141,  143,  144,  146,  147,
+               149,  150,  151,  153,  154,  155,  156,  157,  159,  160,
+               161,  162,  163,  164,  165,  166,  167,  168,  169,  169,
+               170,  171,  172,  173,  174,  174,  175,  176,  177,  177,
+               178,  179,  179,  180,  181,  181,  182,  183,  183,  184,
+               185,  185,  186,  186,  187,  188,  188,  189,  189,  190,
+               190,  191,  191,  192,  192,  193,  193,  194,  194,  195,
+               195,  196,  196,  197,  197,  198,  198,  199,  199,  200,
+               200,  200,  201,  201,  202,  202,  202,  203,  203,  204,
+               204,  204,  205,  205,  206,  206,  206,  207,  207,  207,
+               208,  208,  208,  209,  209,  210,  210,  210,  211,  211,
+               211,  212,  212,  212,  213,  213,  213,  213,  214,  214,
+               214,  215,  215,  215,  216,  216,  216,  217,  217,  217,
+               217,  218,  218,  218,  219,  219,  219,  219,  220,  220,
+               220,  220,  221,  221,  221,  222,  222,  222,  222,  223,
+               223,  223,  223,  224,  224,  224,  224,
+       };
+
+       return x < ARRAY_SIZE(log10) ? log10[x] : 225;
+}
+
+enum {
+       MAX_CCK_EVM_DB = 45,
+};
+
+static int cck_evm_db(u8 status_quality)
+{
+       return (20 * log10times100(status_quality)) / 100;
+}
+
+static int cck_snr_db(u8 status_quality)
+{
+       int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality);
+       ZD_ASSERT(r >= 0);
+       return r;
+}
+
+static int cck_qual_percent(u8 status_quality)
+{
+       int r;
+
+       r = cck_snr_db(status_quality);
+       r = (100*r)/17;
+       return r <= 100 ? r : 100;
+}
+
+u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
+                     const struct rx_status *status)
+{
+       return (status->frame_status&ZD_RX_OFDM) ?
+               ofdm_qual_percent(status->signal_quality_ofdm,
+                                 zd_ofdm_plcp_header_rate(rx_frame),
+                                 size) :
+               cck_qual_percent(status->signal_quality_cck);
+}
+
+u8 zd_rx_strength_percent(u8 rssi)
+{
+       int r = (rssi*100) / 41;
+       if (r > 100)
+               r = 100;
+       return (u8) r;
+}
+
+u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
+{
+       static const u16 ofdm_rates[] = {
+               [ZD_OFDM_RATE_6M]  = 60,
+               [ZD_OFDM_RATE_9M]  = 90,
+               [ZD_OFDM_RATE_12M] = 120,
+               [ZD_OFDM_RATE_18M] = 180,
+               [ZD_OFDM_RATE_24M] = 240,
+               [ZD_OFDM_RATE_36M] = 360,
+               [ZD_OFDM_RATE_48M] = 480,
+               [ZD_OFDM_RATE_54M] = 540,
+       };
+       u16 rate;
+       if (status->frame_status & ZD_RX_OFDM) {
+               u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame);
+               rate = ofdm_rates[ofdm_rate & 0xf];
+       } else {
+               u8 cck_rate = zd_cck_plcp_header_rate(rx_frame);
+               switch (cck_rate) {
+               case ZD_CCK_SIGNAL_1M:
+                       rate = 10;
+                       break;
+               case ZD_CCK_SIGNAL_2M:
+                       rate = 20;
+                       break;
+               case ZD_CCK_SIGNAL_5M5:
+                       rate = 55;
+                       break;
+               case ZD_CCK_SIGNAL_11M:
+                       rate = 110;
+                       break;
+               default:
+                       rate = 0;
+               }
+       }
+
+       return rate;
+}
+
+int zd_chip_switch_radio_on(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_switch_radio_on(&chip->rf);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_switch_radio_off(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_switch_radio_off(&chip->rf);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_enable_int(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_usb_enable_int(&chip->usb);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+void zd_chip_disable_int(struct zd_chip *chip)
+{
+       mutex_lock(&chip->mutex);
+       zd_usb_disable_int(&chip->usb);
+       mutex_unlock(&chip->mutex);
+}
+
+int zd_chip_enable_rx(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_usb_enable_rx(&chip->usb);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+void zd_chip_disable_rx(struct zd_chip *chip)
+{
+       mutex_lock(&chip->mutex);
+       zd_usb_disable_rx(&chip->usb);
+       mutex_unlock(&chip->mutex);
+}
+
+int zd_rfwritev_locked(struct zd_chip *chip,
+                      const u32* values, unsigned int count, u8 bits)
+{
+       int r;
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               r = zd_rfwrite_locked(chip, values[i], bits);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
new file mode 100644 (file)
index 0000000..069d2b4
--- /dev/null
@@ -0,0 +1,827 @@
+/* zd_chip.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ZD_CHIP_H
+#define _ZD_CHIP_H
+
+#include "zd_types.h"
+#include "zd_rf.h"
+#include "zd_usb.h"
+
+/* Header for the Media Access Controller (MAC) and the Baseband Processor
+ * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and
+ * adds a processor for handling the USB protocol.
+ */
+
+/* 8-bit hardware registers */
+#define CR0   CTL_REG(0x0000)
+#define CR1   CTL_REG(0x0004)
+#define CR2   CTL_REG(0x0008)
+#define CR3   CTL_REG(0x000C)
+
+#define CR5   CTL_REG(0x0010)
+/*     bit 5: if set short preamble used
+ *     bit 6: filter band - Japan channel 14 on, else off
+ */
+#define CR6   CTL_REG(0x0014)
+#define CR7   CTL_REG(0x0018)
+#define CR8   CTL_REG(0x001C)
+
+#define CR4   CTL_REG(0x0020)
+
+#define CR9   CTL_REG(0x0024)
+/*     bit 2: antenna switch (together with CR10) */
+#define CR10  CTL_REG(0x0028)
+/*     bit 1: antenna switch (together with CR9)
+ *     RF2959 controls with CR11 radion on and off
+ */
+#define CR11  CTL_REG(0x002C)
+/*     bit 6:  TX power control for OFDM
+ *     RF2959 controls with CR10 radio on and off
+ */
+#define CR12  CTL_REG(0x0030)
+#define CR13  CTL_REG(0x0034)
+#define CR14  CTL_REG(0x0038)
+#define CR15  CTL_REG(0x003C)
+#define CR16  CTL_REG(0x0040)
+#define CR17  CTL_REG(0x0044)
+#define CR18  CTL_REG(0x0048)
+#define CR19  CTL_REG(0x004C)
+#define CR20  CTL_REG(0x0050)
+#define CR21  CTL_REG(0x0054)
+#define CR22  CTL_REG(0x0058)
+#define CR23  CTL_REG(0x005C)
+#define CR24  CTL_REG(0x0060)  /* CCA threshold */
+#define CR25  CTL_REG(0x0064)
+#define CR26  CTL_REG(0x0068)
+#define CR27  CTL_REG(0x006C)
+#define CR28  CTL_REG(0x0070)
+#define CR29  CTL_REG(0x0074)
+#define CR30  CTL_REG(0x0078)
+#define CR31  CTL_REG(0x007C)  /* TX power control for RF in CCK mode */
+#define CR32  CTL_REG(0x0080)
+#define CR33  CTL_REG(0x0084)
+#define CR34  CTL_REG(0x0088)
+#define CR35  CTL_REG(0x008C)
+#define CR36  CTL_REG(0x0090)
+#define CR37  CTL_REG(0x0094)
+#define CR38  CTL_REG(0x0098)
+#define CR39  CTL_REG(0x009C)
+#define CR40  CTL_REG(0x00A0)
+#define CR41  CTL_REG(0x00A4)
+#define CR42  CTL_REG(0x00A8)
+#define CR43  CTL_REG(0x00AC)
+#define CR44  CTL_REG(0x00B0)
+#define CR45  CTL_REG(0x00B4)
+#define CR46  CTL_REG(0x00B8)
+#define CR47  CTL_REG(0x00BC)  /* CCK baseband gain
+                                * (patch value might be in EEPROM)
+                                */
+#define CR48  CTL_REG(0x00C0)
+#define CR49  CTL_REG(0x00C4)
+#define CR50  CTL_REG(0x00C8)
+#define CR51  CTL_REG(0x00CC)  /* TX power control for RF in 6-36M modes */
+#define CR52  CTL_REG(0x00D0)  /* TX power control for RF in 48M mode */
+#define CR53  CTL_REG(0x00D4)  /* TX power control for RF in 54M mode */
+#define CR54  CTL_REG(0x00D8)
+#define CR55  CTL_REG(0x00DC)
+#define CR56  CTL_REG(0x00E0)
+#define CR57  CTL_REG(0x00E4)
+#define CR58  CTL_REG(0x00E8)
+#define CR59  CTL_REG(0x00EC)
+#define CR60  CTL_REG(0x00F0)
+#define CR61  CTL_REG(0x00F4)
+#define CR62  CTL_REG(0x00F8)
+#define CR63  CTL_REG(0x00FC)
+#define CR64  CTL_REG(0x0100)
+#define CR65  CTL_REG(0x0104) /* OFDM 54M calibration */
+#define CR66  CTL_REG(0x0108) /* OFDM 48M calibration */
+#define CR67  CTL_REG(0x010C) /* OFDM 36M calibration */
+#define CR68  CTL_REG(0x0110) /* CCK calibration */
+#define CR69  CTL_REG(0x0114)
+#define CR70  CTL_REG(0x0118)
+#define CR71  CTL_REG(0x011C)
+#define CR72  CTL_REG(0x0120)
+#define CR73  CTL_REG(0x0124)
+#define CR74  CTL_REG(0x0128)
+#define CR75  CTL_REG(0x012C)
+#define CR76  CTL_REG(0x0130)
+#define CR77  CTL_REG(0x0134)
+#define CR78  CTL_REG(0x0138)
+#define CR79  CTL_REG(0x013C)
+#define CR80  CTL_REG(0x0140)
+#define CR81  CTL_REG(0x0144)
+#define CR82  CTL_REG(0x0148)
+#define CR83  CTL_REG(0x014C)
+#define CR84  CTL_REG(0x0150)
+#define CR85  CTL_REG(0x0154)
+#define CR86  CTL_REG(0x0158)
+#define CR87  CTL_REG(0x015C)
+#define CR88  CTL_REG(0x0160)
+#define CR89  CTL_REG(0x0164)
+#define CR90  CTL_REG(0x0168)
+#define CR91  CTL_REG(0x016C)
+#define CR92  CTL_REG(0x0170)
+#define CR93  CTL_REG(0x0174)
+#define CR94  CTL_REG(0x0178)
+#define CR95  CTL_REG(0x017C)
+#define CR96  CTL_REG(0x0180)
+#define CR97  CTL_REG(0x0184)
+#define CR98  CTL_REG(0x0188)
+#define CR99  CTL_REG(0x018C)
+#define CR100 CTL_REG(0x0190)
+#define CR101 CTL_REG(0x0194)
+#define CR102 CTL_REG(0x0198)
+#define CR103 CTL_REG(0x019C)
+#define CR104 CTL_REG(0x01A0)
+#define CR105 CTL_REG(0x01A4)
+#define CR106 CTL_REG(0x01A8)
+#define CR107 CTL_REG(0x01AC)
+#define CR108 CTL_REG(0x01B0)
+#define CR109 CTL_REG(0x01B4)
+#define CR110 CTL_REG(0x01B8)
+#define CR111 CTL_REG(0x01BC)
+#define CR112 CTL_REG(0x01C0)
+#define CR113 CTL_REG(0x01C4)
+#define CR114 CTL_REG(0x01C8)
+#define CR115 CTL_REG(0x01CC)
+#define CR116 CTL_REG(0x01D0)
+#define CR117 CTL_REG(0x01D4)
+#define CR118 CTL_REG(0x01D8)
+#define CR119 CTL_REG(0x01DC)
+#define CR120 CTL_REG(0x01E0)
+#define CR121 CTL_REG(0x01E4)
+#define CR122 CTL_REG(0x01E8)
+#define CR123 CTL_REG(0x01EC)
+#define CR124 CTL_REG(0x01F0)
+#define CR125 CTL_REG(0x01F4)
+#define CR126 CTL_REG(0x01F8)
+#define CR127 CTL_REG(0x01FC)
+#define CR128 CTL_REG(0x0200)
+#define CR129 CTL_REG(0x0204)
+#define CR130 CTL_REG(0x0208)
+#define CR131 CTL_REG(0x020C)
+#define CR132 CTL_REG(0x0210)
+#define CR133 CTL_REG(0x0214)
+#define CR134 CTL_REG(0x0218)
+#define CR135 CTL_REG(0x021C)
+#define CR136 CTL_REG(0x0220)
+#define CR137 CTL_REG(0x0224)
+#define CR138 CTL_REG(0x0228)
+#define CR139 CTL_REG(0x022C)
+#define CR140 CTL_REG(0x0230)
+#define CR141 CTL_REG(0x0234)
+#define CR142 CTL_REG(0x0238)
+#define CR143 CTL_REG(0x023C)
+#define CR144 CTL_REG(0x0240)
+#define CR145 CTL_REG(0x0244)
+#define CR146 CTL_REG(0x0248)
+#define CR147 CTL_REG(0x024C)
+#define CR148 CTL_REG(0x0250)
+#define CR149 CTL_REG(0x0254)
+#define CR150 CTL_REG(0x0258)
+#define CR151 CTL_REG(0x025C)
+#define CR152 CTL_REG(0x0260)
+#define CR153 CTL_REG(0x0264)
+#define CR154 CTL_REG(0x0268)
+#define CR155 CTL_REG(0x026C)
+#define CR156 CTL_REG(0x0270)
+#define CR157 CTL_REG(0x0274)
+#define CR158 CTL_REG(0x0278)
+#define CR159 CTL_REG(0x027C)
+#define CR160 CTL_REG(0x0280)
+#define CR161 CTL_REG(0x0284)
+#define CR162 CTL_REG(0x0288)
+#define CR163 CTL_REG(0x028C)
+#define CR164 CTL_REG(0x0290)
+#define CR165 CTL_REG(0x0294)
+#define CR166 CTL_REG(0x0298)
+#define CR167 CTL_REG(0x029C)
+#define CR168 CTL_REG(0x02A0)
+#define CR169 CTL_REG(0x02A4)
+#define CR170 CTL_REG(0x02A8)
+#define CR171 CTL_REG(0x02AC)
+#define CR172 CTL_REG(0x02B0)
+#define CR173 CTL_REG(0x02B4)
+#define CR174 CTL_REG(0x02B8)
+#define CR175 CTL_REG(0x02BC)
+#define CR176 CTL_REG(0x02C0)
+#define CR177 CTL_REG(0x02C4)
+#define CR178 CTL_REG(0x02C8)
+#define CR179 CTL_REG(0x02CC)
+#define CR180 CTL_REG(0x02D0)
+#define CR181 CTL_REG(0x02D4)
+#define CR182 CTL_REG(0x02D8)
+#define CR183 CTL_REG(0x02DC)
+#define CR184 CTL_REG(0x02E0)
+#define CR185 CTL_REG(0x02E4)
+#define CR186 CTL_REG(0x02E8)
+#define CR187 CTL_REG(0x02EC)
+#define CR188 CTL_REG(0x02F0)
+#define CR189 CTL_REG(0x02F4)
+#define CR190 CTL_REG(0x02F8)
+#define CR191 CTL_REG(0x02FC)
+#define CR192 CTL_REG(0x0300)
+#define CR193 CTL_REG(0x0304)
+#define CR194 CTL_REG(0x0308)
+#define CR195 CTL_REG(0x030C)
+#define CR196 CTL_REG(0x0310)
+#define CR197 CTL_REG(0x0314)
+#define CR198 CTL_REG(0x0318)
+#define CR199 CTL_REG(0x031C)
+#define CR200 CTL_REG(0x0320)
+#define CR201 CTL_REG(0x0324)
+#define CR202 CTL_REG(0x0328)
+#define CR203 CTL_REG(0x032C)  /* I2C bus template value & flash control */
+#define CR204 CTL_REG(0x0330)
+#define CR205 CTL_REG(0x0334)
+#define CR206 CTL_REG(0x0338)
+#define CR207 CTL_REG(0x033C)
+#define CR208 CTL_REG(0x0340)
+#define CR209 CTL_REG(0x0344)
+#define CR210 CTL_REG(0x0348)
+#define CR211 CTL_REG(0x034C)
+#define CR212 CTL_REG(0x0350)
+#define CR213 CTL_REG(0x0354)
+#define CR214 CTL_REG(0x0358)
+#define CR215 CTL_REG(0x035C)
+#define CR216 CTL_REG(0x0360)
+#define CR217 CTL_REG(0x0364)
+#define CR218 CTL_REG(0x0368)
+#define CR219 CTL_REG(0x036C)
+#define CR220 CTL_REG(0x0370)
+#define CR221 CTL_REG(0x0374)
+#define CR222 CTL_REG(0x0378)
+#define CR223 CTL_REG(0x037C)
+#define CR224 CTL_REG(0x0380)
+#define CR225 CTL_REG(0x0384)
+#define CR226 CTL_REG(0x0388)
+#define CR227 CTL_REG(0x038C)
+#define CR228 CTL_REG(0x0390)
+#define CR229 CTL_REG(0x0394)
+#define CR230 CTL_REG(0x0398)
+#define CR231 CTL_REG(0x039C)
+#define CR232 CTL_REG(0x03A0)
+#define CR233 CTL_REG(0x03A4)
+#define CR234 CTL_REG(0x03A8)
+#define CR235 CTL_REG(0x03AC)
+#define CR236 CTL_REG(0x03B0)
+
+#define CR240 CTL_REG(0x03C0)
+/*     bit 7:  host-controlled RF register writes
+ * CR241-CR245: for hardware controlled writing of RF bits, not needed for
+ *              USB
+ */
+#define CR241 CTL_REG(0x03C4)
+#define CR242 CTL_REG(0x03C8)
+#define CR243 CTL_REG(0x03CC)
+#define CR244 CTL_REG(0x03D0)
+#define CR245 CTL_REG(0x03D4)
+
+#define CR251 CTL_REG(0x03EC)  /* only used for activation and deactivation of
+                                * Airoha RFs AL2230 and AL7230B
+                                */
+#define CR252 CTL_REG(0x03F0)
+#define CR253 CTL_REG(0x03F4)
+#define CR254 CTL_REG(0x03F8)
+#define CR255 CTL_REG(0x03FC)
+
+#define CR_MAX_PHY_REG 255
+
+/* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211
+ * driver.
+ */
+
+#define CR_RF_IF_CLK                   CTL_REG(0x0400)
+#define CR_RF_IF_DATA                  CTL_REG(0x0404)
+#define CR_PE1_PE2                     CTL_REG(0x0408)
+#define CR_PE2_DLY                     CTL_REG(0x040C)
+#define CR_LE1                         CTL_REG(0x0410)
+#define CR_LE2                         CTL_REG(0x0414)
+/* Seems to enable/disable GPI (General Purpose IO?) */
+#define CR_GPI_EN                      CTL_REG(0x0418)
+#define CR_RADIO_PD                    CTL_REG(0x042C)
+#define CR_RF2948_PD                   CTL_REG(0x042C)
+#define CR_ENABLE_PS_MANUAL_AGC                CTL_REG(0x043C)
+#define CR_CONFIG_PHILIPS              CTL_REG(0x0440)
+#define CR_SA2400_SER_AP               CTL_REG(0x0444)
+#define CR_I2C_WRITE                   CTL_REG(0x0444)
+#define CR_SA2400_SER_RP               CTL_REG(0x0448)
+#define CR_RADIO_PE                    CTL_REG(0x0458)
+#define CR_RST_BUS_MASTER              CTL_REG(0x045C)
+#define CR_RFCFG                       CTL_REG(0x0464)
+#define CR_HSTSCHG                     CTL_REG(0x046C)
+#define CR_PHY_ON                      CTL_REG(0x0474)
+#define CR_RX_DELAY                    CTL_REG(0x0478)
+#define CR_RX_PE_DELAY                 CTL_REG(0x047C)
+#define CR_GPIO_1                      CTL_REG(0x0490)
+#define CR_GPIO_2                      CTL_REG(0x0494)
+#define CR_EncryBufMux                 CTL_REG(0x04A8)
+#define CR_PS_CTRL                     CTL_REG(0x0500)
+#define CR_ADDA_PWR_DWN                        CTL_REG(0x0504)
+#define CR_ADDA_MBIAS_WARMTIME         CTL_REG(0x0508)
+#define CR_MAC_PS_STATE                        CTL_REG(0x050C)
+
+#define CR_INTERRUPT                   CTL_REG(0x0510)
+#define INT_TX_COMPLETE                        0x00000001
+#define INT_RX_COMPLETE                        0x00000002
+#define INT_RETRY_FAIL                 0x00000004
+#define INT_WAKEUP                     0x00000008
+#define INT_DTIM_NOTIFY                        0x00000020
+#define INT_CFG_NEXT_BCN               0x00000040
+#define INT_BUS_ABORT                  0x00000080
+#define INT_TX_FIFO_READY              0x00000100
+#define INT_UART                       0x00000200
+#define INT_TX_COMPLETE_EN             0x00010000
+#define INT_RX_COMPLETE_EN             0x00020000
+#define INT_RETRY_FAIL_EN              0x00040000
+#define INT_WAKEUP_EN                  0x00080000
+#define INT_DTIM_NOTIFY_EN             0x00200000
+#define INT_CFG_NEXT_BCN_EN            0x00400000
+#define INT_BUS_ABORT_EN               0x00800000
+#define INT_TX_FIFO_READY_EN           0x01000000
+#define INT_UART_EN                    0x02000000
+
+#define CR_TSF_LOW_PART                        CTL_REG(0x0514)
+#define CR_TSF_HIGH_PART               CTL_REG(0x0518)
+
+/* Following three values are in time units (1024us)
+ * Following condition must be met:
+ * atim < tbtt < bcn
+ */
+#define CR_ATIM_WND_PERIOD             CTL_REG(0x051C)
+#define CR_BCN_INTERVAL                        CTL_REG(0x0520)
+#define CR_PRE_TBTT                    CTL_REG(0x0524)
+/* in units of TU(1024us) */
+
+/* for UART support */
+#define CR_UART_RBR_THR_DLL            CTL_REG(0x0540)
+#define CR_UART_DLM_IER                        CTL_REG(0x0544)
+#define CR_UART_IIR_FCR                        CTL_REG(0x0548)
+#define CR_UART_LCR                    CTL_REG(0x054c)
+#define CR_UART_MCR                    CTL_REG(0x0550)
+#define CR_UART_LSR                    CTL_REG(0x0554)
+#define CR_UART_MSR                    CTL_REG(0x0558)
+#define CR_UART_ECR                    CTL_REG(0x055c)
+#define CR_UART_STATUS                 CTL_REG(0x0560)
+
+#define CR_PCI_TX_ADDR_P1              CTL_REG(0x0600)
+#define CR_PCI_TX_AddR_P2              CTL_REG(0x0604)
+#define CR_PCI_RX_AddR_P1              CTL_REG(0x0608)
+#define CR_PCI_RX_AddR_P2              CTL_REG(0x060C)
+
+/* must be overwritten if custom MAC address will be used */
+#define CR_MAC_ADDR_P1                 CTL_REG(0x0610)
+#define CR_MAC_ADDR_P2                 CTL_REG(0x0614)
+#define CR_BSSID_P1                    CTL_REG(0x0618)
+#define CR_BSSID_P2                    CTL_REG(0x061C)
+#define CR_BCN_PLCP_CFG                        CTL_REG(0x0620)
+#define CR_GROUP_HASH_P1               CTL_REG(0x0624)
+#define CR_GROUP_HASH_P2               CTL_REG(0x0628)
+#define CR_RX_TIMEOUT                  CTL_REG(0x062C)
+
+/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
+ * device will use a rate in this table that is less than or equal to the rate
+ * of the incoming frame which prompted the response */
+#define CR_BASIC_RATE_TBL              CTL_REG(0x0630)
+#define CR_RATE_1M     0x0001  /* 802.11b */
+#define CR_RATE_2M     0x0002  /* 802.11b */
+#define CR_RATE_5_5M   0x0004  /* 802.11b */
+#define CR_RATE_11M    0x0008  /* 802.11b */
+#define CR_RATE_6M      0x0100 /* 802.11g */
+#define CR_RATE_9M      0x0200 /* 802.11g */
+#define CR_RATE_12M    0x0400  /* 802.11g */
+#define CR_RATE_18M    0x0800  /* 802.11g */
+#define CR_RATE_24M     0x1000 /* 802.11g */
+#define CR_RATE_36M     0x2000 /* 802.11g */
+#define CR_RATE_48M     0x4000 /* 802.11g */
+#define CR_RATE_54M     0x8000 /* 802.11g */
+#define CR_RATES_80211G        0xff00
+#define CR_RATES_80211B        0x000f
+
+/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if
+ * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will
+ * look for a rate in this table that is less than or equal to the rate of
+ * the incoming frame. */
+#define CR_MANDATORY_RATE_TBL          CTL_REG(0x0634)
+#define CR_RTS_CTS_RATE                        CTL_REG(0x0638)
+
+#define CR_WEP_PROTECT                 CTL_REG(0x063C)
+#define CR_RX_THRESHOLD                        CTL_REG(0x0640)
+
+/* register for controlling the LEDS */
+#define CR_LED                         CTL_REG(0x0644)
+/* masks for controlling LEDs */
+#define LED1                           0x0100
+#define LED2                           0x0200
+
+/* Seems to indicate that the configuration is over.
+ */
+#define CR_AFTER_PNP                   CTL_REG(0x0648)
+#define CR_ACK_TIME_80211              CTL_REG(0x0658)
+
+#define CR_RX_OFFSET                   CTL_REG(0x065c)
+
+#define CR_PHY_DELAY                   CTL_REG(0x066C)
+#define CR_BCN_FIFO                    CTL_REG(0x0670)
+#define CR_SNIFFER_ON                  CTL_REG(0x0674)
+
+#define CR_ENCRYPTION_TYPE             CTL_REG(0x0678)
+#define NO_WEP                         0
+#define WEP64                          1
+#define WEP128                         5
+#define WEP256                         6
+#define ENC_SNIFFER                    8
+
+#define CR_ZD1211_RETRY_MAX            CTL_REG(0x067C)
+
+#define CR_REG1                                CTL_REG(0x0680)
+/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical
+ * registers, so one could argue it is a LOCK bit. But calling it
+ * LOCK_PHY_REGS makes it confusing.
+ */
+#define UNLOCK_PHY_REGS                        0x0080
+
+#define CR_DEVICE_STATE                        CTL_REG(0x0684)
+#define CR_UNDERRUN_CNT                        CTL_REG(0x0688)
+
+#define CR_RX_FILTER                   CTL_REG(0x068c)
+#define RX_FILTER_ASSOC_RESPONSE       0x0002
+#define RX_FILTER_REASSOC_RESPONSE     0x0008
+#define RX_FILTER_PROBE_RESPONSE       0x0020
+#define RX_FILTER_BEACON               0x0100
+#define RX_FILTER_DISASSOC             0x0400
+#define RX_FILTER_AUTH                 0x0800
+#define AP_RX_FILTER                   0x0400feff
+#define STA_RX_FILTER                  0x0000ffff
+
+/* Monitor mode sets filter to 0xfffff */
+
+#define CR_ACK_TIMEOUT_EXT             CTL_REG(0x0690)
+#define CR_BCN_FIFO_SEMAPHORE          CTL_REG(0x0694)
+#define CR_IFS_VALUE                   CTL_REG(0x0698)
+#define CR_RX_TIME_OUT                 CTL_REG(0x069C)
+#define CR_TOTAL_RX_FRM                        CTL_REG(0x06A0)
+#define CR_CRC32_CNT                   CTL_REG(0x06A4)
+#define CR_CRC16_CNT                   CTL_REG(0x06A8)
+#define CR_DECRYPTION_ERR_UNI          CTL_REG(0x06AC)
+#define CR_RX_FIFO_OVERRUN             CTL_REG(0x06B0)
+
+#define CR_DECRYPTION_ERR_MUL          CTL_REG(0x06BC)
+
+#define CR_NAV_CNT                     CTL_REG(0x06C4)
+#define CR_NAV_CCA                     CTL_REG(0x06C8)
+#define CR_RETRY_CNT                   CTL_REG(0x06CC)
+
+#define CR_READ_TCB_ADDR               CTL_REG(0x06E8)
+#define CR_READ_RFD_ADDR               CTL_REG(0x06EC)
+#define CR_CWMIN_CWMAX                 CTL_REG(0x06F0)
+#define CR_TOTAL_TX_FRM                        CTL_REG(0x06F4)
+
+/* CAM: Continuous Access Mode (power management) */
+#define CR_CAM_MODE                    CTL_REG(0x0700)
+#define CR_CAM_ROLL_TB_LOW             CTL_REG(0x0704)
+#define CR_CAM_ROLL_TB_HIGH            CTL_REG(0x0708)
+#define CR_CAM_ADDRESS                 CTL_REG(0x070C)
+#define CR_CAM_DATA                    CTL_REG(0x0710)
+
+#define CR_ROMDIR                      CTL_REG(0x0714)
+
+#define CR_DECRY_ERR_FLG_LOW           CTL_REG(0x0714)
+#define CR_DECRY_ERR_FLG_HIGH          CTL_REG(0x0718)
+
+#define CR_WEPKEY0                     CTL_REG(0x0720)
+#define CR_WEPKEY1                     CTL_REG(0x0724)
+#define CR_WEPKEY2                     CTL_REG(0x0728)
+#define CR_WEPKEY3                     CTL_REG(0x072C)
+#define CR_WEPKEY4                     CTL_REG(0x0730)
+#define CR_WEPKEY5                     CTL_REG(0x0734)
+#define CR_WEPKEY6                     CTL_REG(0x0738)
+#define CR_WEPKEY7                     CTL_REG(0x073C)
+#define CR_WEPKEY8                     CTL_REG(0x0740)
+#define CR_WEPKEY9                     CTL_REG(0x0744)
+#define CR_WEPKEY10                    CTL_REG(0x0748)
+#define CR_WEPKEY11                    CTL_REG(0x074C)
+#define CR_WEPKEY12                    CTL_REG(0x0750)
+#define CR_WEPKEY13                    CTL_REG(0x0754)
+#define CR_WEPKEY14                    CTL_REG(0x0758)
+#define CR_WEPKEY15                    CTL_REG(0x075c)
+#define CR_TKIP_MODE                   CTL_REG(0x0760)
+
+#define CR_EEPROM_PROTECT0             CTL_REG(0x0758)
+#define CR_EEPROM_PROTECT1             CTL_REG(0x075C)
+
+#define CR_DBG_FIFO_RD                 CTL_REG(0x0800)
+#define CR_DBG_SELECT                  CTL_REG(0x0804)
+#define CR_FIFO_Length                 CTL_REG(0x0808)
+
+
+#define CR_RSSI_MGC                    CTL_REG(0x0810)
+
+#define CR_PON                         CTL_REG(0x0818)
+#define CR_RX_ON                       CTL_REG(0x081C)
+#define CR_TX_ON                       CTL_REG(0x0820)
+#define CR_CHIP_EN                     CTL_REG(0x0824)
+#define CR_LO_SW                       CTL_REG(0x0828)
+#define CR_TXRX_SW                     CTL_REG(0x082C)
+#define CR_S_MD                                CTL_REG(0x0830)
+
+#define CR_USB_DEBUG_PORT              CTL_REG(0x0888)
+
+#define CR_ZD1211B_TX_PWR_CTL1         CTL_REG(0x0b00)
+#define CR_ZD1211B_TX_PWR_CTL2         CTL_REG(0x0b04)
+#define CR_ZD1211B_TX_PWR_CTL3         CTL_REG(0x0b08)
+#define CR_ZD1211B_TX_PWR_CTL4         CTL_REG(0x0b0c)
+#define CR_ZD1211B_AIFS_CTL1           CTL_REG(0x0b10)
+#define CR_ZD1211B_AIFS_CTL2           CTL_REG(0x0b14)
+#define CR_ZD1211B_TXOP                        CTL_REG(0x0b20)
+#define CR_ZD1211B_RETRY_MAX           CTL_REG(0x0b28)
+
+#define CWIN_SIZE                      0x007f043f
+
+
+#define HWINT_ENABLED                  0x004f0000
+#define HWINT_DISABLED                 0
+
+#define E2P_PWR_INT_GUARD              8
+#define E2P_CHANNEL_COUNT              14
+
+/* If you compare this addresses with the ZYDAS orignal driver, please notify
+ * that we use word mapping for the EEPROM.
+ */
+
+/*
+ * Upper 16 bit contains the regulatory domain.
+ */
+#define E2P_SUBID              E2P_REG(0x00)
+#define E2P_POD                        E2P_REG(0x02)
+#define E2P_MAC_ADDR_P1                E2P_REG(0x04)
+#define E2P_MAC_ADDR_P2                E2P_REG(0x06)
+#define E2P_PWR_CAL_VALUE1     E2P_REG(0x08)
+#define E2P_PWR_CAL_VALUE2     E2P_REG(0x0a)
+#define E2P_PWR_CAL_VALUE3     E2P_REG(0x0c)
+#define E2P_PWR_CAL_VALUE4      E2P_REG(0x0e)
+#define E2P_PWR_INT_VALUE1     E2P_REG(0x10)
+#define E2P_PWR_INT_VALUE2     E2P_REG(0x12)
+#define E2P_PWR_INT_VALUE3     E2P_REG(0x14)
+#define E2P_PWR_INT_VALUE4     E2P_REG(0x16)
+
+/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30)
+ * also only 11 channels. */
+#define E2P_ALLOWED_CHANNEL    E2P_REG(0x18)
+
+#define E2P_PHY_REG            E2P_REG(0x1a)
+#define E2P_DEVICE_VER         E2P_REG(0x20)
+#define E2P_36M_CAL_VALUE1     E2P_REG(0x28)
+#define E2P_36M_CAL_VALUE2      E2P_REG(0x2a)
+#define E2P_36M_CAL_VALUE3      E2P_REG(0x2c)
+#define E2P_36M_CAL_VALUE4     E2P_REG(0x2e)
+#define E2P_11A_INT_VALUE1     E2P_REG(0x30)
+#define E2P_11A_INT_VALUE2     E2P_REG(0x32)
+#define E2P_11A_INT_VALUE3     E2P_REG(0x34)
+#define E2P_11A_INT_VALUE4     E2P_REG(0x36)
+#define E2P_48M_CAL_VALUE1     E2P_REG(0x38)
+#define E2P_48M_CAL_VALUE2     E2P_REG(0x3a)
+#define E2P_48M_CAL_VALUE3     E2P_REG(0x3c)
+#define E2P_48M_CAL_VALUE4     E2P_REG(0x3e)
+#define E2P_48M_INT_VALUE1     E2P_REG(0x40)
+#define E2P_48M_INT_VALUE2     E2P_REG(0x42)
+#define E2P_48M_INT_VALUE3     E2P_REG(0x44)
+#define E2P_48M_INT_VALUE4     E2P_REG(0x46)
+#define E2P_54M_CAL_VALUE1     E2P_REG(0x48)   /* ??? */
+#define E2P_54M_CAL_VALUE2     E2P_REG(0x4a)
+#define E2P_54M_CAL_VALUE3     E2P_REG(0x4c)
+#define E2P_54M_CAL_VALUE4     E2P_REG(0x4e)
+#define E2P_54M_INT_VALUE1     E2P_REG(0x50)
+#define E2P_54M_INT_VALUE2     E2P_REG(0x52)
+#define E2P_54M_INT_VALUE3     E2P_REG(0x54)
+#define E2P_54M_INT_VALUE4     E2P_REG(0x56)
+
+/* All 16 bit values */
+#define FW_FIRMWARE_VER         FW_REG(0)
+/* non-zero if USB high speed connection */
+#define FW_USB_SPEED            FW_REG(1)
+#define FW_FIX_TX_RATE          FW_REG(2)
+/* Seems to be able to control LEDs over the firmware */
+#define FW_LINK_STATUS          FW_REG(3)
+#define FW_SOFT_RESET           FW_REG(4)
+#define FW_FLASH_CHK            FW_REG(5)
+
+enum {
+       CR_BASE_OFFSET                  = 0x9000,
+       FW_START_OFFSET                 = 0xee00,
+       FW_BASE_ADDR_OFFSET             = FW_START_OFFSET + 0x1d,
+       EEPROM_START_OFFSET             = 0xf800,
+       EEPROM_SIZE                     = 0x800, /* words */
+       LOAD_CODE_SIZE                  = 0xe, /* words */
+       LOAD_VECT_SIZE                  = 0x10000 - 0xfff7, /* words */
+       EEPROM_REGS_OFFSET              = LOAD_CODE_SIZE + LOAD_VECT_SIZE,
+       E2P_BASE_OFFSET                 = EEPROM_START_OFFSET +
+                                         EEPROM_REGS_OFFSET,
+};
+
+#define FW_REG_TABLE_ADDR      USB_ADDR(FW_START_OFFSET + 0x1d)
+
+enum {
+       /* indices for ofdm_cal_values */
+       OFDM_36M_INDEX = 0,
+       OFDM_48M_INDEX = 1,
+       OFDM_54M_INDEX = 2,
+};
+
+struct zd_chip {
+       struct zd_usb usb;
+       struct zd_rf rf;
+       struct mutex mutex;
+       u8 e2p_mac[ETH_ALEN];
+       /* EepSetPoint in the vendor driver */
+       u8 pwr_cal_values[E2P_CHANNEL_COUNT];
+       /* integration values in the vendor driver */
+       u8 pwr_int_values[E2P_CHANNEL_COUNT];
+       /* SetPointOFDM in the vendor driver */
+       u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
+       u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
+          is_zd1211b:1;
+};
+
+static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
+{
+       return container_of(usb, struct zd_chip, usb);
+}
+
+static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
+{
+       return container_of(rf, struct zd_chip, rf);
+}
+
+#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
+
+void zd_chip_init(struct zd_chip *chip,
+                struct net_device *netdev,
+                struct usb_interface *intf);
+void zd_chip_clear(struct zd_chip *chip);
+int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
+int zd_chip_reset(struct zd_chip *chip);
+
+static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
+                                     const zd_addr_t *addresses,
+                                     unsigned int count)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_usb_ioread16v(&chip->usb, values, addresses, count);
+}
+
+static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value,
+                                    const zd_addr_t addr)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_usb_ioread16(&chip->usb, value, addr);
+}
+
+int zd_ioread32v_locked(struct zd_chip *chip, u32 *values,
+                       const zd_addr_t *addresses, unsigned int count);
+
+static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value,
+                                    const zd_addr_t addr)
+{
+       return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1);
+}
+
+static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value,
+                                     zd_addr_t addr)
+{
+       struct zd_ioreq16 ioreq;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       ioreq.addr = addr;
+       ioreq.value = value;
+
+       return zd_usb_iowrite16v(&chip->usb, &ioreq, 1);
+}
+
+int zd_iowrite16a_locked(struct zd_chip *chip,
+                         const struct zd_ioreq16 *ioreqs, unsigned int count);
+
+int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                         unsigned int count);
+
+static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value,
+                                     zd_addr_t addr)
+{
+       struct zd_ioreq32 ioreq;
+
+       ioreq.addr = addr;
+       ioreq.value = value;
+
+       return _zd_iowrite32v_locked(chip, &ioreq, 1);
+}
+
+int zd_iowrite32a_locked(struct zd_chip *chip,
+                        const struct zd_ioreq32 *ioreqs, unsigned int count);
+
+static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_usb_rfwrite(&chip->usb, value, bits);
+}
+
+int zd_rfwritev_locked(struct zd_chip *chip,
+                      const u32* values, unsigned int count, u8 bits);
+
+/* Locking functions for reading and writing registers.
+ * The different parameters are intentional.
+ */
+int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value);
+int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value);
+int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value);
+int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value);
+int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
+                 u32 *values, unsigned int count);
+int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                  unsigned int count);
+
+int zd_chip_set_channel(struct zd_chip *chip, u8 channel);
+static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
+{
+       return chip->rf.channel;
+}
+u8  zd_chip_get_channel(struct zd_chip *chip);
+int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
+void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
+int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
+int zd_chip_switch_radio_on(struct zd_chip *chip);
+int zd_chip_switch_radio_off(struct zd_chip *chip);
+int zd_chip_enable_int(struct zd_chip *chip);
+void zd_chip_disable_int(struct zd_chip *chip);
+int zd_chip_enable_rx(struct zd_chip *chip);
+void zd_chip_disable_rx(struct zd_chip *chip);
+int zd_chip_enable_hwint(struct zd_chip *chip);
+int zd_chip_disable_hwint(struct zd_chip *chip);
+
+static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
+{
+       return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type);
+}
+
+static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type)
+{
+       return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type);
+}
+
+static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
+{
+       return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
+}
+
+int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
+
+static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter)
+{
+       return zd_iowrite32(chip, CR_RX_FILTER, filter);
+}
+
+int zd_chip_lock_phy_regs(struct zd_chip *chip);
+int zd_chip_unlock_phy_regs(struct zd_chip *chip);
+
+enum led_status {
+       LED_OFF    = 0,
+       LED_ON     = 1,
+       LED_FLIP   = 2,
+       LED_STATUS = 3,
+};
+
+int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status);
+int zd_chip_led_flip(struct zd_chip *chip, int led,
+                    const unsigned int *phases_msecs, unsigned int count);
+
+int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
+
+static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
+{
+       return zd_ioread32(chip, CR_BCN_INTERVAL, interval);
+}
+
+struct rx_status;
+
+u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
+                      const struct rx_status *status);
+u8 zd_rx_strength_percent(u8 rssi);
+
+u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
+
+#endif /* _ZD_CHIP_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
new file mode 100644 (file)
index 0000000..4659068
--- /dev/null
@@ -0,0 +1,48 @@
+/* zd_def.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ZD_DEF_H
+#define _ZD_DEF_H
+
+#include <linux/kernel.h>
+#include <linux/stringify.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#define dev_printk_f(level, dev, fmt, args...) \
+       dev_printk(level, dev, "%s() " fmt, __func__, ##args)
+
+#ifdef DEBUG
+#  define dev_dbg_f(dev, fmt, args...) \
+         dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
+#else
+#  define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
+#endif /* DEBUG */
+
+#ifdef DEBUG
+#  define ZD_ASSERT(x) \
+do { \
+       if (!(x)) { \
+               pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
+                       __FILE__, __LINE__, __stringify(x)); \
+       } \
+} while (0)
+#else
+#  define ZD_ASSERT(x) do { } while (0)
+#endif
+
+#endif /* _ZD_DEF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
new file mode 100644 (file)
index 0000000..66905f7
--- /dev/null
@@ -0,0 +1,191 @@
+/* zd_ieee80211.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * A lot of this code is generic and should be moved into the upper layers
+ * at some point.
+ */
+
+#include <linux/errno.h>
+#include <linux/wireless.h>
+#include <linux/kernel.h>
+#include <net/ieee80211.h>
+
+#include "zd_def.h"
+#include "zd_ieee80211.h"
+#include "zd_mac.h"
+
+static const struct channel_range channel_ranges[] = {
+       [0]                      = { 0,  0},
+       [ZD_REGDOMAIN_FCC]       = { 1, 12},
+       [ZD_REGDOMAIN_IC]        = { 1, 12},
+       [ZD_REGDOMAIN_ETSI]      = { 1, 14},
+       [ZD_REGDOMAIN_JAPAN]     = { 1, 14},
+       [ZD_REGDOMAIN_SPAIN]     = { 1, 14},
+       [ZD_REGDOMAIN_FRANCE]    = { 1, 14},
+       [ZD_REGDOMAIN_JAPAN_ADD] = {14, 15},
+};
+
+const struct channel_range *zd_channel_range(u8 regdomain)
+{
+       if (regdomain >= ARRAY_SIZE(channel_ranges))
+               regdomain = 0;
+       return &channel_ranges[regdomain];
+}
+
+int zd_regdomain_supports_channel(u8 regdomain, u8 channel)
+{
+       const struct channel_range *range = zd_channel_range(regdomain);
+       return range->start <= channel && channel < range->end;
+}
+
+int zd_regdomain_supported(u8 regdomain)
+{
+       const struct channel_range *range = zd_channel_range(regdomain);
+       return range->start != 0;
+}
+
+/* Stores channel frequencies in MHz. */
+static const u16 channel_frequencies[] = {
+       2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447,
+       2452, 2457, 2462, 2467, 2472, 2484,
+};
+
+#define NUM_CHANNELS ARRAY_SIZE(channel_frequencies)
+
+static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz)
+{
+       u32 factor;
+
+       freq->e = 0;
+       if (mhz >= 1000000000U) {
+               pr_debug("zd1211 mhz %u to large\n", mhz);
+               freq->m = 0;
+               return -EINVAL;
+       }
+
+       factor = 1000;
+       while (mhz >= factor) {
+
+               freq->e += 1;
+               factor *= 10;
+       }
+
+       factor /= 1000U;
+       freq->m = mhz * (1000000U/factor) + hz/factor;
+
+       return 0;
+}
+
+int zd_channel_to_freq(struct iw_freq *freq, u8 channel)
+{
+       if (channel > NUM_CHANNELS) {
+               freq->m = 0;
+               freq->e = 0;
+               return -EINVAL;
+       }
+       if (!channel) {
+               freq->m = 0;
+               freq->e = 0;
+               return -EINVAL;
+       }
+       return compute_freq(freq, channel_frequencies[channel-1], 0);
+}
+
+static int freq_to_mhz(const struct iw_freq *freq)
+{
+       u32 factor;
+       int e;
+
+       /* Such high frequencies are not supported. */
+       if (freq->e > 6)
+               return -EINVAL;
+
+       factor = 1;
+       for (e = freq->e; e > 0; --e) {
+               factor *= 10;
+       }
+       factor = 1000000U / factor;
+
+       if (freq->m % factor) {
+               return -EINVAL;
+       }
+
+       return freq->m / factor;
+}
+
+int zd_find_channel(u8 *channel, const struct iw_freq *freq)
+{
+       int i, r;
+       u32 mhz;
+
+       if (!(freq->flags & IW_FREQ_FIXED))
+               return 0;
+
+       if (freq->m < 1000) {
+               if (freq->m  > NUM_CHANNELS || freq->m == 0)
+                       return -EINVAL;
+               *channel = freq->m;
+               return 1;
+       }
+
+       r = freq_to_mhz(freq);
+       if (r < 0)
+               return r;
+       mhz = r;
+
+       for (i = 0; i < NUM_CHANNELS; i++) {
+               if (mhz == channel_frequencies[i]) {
+                       *channel = i+1;
+                       return 1;
+               }
+       }
+
+       return -EINVAL;
+}
+
+int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain)
+{
+       struct ieee80211_geo geo;
+       const struct channel_range *range;
+       int i;
+       u8 channel;
+
+       dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)),
+               "regdomain %#04x\n", regdomain);
+
+       range = zd_channel_range(regdomain);
+       if (range->start == 0) {
+               dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)),
+                       "zd1211 regdomain %#04x not supported\n",
+                       regdomain);
+               return -EINVAL;
+       }
+
+       memset(&geo, 0, sizeof(geo));
+
+       for (i = 0, channel = range->start; channel < range->end; channel++) {
+               struct ieee80211_channel *chan = &geo.bg[i++];
+               chan->freq = channel_frequencies[channel - 1];
+               chan->channel = channel;
+       }
+
+       geo.bg_channels = i;
+       memcpy(geo.name, "XX ", 4);
+       ieee80211_set_geo(ieee, &geo);
+       return 0;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
new file mode 100644 (file)
index 0000000..3632989
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef _ZD_IEEE80211_H
+#define _ZD_IEEE80211_H
+
+#include <net/ieee80211.h>
+#include "zd_types.h"
+
+/* Additional definitions from the standards.
+ */
+
+#define ZD_REGDOMAIN_FCC       0x10
+#define ZD_REGDOMAIN_IC                0x20
+#define ZD_REGDOMAIN_ETSI      0x30
+#define ZD_REGDOMAIN_SPAIN     0x31
+#define ZD_REGDOMAIN_FRANCE    0x32
+#define ZD_REGDOMAIN_JAPAN_ADD 0x40
+#define ZD_REGDOMAIN_JAPAN     0x41
+
+enum {
+       MIN_CHANNEL24 = 1,
+       MAX_CHANNEL24 = 14,
+};
+
+struct channel_range {
+       u8 start;
+       u8 end; /* exclusive (channel must be less than end) */
+};
+
+struct iw_freq;
+
+int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain);
+
+const struct channel_range *zd_channel_range(u8 regdomain);
+int zd_regdomain_supports_channel(u8 regdomain, u8 channel);
+int zd_regdomain_supported(u8 regdomain);
+
+/* for 2.4 GHz band */
+int zd_channel_to_freq(struct iw_freq *freq, u8 channel);
+int zd_find_channel(u8 *channel, const struct iw_freq *freq);
+
+#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
+
+struct ofdm_plcp_header {
+       u8 prefix[3];
+       __le16 service;
+} __attribute__((packed));
+
+static inline u8 zd_ofdm_plcp_header_rate(
+       const struct ofdm_plcp_header *header)
+{
+       return header->prefix[0] & 0xf;
+}
+
+#define ZD_OFDM_RATE_6M                0xb
+#define ZD_OFDM_RATE_9M                0xf
+#define ZD_OFDM_RATE_12M       0xa
+#define ZD_OFDM_RATE_18M       0xe
+#define ZD_OFDM_RATE_24M       0x9
+#define ZD_OFDM_RATE_36M       0xd
+#define ZD_OFDM_RATE_48M       0x8
+#define ZD_OFDM_RATE_54M       0xc
+
+struct cck_plcp_header {
+       u8 signal;
+       u8 service;
+       __le16 length;
+       __le16 crc16;
+} __attribute__((packed));
+
+static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header)
+{
+       return header->signal;
+}
+
+#define ZD_CCK_SIGNAL_1M       0x0a
+#define ZD_CCK_SIGNAL_2M       0x14
+#define ZD_CCK_SIGNAL_5M5      0x37
+#define ZD_CCK_SIGNAL_11M      0x6e
+
+enum ieee80211_std {
+       IEEE80211B = 0x01,
+       IEEE80211A = 0x02,
+       IEEE80211G = 0x04,
+};
+
+#endif /* _ZD_IEEE80211_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
new file mode 100644 (file)
index 0000000..a9bd80a
--- /dev/null
@@ -0,0 +1,1084 @@
+/* zd_mac.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/usb.h>
+#include <linux/jiffies.h>
+#include <net/ieee80211_radiotap.h>
+
+#include "zd_def.h"
+#include "zd_chip.h"
+#include "zd_mac.h"
+#include "zd_ieee80211.h"
+#include "zd_netdev.h"
+#include "zd_rf.h"
+#include "zd_util.h"
+
+static void ieee_init(struct ieee80211_device *ieee);
+static void softmac_init(struct ieee80211softmac_device *sm);
+
+int zd_mac_init(struct zd_mac *mac,
+               struct net_device *netdev,
+               struct usb_interface *intf)
+{
+       struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev);
+
+       memset(mac, 0, sizeof(*mac));
+       spin_lock_init(&mac->lock);
+       mac->netdev = netdev;
+
+       ieee_init(ieee);
+       softmac_init(ieee80211_priv(netdev));
+       zd_chip_init(&mac->chip, netdev, intf);
+       return 0;
+}
+
+static int reset_channel(struct zd_mac *mac)
+{
+       int r;
+       unsigned long flags;
+       const struct channel_range *range;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       range = zd_channel_range(mac->regdomain);
+       if (!range->start) {
+               r = -EINVAL;
+               goto out;
+       }
+       mac->requested_channel = range->start;
+       r = 0;
+out:
+       spin_unlock_irqrestore(&mac->lock, flags);
+       return r;
+}
+
+int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
+{
+       int r;
+       struct zd_chip *chip = &mac->chip;
+       u8 addr[ETH_ALEN];
+       u8 default_regdomain;
+
+       r = zd_chip_enable_int(chip);
+       if (r)
+               goto out;
+       r = zd_chip_init_hw(chip, device_type);
+       if (r)
+               goto disable_int;
+
+       zd_get_e2p_mac_addr(chip, addr);
+       r = zd_write_mac_addr(chip, addr);
+       if (r)
+               goto disable_int;
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&mac->lock);
+       memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
+       spin_unlock_irq(&mac->lock);
+
+       r = zd_read_regdomain(chip, &default_regdomain);
+       if (r)
+               goto disable_int;
+       if (!zd_regdomain_supported(default_regdomain)) {
+               dev_dbg_f(zd_mac_dev(mac),
+                         "Regulatory Domain %#04x is not supported.\n",
+                         default_regdomain);
+               r = -EINVAL;
+               goto disable_int;
+       }
+       spin_lock_irq(&mac->lock);
+       mac->regdomain = mac->default_regdomain = default_regdomain;
+       spin_unlock_irq(&mac->lock);
+       r = reset_channel(mac);
+       if (r)
+               goto disable_int;
+
+       /* We must inform the device that we are doing encryption/decryption in
+        * software at the moment. */
+       r = zd_set_encryption_type(chip, ENC_SNIFFER);
+       if (r)
+               goto disable_int;
+
+       r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain);
+       if (r)
+               goto disable_int;
+
+       r = 0;
+disable_int:
+       zd_chip_disable_int(chip);
+out:
+       return r;
+}
+
+void zd_mac_clear(struct zd_mac *mac)
+{
+       /* Aquire the lock. */
+       spin_lock(&mac->lock);
+       spin_unlock(&mac->lock);
+       zd_chip_clear(&mac->chip);
+       memset(mac, 0, sizeof(*mac));
+}
+
+static int reset_mode(struct zd_mac *mac)
+{
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+       struct zd_ioreq32 ioreqs[3] = {
+               { CR_RX_FILTER, STA_RX_FILTER },
+               { CR_SNIFFER_ON, 0U },
+       };
+
+       if (ieee->iw_mode == IW_MODE_MONITOR) {
+               ioreqs[0].value = 0xffffffff;
+               ioreqs[1].value = 0x1;
+               ioreqs[2].value = ENC_SNIFFER;
+       }
+
+       return zd_iowrite32a(&mac->chip, ioreqs, 3);
+}
+
+int zd_mac_open(struct net_device *netdev)
+{
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+       struct zd_chip *chip = &mac->chip;
+       int r;
+
+       r = zd_chip_enable_int(chip);
+       if (r < 0)
+               goto out;
+
+       r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
+       if (r < 0)
+               goto disable_int;
+       r = reset_mode(mac);
+       if (r)
+               goto disable_int;
+       r = zd_chip_switch_radio_on(chip);
+       if (r < 0)
+               goto disable_int;
+       r = zd_chip_set_channel(chip, mac->requested_channel);
+       if (r < 0)
+               goto disable_radio;
+       r = zd_chip_enable_rx(chip);
+       if (r < 0)
+               goto disable_radio;
+       r = zd_chip_enable_hwint(chip);
+       if (r < 0)
+               goto disable_rx;
+
+       ieee80211softmac_start(netdev);
+       return 0;
+disable_rx:
+       zd_chip_disable_rx(chip);
+disable_radio:
+       zd_chip_switch_radio_off(chip);
+disable_int:
+       zd_chip_disable_int(chip);
+out:
+       return r;
+}
+
+int zd_mac_stop(struct net_device *netdev)
+{
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+       struct zd_chip *chip = &mac->chip;
+
+       netif_stop_queue(netdev);
+
+       /*
+        * The order here deliberately is a little different from the open()
+        * method, since we need to make sure there is no opportunity for RX
+        * frames to be processed by softmac after we have stopped it.
+        */
+
+       zd_chip_disable_rx(chip);
+       ieee80211softmac_stop(netdev);
+
+       zd_chip_disable_hwint(chip);
+       zd_chip_switch_radio_off(chip);
+       zd_chip_disable_int(chip);
+
+       return 0;
+}
+
+int zd_mac_set_mac_address(struct net_device *netdev, void *p)
+{
+       int r;
+       unsigned long flags;
+       struct sockaddr *addr = p;
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+       struct zd_chip *chip = &mac->chip;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       dev_dbg_f(zd_mac_dev(mac),
+                 "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data));
+
+       r = zd_write_mac_addr(chip, addr->sa_data);
+       if (r)
+               return r;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
+       spin_unlock_irqrestore(&mac->lock, flags);
+
+       return 0;
+}
+
+int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain)
+{
+       int r;
+       u8 channel;
+
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&mac->lock);
+       if (regdomain == 0) {
+               regdomain = mac->default_regdomain;
+       }
+       if (!zd_regdomain_supported(regdomain)) {
+               spin_unlock_irq(&mac->lock);
+               return -EINVAL;
+       }
+       mac->regdomain = regdomain;
+       channel = mac->requested_channel;
+       spin_unlock_irq(&mac->lock);
+
+       r = zd_geo_init(zd_mac_to_ieee80211(mac), regdomain);
+       if (r)
+               return r;
+       if (!zd_regdomain_supports_channel(regdomain, channel)) {
+               r = reset_channel(mac);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+u8 zd_mac_get_regdomain(struct zd_mac *mac)
+{
+       unsigned long flags;
+       u8 regdomain;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       regdomain = mac->regdomain;
+       spin_unlock_irqrestore(&mac->lock, flags);
+       return regdomain;
+}
+
+static void set_channel(struct net_device *netdev, u8 channel)
+{
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+
+       dev_dbg_f(zd_mac_dev(mac), "channel %d\n", channel);
+
+       zd_chip_set_channel(&mac->chip, channel);
+}
+
+/* TODO: Should not work in Managed mode. */
+int zd_mac_request_channel(struct zd_mac *mac, u8 channel)
+{
+       unsigned long lock_flags;
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+       if (ieee->iw_mode == IW_MODE_INFRA)
+               return -EPERM;
+
+       spin_lock_irqsave(&mac->lock, lock_flags);
+       if (!zd_regdomain_supports_channel(mac->regdomain, channel)) {
+               spin_unlock_irqrestore(&mac->lock, lock_flags);
+               return -EINVAL;
+       }
+       mac->requested_channel = channel;
+       spin_unlock_irqrestore(&mac->lock, lock_flags);
+       if (netif_running(mac->netdev))
+               return zd_chip_set_channel(&mac->chip, channel);
+       else
+               return 0;
+}
+
+int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags)
+{
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+       *channel = zd_chip_get_channel(&mac->chip);
+       if (ieee->iw_mode != IW_MODE_INFRA) {
+               spin_lock_irq(&mac->lock);
+               *flags = *channel == mac->requested_channel ?
+                       MAC_FIXED_CHANNEL : 0;
+               spin_unlock(&mac->lock);
+       } else {
+               *flags = 0;
+       }
+       dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags);
+       return 0;
+}
+
+/* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */
+static u8 cs_typed_rate(u8 cs_rate)
+{
+       static const u8 typed_rates[16] = {
+               [ZD_CS_CCK_RATE_1M]     = ZD_CS_CCK|ZD_CS_CCK_RATE_1M,
+               [ZD_CS_CCK_RATE_2M]     = ZD_CS_CCK|ZD_CS_CCK_RATE_2M,
+               [ZD_CS_CCK_RATE_5_5M]   = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M,
+               [ZD_CS_CCK_RATE_11M]    = ZD_CS_CCK|ZD_CS_CCK_RATE_11M,
+               [ZD_OFDM_RATE_6M]       = ZD_CS_OFDM|ZD_OFDM_RATE_6M,
+               [ZD_OFDM_RATE_9M]       = ZD_CS_OFDM|ZD_OFDM_RATE_9M,
+               [ZD_OFDM_RATE_12M]      = ZD_CS_OFDM|ZD_OFDM_RATE_12M,
+               [ZD_OFDM_RATE_18M]      = ZD_CS_OFDM|ZD_OFDM_RATE_18M,
+               [ZD_OFDM_RATE_24M]      = ZD_CS_OFDM|ZD_OFDM_RATE_24M,
+               [ZD_OFDM_RATE_36M]      = ZD_CS_OFDM|ZD_OFDM_RATE_36M,
+               [ZD_OFDM_RATE_48M]      = ZD_CS_OFDM|ZD_OFDM_RATE_48M,
+               [ZD_OFDM_RATE_54M]      = ZD_CS_OFDM|ZD_OFDM_RATE_54M,
+       };
+
+       ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f);
+       return typed_rates[cs_rate & ZD_CS_RATE_MASK];
+}
+
+/* Fallback to lowest rate, if rate is unknown. */
+static u8 rate_to_cs_rate(u8 rate)
+{
+       switch (rate) {
+       case IEEE80211_CCK_RATE_2MB:
+               return ZD_CS_CCK_RATE_2M;
+       case IEEE80211_CCK_RATE_5MB:
+               return ZD_CS_CCK_RATE_5_5M;
+       case IEEE80211_CCK_RATE_11MB:
+               return ZD_CS_CCK_RATE_11M;
+       case IEEE80211_OFDM_RATE_6MB:
+               return ZD_OFDM_RATE_6M;
+       case IEEE80211_OFDM_RATE_9MB:
+               return ZD_OFDM_RATE_9M;
+       case IEEE80211_OFDM_RATE_12MB:
+               return ZD_OFDM_RATE_12M;
+       case IEEE80211_OFDM_RATE_18MB:
+               return ZD_OFDM_RATE_18M;
+       case IEEE80211_OFDM_RATE_24MB:
+               return ZD_OFDM_RATE_24M;
+       case IEEE80211_OFDM_RATE_36MB:
+               return ZD_OFDM_RATE_36M;
+       case IEEE80211_OFDM_RATE_48MB:
+               return ZD_OFDM_RATE_48M;
+       case IEEE80211_OFDM_RATE_54MB:
+               return ZD_OFDM_RATE_54M;
+       }
+       return ZD_CS_CCK_RATE_1M;
+}
+
+int zd_mac_set_mode(struct zd_mac *mac, u32 mode)
+{
+       struct ieee80211_device *ieee;
+
+       switch (mode) {
+       case IW_MODE_AUTO:
+       case IW_MODE_ADHOC:
+       case IW_MODE_INFRA:
+               mac->netdev->type = ARPHRD_ETHER;
+               break;
+       case IW_MODE_MONITOR:
+               mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP;
+               break;
+       default:
+               dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode);
+               return -EINVAL;
+       }
+
+       ieee = zd_mac_to_ieee80211(mac);
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&ieee->lock);
+       ieee->iw_mode = mode;
+       spin_unlock_irq(&ieee->lock);
+
+       if (netif_running(mac->netdev))
+               return reset_mode(mac);
+
+       return 0;
+}
+
+int zd_mac_get_mode(struct zd_mac *mac, u32 *mode)
+{
+       unsigned long flags;
+       struct ieee80211_device *ieee;
+
+       ieee = zd_mac_to_ieee80211(mac);
+       spin_lock_irqsave(&ieee->lock, flags);
+       *mode = ieee->iw_mode;
+       spin_unlock_irqrestore(&ieee->lock, flags);
+       return 0;
+}
+
+int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range)
+{
+       int i;
+       const struct channel_range *channel_range;
+       u8 regdomain;
+
+       memset(range, 0, sizeof(*range));
+
+       /* FIXME: Not so important and depends on the mode. For 802.11g
+        * usually this value is used. It seems to be that Bit/s number is
+        * given here.
+        */
+       range->throughput = 27 * 1000 * 1000;
+
+       range->max_qual.qual = 100;
+       range->max_qual.level = 100;
+
+       /* FIXME: Needs still to be tuned. */
+       range->avg_qual.qual = 71;
+       range->avg_qual.level = 80;
+
+       /* FIXME: depends on standard? */
+       range->min_rts = 256;
+       range->max_rts = 2346;
+
+       range->min_frag = MIN_FRAG_THRESHOLD;
+       range->max_frag = MAX_FRAG_THRESHOLD;
+
+       range->max_encoding_tokens = WEP_KEYS;
+       range->num_encoding_sizes = 2;
+       range->encoding_size[0] = 5;
+       range->encoding_size[1] = WEP_KEY_LEN;
+
+       range->we_version_compiled = WIRELESS_EXT;
+       range->we_version_source = 20;
+
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&mac->lock);
+       regdomain = mac->regdomain;
+       spin_unlock_irq(&mac->lock);
+       channel_range = zd_channel_range(regdomain);
+
+       range->num_channels = channel_range->end - channel_range->start;
+       range->old_num_channels = range->num_channels;
+       range->num_frequency = range->num_channels;
+       range->old_num_frequency = range->num_frequency;
+
+       for (i = 0; i < range->num_frequency; i++) {
+               struct iw_freq *freq = &range->freq[i];
+               freq->i = channel_range->start + i;
+               zd_channel_to_freq(freq, freq->i);
+       }
+
+       return 0;
+}
+
+static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length)
+{
+       static const u8 rate_divisor[] = {
+               [ZD_CS_CCK_RATE_1M]     =  1,
+               [ZD_CS_CCK_RATE_2M]     =  2,
+               [ZD_CS_CCK_RATE_5_5M]   = 11, /* bits must be doubled */
+               [ZD_CS_CCK_RATE_11M]    = 11,
+               [ZD_OFDM_RATE_6M]       =  6,
+               [ZD_OFDM_RATE_9M]       =  9,
+               [ZD_OFDM_RATE_12M]      = 12,
+               [ZD_OFDM_RATE_18M]      = 18,
+               [ZD_OFDM_RATE_24M]      = 24,
+               [ZD_OFDM_RATE_36M]      = 36,
+               [ZD_OFDM_RATE_48M]      = 48,
+               [ZD_OFDM_RATE_54M]      = 54,
+       };
+
+       u32 bits = (u32)tx_length * 8;
+       u32 divisor;
+
+       divisor = rate_divisor[cs_rate];
+       if (divisor == 0)
+               return -EINVAL;
+
+       switch (cs_rate) {
+       case ZD_CS_CCK_RATE_5_5M:
+               bits = (2*bits) + 10; /* round up to the next integer */
+               break;
+       case ZD_CS_CCK_RATE_11M:
+               if (service) {
+                       u32 t = bits % 11;
+                       *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION;
+                       if (0 < t && t <= 3) {
+                               *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION;
+                       }
+               }
+               bits += 10; /* round up to the next integer */
+               break;
+       }
+
+       return bits/divisor;
+}
+
+enum {
+       R2M_SHORT_PREAMBLE = 0x01,
+       R2M_11A            = 0x02,
+};
+
+static u8 cs_rate_to_modulation(u8 cs_rate, int flags)
+{
+       u8 modulation;
+
+       modulation = cs_typed_rate(cs_rate);
+       if (flags & R2M_SHORT_PREAMBLE) {
+               switch (ZD_CS_RATE(modulation)) {
+               case ZD_CS_CCK_RATE_2M:
+               case ZD_CS_CCK_RATE_5_5M:
+               case ZD_CS_CCK_RATE_11M:
+                       modulation |= ZD_CS_CCK_PREA_SHORT;
+                       return modulation;
+               }
+       }
+       if (flags & R2M_11A) {
+               if (ZD_CS_TYPE(modulation) == ZD_CS_OFDM)
+                       modulation |= ZD_CS_OFDM_MODE_11A;
+       }
+       return modulation;
+}
+
+static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs,
+                             struct ieee80211_hdr_4addr *hdr)
+{
+       struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
+       u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl));
+       u8 rate, cs_rate;
+       int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0;
+
+       /* FIXME: 802.11a? short preamble? */
+       rate = ieee80211softmac_suggest_txrate(softmac,
+               is_multicast_ether_addr(hdr->addr1), is_mgt);
+
+       cs_rate = rate_to_cs_rate(rate);
+       cs->modulation = cs_rate_to_modulation(cs_rate, 0);
+}
+
+static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
+                          struct ieee80211_hdr_4addr *header)
+{
+       unsigned int tx_length = le16_to_cpu(cs->tx_length);
+       u16 fctl = le16_to_cpu(header->frame_ctl);
+       u16 ftype = WLAN_FC_GET_TYPE(fctl);
+       u16 stype = WLAN_FC_GET_STYPE(fctl);
+
+       /*
+        * CONTROL:
+        * - start at 0x00
+        * - if fragment 0, enable bit 0
+        * - if backoff needed, enable bit 0
+        * - if burst (backoff not needed) disable bit 0
+        * - if multicast, enable bit 1
+        * - if PS-POLL frame, enable bit 2
+        * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable
+        *   bit 4 (FIXME: wtf)
+        * - if frag_len > RTS threshold, set bit 5 as long if it isnt
+        *   multicast or mgt
+        * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit
+        *   7
+        */
+
+       cs->control = 0;
+
+       /* First fragment */
+       if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0)
+               cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
+
+       /* Multicast */
+       if (is_multicast_ether_addr(header->addr1))
+               cs->control |= ZD_CS_MULTICAST;
+
+       /* PS-POLL */
+       if (stype == IEEE80211_STYPE_PSPOLL)
+               cs->control |= ZD_CS_PS_POLL_FRAME;
+
+       if (!is_multicast_ether_addr(header->addr1) &&
+           ftype != IEEE80211_FTYPE_MGMT &&
+           tx_length > zd_netdev_ieee80211(mac->netdev)->rts)
+       {
+               /* FIXME: check the logic */
+               if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) {
+                       /* 802.11g */
+                       cs->control |= ZD_CS_SELF_CTS;
+               } else { /* 802.11b */
+                       cs->control |= ZD_CS_RTS;
+               }
+       }
+
+       /* FIXME: Management frame? */
+}
+
+static int fill_ctrlset(struct zd_mac *mac,
+                       struct ieee80211_txb *txb,
+                       int frag_num)
+{
+       int r;
+       struct sk_buff *skb = txb->fragments[frag_num];
+       struct ieee80211_hdr_4addr *hdr =
+               (struct ieee80211_hdr_4addr *) skb->data;
+       unsigned int frag_len = skb->len + IEEE80211_FCS_LEN;
+       unsigned int next_frag_len;
+       unsigned int packet_length;
+       struct zd_ctrlset *cs = (struct zd_ctrlset *)
+               skb_push(skb, sizeof(struct zd_ctrlset));
+
+       if (frag_num+1  < txb->nr_frags) {
+               next_frag_len = txb->fragments[frag_num+1]->len +
+                               IEEE80211_FCS_LEN;
+       } else {
+               next_frag_len = 0;
+       }
+       ZD_ASSERT(frag_len <= 0xffff);
+       ZD_ASSERT(next_frag_len <= 0xffff);
+
+       cs_set_modulation(mac, cs, hdr);
+
+       cs->tx_length = cpu_to_le16(frag_len);
+
+       cs_set_control(mac, cs, hdr);
+
+       packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
+       ZD_ASSERT(packet_length <= 0xffff);
+       /* ZD1211B: Computing the length difference this way, gives us
+        * flexibility to compute the packet length.
+        */
+       cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ?
+                       packet_length - frag_len : packet_length);
+
+       /*
+        * CURRENT LENGTH:
+        * - transmit frame length in microseconds
+        * - seems to be derived from frame length
+        * - see Cal_Us_Service() in zdinlinef.h
+        * - if macp->bTxBurstEnable is enabled, then multiply by 4
+        *  - bTxBurstEnable is never set in the vendor driver
+        *
+        * SERVICE:
+        * - "for PLCP configuration"
+        * - always 0 except in some situations at 802.11b 11M
+        * - see line 53 of zdinlinef.h
+        */
+       cs->service = 0;
+       r = zd_calc_tx_length_us(&cs->service, ZD_CS_RATE(cs->modulation),
+                                le16_to_cpu(cs->tx_length));
+       if (r < 0)
+               return r;
+       cs->current_length = cpu_to_le16(r);
+
+       if (next_frag_len == 0) {
+               cs->next_frame_length = 0;
+       } else {
+               r = zd_calc_tx_length_us(NULL, ZD_CS_RATE(cs->modulation),
+                                        next_frag_len);
+               if (r < 0)
+                       return r;
+               cs->next_frame_length = cpu_to_le16(r);
+       }
+
+       return 0;
+}
+
+static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
+{
+       int i, r;
+
+       for (i = 0; i < txb->nr_frags; i++) {
+               struct sk_buff *skb = txb->fragments[i];
+
+               r = fill_ctrlset(mac, txb, i);
+               if (r)
+                       return r;
+               r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
+               if (r)
+                       return r;
+       }
+
+       /* FIXME: shouldn't this be handled by the upper layers? */
+       mac->netdev->trans_start = jiffies;
+
+       ieee80211_txb_free(txb);
+       return 0;
+}
+
+struct zd_rt_hdr {
+       struct ieee80211_radiotap_header rt_hdr;
+       u8  rt_flags;
+       u8  rt_rate;
+       u16 rt_channel;
+       u16 rt_chbitmask;
+} __attribute__((packed));
+
+static void fill_rt_header(void *buffer, struct zd_mac *mac,
+                          const struct ieee80211_rx_stats *stats,
+                          const struct rx_status *status)
+{
+       struct zd_rt_hdr *hdr = buffer;
+
+       hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+       hdr->rt_hdr.it_pad = 0;
+       hdr->rt_hdr.it_len = cpu_to_le16(sizeof(struct zd_rt_hdr));
+       hdr->rt_hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
+                                (1 << IEEE80211_RADIOTAP_CHANNEL) |
+                                (1 << IEEE80211_RADIOTAP_RATE));
+
+       hdr->rt_flags = 0;
+       if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256))
+               hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP;
+
+       hdr->rt_rate = stats->rate / 5;
+
+       /* FIXME: 802.11a */
+       hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz(
+                                            _zd_chip_get_channel(&mac->chip)));
+       hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ |
+               ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) ==
+               ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK));
+}
+
+/* Returns 1 if the data packet is for us and 0 otherwise. */
+static int is_data_packet_for_us(struct ieee80211_device *ieee,
+                                struct ieee80211_hdr_4addr *hdr)
+{
+       struct net_device *netdev = ieee->dev;
+       u16 fc = le16_to_cpu(hdr->frame_ctl);
+
+       ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA);
+
+       switch (ieee->iw_mode) {
+       case IW_MODE_ADHOC:
+               if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 ||
+                   memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0)
+                       return 0;
+               break;
+       case IW_MODE_AUTO:
+       case IW_MODE_INFRA:
+               if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) !=
+                   IEEE80211_FCTL_FROMDS ||
+                   memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0)
+                       return 0;
+               break;
+       default:
+               ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR);
+               return 0;
+       }
+
+       return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 ||
+              is_multicast_ether_addr(hdr->addr1) ||
+              (netdev->flags & IFF_PROMISC);
+}
+
+/* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0
+ * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is
+ * called here.
+ *
+ * It has been based on ieee80211_rx_any.
+ */
+static int filter_rx(struct ieee80211_device *ieee,
+                    const u8 *buffer, unsigned int length,
+                    struct ieee80211_rx_stats *stats)
+{
+       struct ieee80211_hdr_4addr *hdr;
+       u16 fc;
+
+       if (ieee->iw_mode == IW_MODE_MONITOR)
+               return 1;
+
+       hdr = (struct ieee80211_hdr_4addr *)buffer;
+       fc = le16_to_cpu(hdr->frame_ctl);
+       if ((fc & IEEE80211_FCTL_VERS) != 0)
+               return -EINVAL;
+
+       switch (WLAN_FC_GET_TYPE(fc)) {
+       case IEEE80211_FTYPE_MGMT:
+               if (length < sizeof(struct ieee80211_hdr_3addr))
+                       return -EINVAL;
+               ieee80211_rx_mgt(ieee, hdr, stats);
+               return 0;
+       case IEEE80211_FTYPE_CTL:
+               /* Ignore invalid short buffers */
+               return 0;
+       case IEEE80211_FTYPE_DATA:
+               if (length < sizeof(struct ieee80211_hdr_3addr))
+                       return -EINVAL;
+               return is_data_packet_for_us(ieee, hdr);
+       }
+
+       return -EINVAL;
+}
+
+static void update_qual_rssi(struct zd_mac *mac,
+                            const u8 *buffer, unsigned int length,
+                            u8 qual_percent, u8 rssi_percent)
+{
+       unsigned long flags;
+       struct ieee80211_hdr_3addr *hdr;
+       int i;
+
+       hdr = (struct ieee80211_hdr_3addr *)buffer;
+       if (length < offsetof(struct ieee80211_hdr_3addr, addr3))
+               return;
+       if (memcmp(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid, ETH_ALEN) != 0)
+               return;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       i = mac->stats_count % ZD_MAC_STATS_BUFFER_SIZE;
+       mac->qual_buffer[i] = qual_percent;
+       mac->rssi_buffer[i] = rssi_percent;
+       mac->stats_count++;
+       spin_unlock_irqrestore(&mac->lock, flags);
+}
+
+static int fill_rx_stats(struct ieee80211_rx_stats *stats,
+                        const struct rx_status **pstatus,
+                        struct zd_mac *mac,
+                        const u8 *buffer, unsigned int length)
+{
+       const struct rx_status *status;
+
+       *pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
+       if (status->frame_status & ZD_RX_ERROR) {
+               /* FIXME: update? */
+               return -EINVAL;
+       }
+       memset(stats, 0, sizeof(struct ieee80211_rx_stats));
+       stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
+                              + sizeof(struct rx_status));
+       /* FIXME: 802.11a */
+       stats->freq = IEEE80211_24GHZ_BAND;
+       stats->received_channel = _zd_chip_get_channel(&mac->chip);
+       stats->rssi = zd_rx_strength_percent(status->signal_strength);
+       stats->signal = zd_rx_qual_percent(buffer,
+                                         length - sizeof(struct rx_status),
+                                         status);
+       stats->mask = IEEE80211_STATMASK_RSSI | IEEE80211_STATMASK_SIGNAL;
+       stats->rate = zd_rx_rate(buffer, status);
+       if (stats->rate)
+               stats->mask |= IEEE80211_STATMASK_RATE;
+
+       return 0;
+}
+
+int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length)
+{
+       int r;
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+       struct ieee80211_rx_stats stats;
+       const struct rx_status *status;
+       struct sk_buff *skb;
+
+       if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
+                    IEEE80211_FCS_LEN + sizeof(struct rx_status))
+               return -EINVAL;
+
+       r = fill_rx_stats(&stats, &status, mac, buffer, length);
+       if (r)
+               return r;
+
+       length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+
+                 sizeof(struct rx_status);
+       buffer += ZD_PLCP_HEADER_SIZE;
+
+       update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi);
+
+       r = filter_rx(ieee, buffer, length, &stats);
+       if (r <= 0)
+               return r;
+
+       skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
+       if (!skb)
+               return -ENOMEM;
+       if (ieee->iw_mode == IW_MODE_MONITOR)
+               fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac,
+                              &stats, status);
+       memcpy(skb_put(skb, length), buffer, length);
+
+       r = ieee80211_rx(ieee, skb, &stats);
+       if (!r) {
+               ZD_ASSERT(in_irq());
+               dev_kfree_skb_irq(skb);
+       }
+       return 0;
+}
+
+static int netdev_tx(struct ieee80211_txb *txb, struct net_device *netdev,
+                    int pri)
+{
+       return zd_mac_tx(zd_netdev_mac(netdev), txb, pri);
+}
+
+static void set_security(struct net_device *netdev,
+                        struct ieee80211_security *sec)
+{
+       struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev);
+       struct ieee80211_security *secinfo = &ieee->sec;
+       int keyidx;
+
+       dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
+
+       for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
+               if (sec->flags & (1<<keyidx)) {
+                       secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
+                       secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
+                       memcpy(secinfo->keys[keyidx], sec->keys[keyidx],
+                              SCM_KEY_LEN);
+               }
+
+       if (sec->flags & SEC_ACTIVE_KEY) {
+               secinfo->active_key = sec->active_key;
+               dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
+                       "   .active_key = %d\n", sec->active_key);
+       }
+       if (sec->flags & SEC_UNICAST_GROUP) {
+               secinfo->unicast_uses_group = sec->unicast_uses_group;
+               dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
+                       "   .unicast_uses_group = %d\n",
+                       sec->unicast_uses_group);
+       }
+       if (sec->flags & SEC_LEVEL) {
+               secinfo->level = sec->level;
+               dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
+                       "   .level = %d\n", sec->level);
+       }
+       if (sec->flags & SEC_ENABLED) {
+               secinfo->enabled = sec->enabled;
+               dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
+                       "   .enabled = %d\n", sec->enabled);
+       }
+       if (sec->flags & SEC_ENCRYPT) {
+               secinfo->encrypt = sec->encrypt;
+               dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
+                       "   .encrypt = %d\n", sec->encrypt);
+       }
+       if (sec->flags & SEC_AUTH_MODE) {
+               secinfo->auth_mode = sec->auth_mode;
+               dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
+                       "   .auth_mode = %d\n", sec->auth_mode);
+       }
+}
+
+static void ieee_init(struct ieee80211_device *ieee)
+{
+       ieee->mode = IEEE_B | IEEE_G;
+       ieee->freq_band = IEEE80211_24GHZ_BAND;
+       ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION;
+       ieee->tx_headroom = sizeof(struct zd_ctrlset);
+       ieee->set_security = set_security;
+       ieee->hard_start_xmit = netdev_tx;
+
+       /* Software encryption/decryption for now */
+       ieee->host_build_iv = 0;
+       ieee->host_encrypt = 1;
+       ieee->host_decrypt = 1;
+
+       /* FIXME: default to managed mode, until ieee80211 and zd1211rw can
+        * correctly support AUTO */
+       ieee->iw_mode = IW_MODE_INFRA;
+}
+
+static void softmac_init(struct ieee80211softmac_device *sm)
+{
+       sm->set_channel = set_channel;
+}
+
+struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev)
+{
+       struct zd_mac *mac = zd_netdev_mac(ndev);
+       struct iw_statistics *iw_stats = &mac->iw_stats;
+       unsigned int i, count, qual_total, rssi_total;
+
+       memset(iw_stats, 0, sizeof(struct iw_statistics));
+       /* We are not setting the status, because ieee->state is not updated
+        * at all and this driver doesn't track authentication state.
+        */
+       spin_lock_irq(&mac->lock);
+       count = mac->stats_count < ZD_MAC_STATS_BUFFER_SIZE ?
+               mac->stats_count : ZD_MAC_STATS_BUFFER_SIZE;
+       qual_total = rssi_total = 0;
+       for (i = 0; i < count; i++) {
+               qual_total += mac->qual_buffer[i];
+               rssi_total += mac->rssi_buffer[i];
+       }
+       spin_unlock_irq(&mac->lock);
+       iw_stats->qual.updated = IW_QUAL_NOISE_INVALID;
+       if (count > 0) {
+               iw_stats->qual.qual = qual_total / count;
+               iw_stats->qual.level = rssi_total / count;
+               iw_stats->qual.updated |=
+                       IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED;
+       } else {
+               iw_stats->qual.updated |=
+                       IW_QUAL_QUAL_INVALID|IW_QUAL_LEVEL_INVALID;
+       }
+       /* TODO: update counter */
+       return iw_stats;
+}
+
+#ifdef DEBUG
+static const char* decryption_types[] = {
+       [ZD_RX_NO_WEP] = "none",
+       [ZD_RX_WEP64] = "WEP64",
+       [ZD_RX_TKIP] = "TKIP",
+       [ZD_RX_AES] = "AES",
+       [ZD_RX_WEP128] = "WEP128",
+       [ZD_RX_WEP256] = "WEP256",
+};
+
+static const char *decryption_type_string(u8 type)
+{
+       const char *s;
+
+       if (type < ARRAY_SIZE(decryption_types)) {
+               s = decryption_types[type];
+       } else {
+               s = NULL;
+       }
+       return s ? s : "unknown";
+}
+
+static int is_ofdm(u8 frame_status)
+{
+       return (frame_status & ZD_RX_OFDM);
+}
+
+void zd_dump_rx_status(const struct rx_status *status)
+{
+       const char* modulation;
+       u8 quality;
+
+       if (is_ofdm(status->frame_status)) {
+               modulation = "ofdm";
+               quality = status->signal_quality_ofdm;
+       } else {
+               modulation = "cck";
+               quality = status->signal_quality_cck;
+       }
+       pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n",
+               modulation, status->signal_strength, quality,
+               decryption_type_string(status->decryption_type));
+       if (status->frame_status & ZD_RX_ERROR) {
+               pr_debug("rx error %s%s%s%s%s%s\n",
+                       (status->frame_status & ZD_RX_TIMEOUT_ERROR) ?
+                               "timeout " : "",
+                       (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ?
+                               "fifo " : "",
+                       (status->frame_status & ZD_RX_DECRYPTION_ERROR) ?
+                               "decryption " : "",
+                       (status->frame_status & ZD_RX_CRC32_ERROR) ?
+                               "crc32 " : "",
+                       (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ?
+                               "addr1 " : "",
+                       (status->frame_status & ZD_RX_CRC16_ERROR) ?
+                               "crc16" : "");
+       }
+}
+#endif /* DEBUG */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
new file mode 100644 (file)
index 0000000..b3ba49b
--- /dev/null
@@ -0,0 +1,193 @@
+/* zd_mac.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ZD_MAC_H
+#define _ZD_MAC_H
+
+#include <linux/wireless.h>
+#include <linux/kernel.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211softmac.h>
+
+#include "zd_chip.h"
+#include "zd_netdev.h"
+
+struct zd_ctrlset {
+       u8     modulation;
+       __le16 tx_length;
+       u8     control;
+       /* stores only the difference to tx_length on ZD1211B */
+       __le16 packet_length;
+       __le16 current_length;
+       u8     service;
+       __le16  next_frame_length;
+} __attribute__((packed));
+
+#define ZD_CS_RESERVED_SIZE    25
+
+/* zd_crtlset field modulation */
+#define ZD_CS_RATE_MASK                0x0f
+#define ZD_CS_TYPE_MASK                0x10
+#define ZD_CS_RATE(modulation) ((modulation) & ZD_CS_RATE_MASK)
+#define ZD_CS_TYPE(modulation) ((modulation) & ZD_CS_TYPE_MASK)
+
+#define ZD_CS_CCK              0x00
+#define ZD_CS_OFDM             0x10
+
+#define ZD_CS_CCK_RATE_1M      0x00
+#define ZD_CS_CCK_RATE_2M      0x01
+#define ZD_CS_CCK_RATE_5_5M    0x02
+#define ZD_CS_CCK_RATE_11M     0x03
+/* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*.
+ */
+
+/* bit 5 is preamble (when in CCK mode), or a/g selection (when in OFDM mode) */
+#define ZD_CS_CCK_PREA_LONG    0x00
+#define ZD_CS_CCK_PREA_SHORT   0x20
+#define ZD_CS_OFDM_MODE_11G    0x00
+#define ZD_CS_OFDM_MODE_11A    0x20
+
+/* zd_ctrlset control field */
+#define ZD_CS_NEED_RANDOM_BACKOFF      0x01
+#define ZD_CS_MULTICAST                        0x02
+
+#define ZD_CS_FRAME_TYPE_MASK          0x0c
+#define ZD_CS_DATA_FRAME               0x00
+#define ZD_CS_PS_POLL_FRAME            0x04
+#define ZD_CS_MANAGEMENT_FRAME         0x08
+#define ZD_CS_NO_SEQUENCE_CTL_FRAME    0x0c
+
+#define ZD_CS_WAKE_DESTINATION         0x10
+#define ZD_CS_RTS                      0x20
+#define ZD_CS_ENCRYPT                  0x40
+#define ZD_CS_SELF_CTS                 0x80
+
+/* Incoming frames are prepended by a PLCP header */
+#define ZD_PLCP_HEADER_SIZE            5
+
+struct rx_length_info {
+       __le16 length[3];
+       __le16 tag;
+} __attribute__((packed));
+
+#define RX_LENGTH_INFO_TAG             0x697e
+
+struct rx_status {
+       u8 signal_quality_cck;
+       /* rssi */
+       u8 signal_strength;
+       u8 signal_quality_ofdm;
+       u8 decryption_type;
+       u8 frame_status;
+} __attribute__((packed));
+
+/* rx_status field decryption_type */
+#define ZD_RX_NO_WEP   0
+#define ZD_RX_WEP64    1
+#define ZD_RX_TKIP     2
+#define ZD_RX_AES      4
+#define ZD_RX_WEP128   5
+#define ZD_RX_WEP256   6
+
+/* rx_status field frame_status */
+#define ZD_RX_FRAME_MODULATION_MASK    0x01
+#define ZD_RX_CCK                      0x00
+#define ZD_RX_OFDM                     0x01
+
+#define ZD_RX_TIMEOUT_ERROR            0x02
+#define ZD_RX_FIFO_OVERRUN_ERROR       0x04
+#define ZD_RX_DECRYPTION_ERROR         0x08
+#define ZD_RX_CRC32_ERROR              0x10
+#define ZD_RX_NO_ADDR1_MATCH_ERROR     0x20
+#define ZD_RX_CRC16_ERROR              0x40
+#define ZD_RX_ERROR                    0x80
+
+enum mac_flags {
+       MAC_FIXED_CHANNEL = 0x01,
+};
+
+#define ZD_MAC_STATS_BUFFER_SIZE 16
+
+struct zd_mac {
+       struct net_device *netdev;
+       struct zd_chip chip;
+       spinlock_t lock;
+       /* Unlocked reading possible */
+       struct iw_statistics iw_stats;
+       unsigned int stats_count;
+       u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
+       u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
+       u8 regdomain;
+       u8 default_regdomain;
+       u8 requested_channel;
+};
+
+static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac)
+{
+       return zd_netdev_ieee80211(mac->netdev);
+}
+
+static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev)
+{
+       return ieee80211softmac_priv(netdev);
+}
+
+static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip)
+{
+       return container_of(chip, struct zd_mac, chip);
+}
+
+static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb)
+{
+       return zd_chip_to_mac(zd_usb_to_chip(usb));
+}
+
+#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip))
+
+int zd_mac_init(struct zd_mac *mac,
+                struct net_device *netdev,
+               struct usb_interface *intf);
+void zd_mac_clear(struct zd_mac *mac);
+
+int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
+
+int zd_mac_open(struct net_device *netdev);
+int zd_mac_stop(struct net_device *netdev);
+int zd_mac_set_mac_address(struct net_device *dev, void *p);
+
+int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
+
+int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
+u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
+
+int zd_mac_request_channel(struct zd_mac *mac, u8 channel);
+int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags);
+
+int zd_mac_set_mode(struct zd_mac *mac, u32 mode);
+int zd_mac_get_mode(struct zd_mac *mac, u32 *mode);
+
+int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range);
+
+struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev);
+
+#ifdef DEBUG
+void zd_dump_rx_status(const struct rx_status *status);
+#else
+#define zd_dump_rx_status(status)
+#endif /* DEBUG */
+
+#endif /* _ZD_MAC_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
new file mode 100644 (file)
index 0000000..9df232c
--- /dev/null
@@ -0,0 +1,267 @@
+/* zd_netdev.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211softmac.h>
+#include <net/ieee80211softmac_wx.h>
+#include <net/iw_handler.h>
+
+#include "zd_def.h"
+#include "zd_netdev.h"
+#include "zd_mac.h"
+#include "zd_ieee80211.h"
+
+/* Region 0 means reset regdomain to default. */
+static int zd_set_regdomain(struct net_device *netdev,
+                           struct iw_request_info *info,
+                           union iwreq_data *req, char *extra)
+{
+       const u8 *regdomain = (u8 *)req;
+       return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain);
+}
+
+static int zd_get_regdomain(struct net_device *netdev,
+                           struct iw_request_info *info,
+                           union iwreq_data *req, char *extra)
+{
+       u8 *regdomain = (u8 *)req;
+       if (!regdomain)
+               return -EINVAL;
+       *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev));
+       return 0;
+}
+
+static const struct iw_priv_args zd_priv_args[] = {
+       {
+               .cmd = ZD_PRIV_SET_REGDOMAIN,
+               .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
+               .name = "set_regdomain",
+       },
+       {
+               .cmd = ZD_PRIV_GET_REGDOMAIN,
+               .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
+               .name = "get_regdomain",
+       },
+};
+
+#define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV]
+
+static const iw_handler zd_priv_handler[] = {
+       PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain,
+       PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain,
+};
+
+static int iw_get_name(struct net_device *netdev,
+                      struct iw_request_info *info,
+                      union iwreq_data *req, char *extra)
+{
+       /* FIXME: check whether 802.11a will also supported, add also
+        *        zd1211B, if we support it.
+        */
+       strlcpy(req->name, "802.11g zd1211", IFNAMSIZ);
+       return 0;
+}
+
+static int iw_set_freq(struct net_device *netdev,
+                      struct iw_request_info *info,
+                      union iwreq_data *req, char *extra)
+{
+       int r;
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+       struct iw_freq *freq = &req->freq;
+       u8 channel;
+
+       r = zd_find_channel(&channel, freq);
+       if (r < 0)
+               return r;
+       r = zd_mac_request_channel(mac, channel);
+       return r;
+}
+
+static int iw_get_freq(struct net_device *netdev,
+                  struct iw_request_info *info,
+                  union iwreq_data *req, char *extra)
+{
+       int r;
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+       struct iw_freq *freq = &req->freq;
+       u8 channel;
+       u8 flags;
+
+       r = zd_mac_get_channel(mac, &channel, &flags);
+       if (r)
+               return r;
+
+       freq->flags = (flags & MAC_FIXED_CHANNEL) ?
+                     IW_FREQ_FIXED : IW_FREQ_AUTO;
+       dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
+                 (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
+       return zd_channel_to_freq(freq, channel);
+}
+
+static int iw_set_mode(struct net_device *netdev,
+                      struct iw_request_info *info,
+                      union iwreq_data *req, char *extra)
+{
+       return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
+}
+
+static int iw_get_mode(struct net_device *netdev,
+                      struct iw_request_info *info,
+                      union iwreq_data *req, char *extra)
+{
+       return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
+}
+
+static int iw_get_range(struct net_device *netdev,
+                      struct iw_request_info *info,
+                      union iwreq_data *req, char *extra)
+{
+       struct iw_range *range = (struct iw_range *)extra;
+
+       dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
+       req->data.length = sizeof(*range);
+       return zd_mac_get_range(zd_netdev_mac(netdev), range);
+}
+
+static int iw_set_encode(struct net_device *netdev,
+                        struct iw_request_info *info,
+                        union iwreq_data *data,
+                        char *extra)
+{
+       return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
+               data, extra);
+}
+
+static int iw_get_encode(struct net_device *netdev,
+                        struct iw_request_info *info,
+                        union iwreq_data *data,
+                        char *extra)
+{
+       return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
+               data, extra);
+}
+
+static int iw_set_encodeext(struct net_device *netdev,
+                        struct iw_request_info *info,
+                        union iwreq_data *data,
+                        char *extra)
+{
+       return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
+               data, extra);
+}
+
+static int iw_get_encodeext(struct net_device *netdev,
+                        struct iw_request_info *info,
+                        union iwreq_data *data,
+                        char *extra)
+{
+       return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
+               data, extra);
+}
+
+#define WX(x) [(x)-SIOCIWFIRST]
+
+static const iw_handler zd_standard_iw_handlers[] = {
+       WX(SIOCGIWNAME)         = iw_get_name,
+       WX(SIOCSIWFREQ)         = iw_set_freq,
+       WX(SIOCGIWFREQ)         = iw_get_freq,
+       WX(SIOCSIWMODE)         = iw_set_mode,
+       WX(SIOCGIWMODE)         = iw_get_mode,
+       WX(SIOCGIWRANGE)        = iw_get_range,
+       WX(SIOCSIWENCODE)       = iw_set_encode,
+       WX(SIOCGIWENCODE)       = iw_get_encode,
+       WX(SIOCSIWENCODEEXT)    = iw_set_encodeext,
+       WX(SIOCGIWENCODEEXT)    = iw_get_encodeext,
+       WX(SIOCSIWAUTH)         = ieee80211_wx_set_auth,
+       WX(SIOCGIWAUTH)         = ieee80211_wx_get_auth,
+       WX(SIOCSIWSCAN)         = ieee80211softmac_wx_trigger_scan,
+       WX(SIOCGIWSCAN)         = ieee80211softmac_wx_get_scan_results,
+       WX(SIOCSIWESSID)        = ieee80211softmac_wx_set_essid,
+       WX(SIOCGIWESSID)        = ieee80211softmac_wx_get_essid,
+       WX(SIOCSIWAP)           = ieee80211softmac_wx_set_wap,
+       WX(SIOCGIWAP)           = ieee80211softmac_wx_get_wap,
+       WX(SIOCSIWRATE)         = ieee80211softmac_wx_set_rate,
+       WX(SIOCGIWRATE)         = ieee80211softmac_wx_get_rate,
+       WX(SIOCSIWGENIE)        = ieee80211softmac_wx_set_genie,
+       WX(SIOCGIWGENIE)        = ieee80211softmac_wx_get_genie,
+       WX(SIOCSIWMLME)         = ieee80211softmac_wx_set_mlme,
+};
+
+static const struct iw_handler_def iw_handler_def = {
+       .standard               = zd_standard_iw_handlers,
+       .num_standard           = ARRAY_SIZE(zd_standard_iw_handlers),
+       .private                = zd_priv_handler,
+       .num_private            = ARRAY_SIZE(zd_priv_handler),
+       .private_args           = zd_priv_args,
+       .num_private_args       = ARRAY_SIZE(zd_priv_args),
+       .get_wireless_stats     = zd_mac_get_wireless_stats,
+};
+
+struct net_device *zd_netdev_alloc(struct usb_interface *intf)
+{
+       int r;
+       struct net_device *netdev;
+       struct zd_mac *mac;
+
+       netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
+       if (!netdev) {
+               dev_dbg_f(&intf->dev, "out of memory\n");
+               return NULL;
+       }
+
+       mac = zd_netdev_mac(netdev);
+       r = zd_mac_init(mac, netdev, intf);
+       if (r) {
+               usb_set_intfdata(intf, NULL);
+               free_ieee80211(netdev);
+               return NULL;
+       }
+
+       SET_MODULE_OWNER(netdev);
+       SET_NETDEV_DEV(netdev, &intf->dev);
+
+       dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
+       dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
+
+       netdev->open = zd_mac_open;
+       netdev->stop = zd_mac_stop;
+       /* netdev->get_stats = */
+       /* netdev->set_multicast_list = */
+       netdev->set_mac_address = zd_mac_set_mac_address;
+       netdev->wireless_handlers = &iw_handler_def;
+       /* netdev->ethtool_ops = */
+
+       return netdev;
+}
+
+void zd_netdev_free(struct net_device *netdev)
+{
+       if (!netdev)
+               return;
+
+       zd_mac_clear(zd_netdev_mac(netdev));
+       free_ieee80211(netdev);
+}
+
+void zd_netdev_disconnect(struct net_device *netdev)
+{
+       unregister_netdev(netdev);
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.h b/drivers/net/wireless/zd1211rw/zd_netdev.h
new file mode 100644 (file)
index 0000000..374a957
--- /dev/null
@@ -0,0 +1,45 @@
+/* zd_netdev.h: Header for net device related functions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 _ZD_NETDEV_H
+#define _ZD_NETDEV_H
+
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <net/ieee80211.h>
+
+#define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV)
+#define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1)
+
+static inline struct ieee80211_device *zd_netdev_ieee80211(
+       struct net_device *ndev)
+{
+       return netdev_priv(ndev);
+}
+
+static inline struct net_device *zd_ieee80211_to_netdev(
+       struct ieee80211_device *ieee)
+{
+       return ieee->dev;
+}
+
+struct net_device *zd_netdev_alloc(struct usb_interface *intf);
+void zd_netdev_free(struct net_device *netdev);
+
+void zd_netdev_disconnect(struct net_device *netdev);
+
+#endif /* _ZD_NETDEV_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
new file mode 100644 (file)
index 0000000..d3770d2
--- /dev/null
@@ -0,0 +1,151 @@
+/* zd_rf.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+
+#include "zd_def.h"
+#include "zd_rf.h"
+#include "zd_ieee80211.h"
+#include "zd_chip.h"
+
+static const char *rfs[] = {
+       [0]             = "unknown RF0",
+       [1]             = "unknown RF1",
+       [UW2451_RF]     = "UW2451_RF",
+       [UCHIP_RF]      = "UCHIP_RF",
+       [AL2230_RF]     = "AL2230_RF",
+       [AL7230B_RF]    = "AL7230B_RF",
+       [THETA_RF]      = "THETA_RF",
+       [AL2210_RF]     = "AL2210_RF",
+       [MAXIM_NEW_RF]  = "MAXIM_NEW_RF",
+       [UW2453_RF]     = "UW2453_RF",
+       [AL2230S_RF]    = "AL2230S_RF",
+       [RALINK_RF]     = "RALINK_RF",
+       [INTERSIL_RF]   = "INTERSIL_RF",
+       [RF2959_RF]     = "RF2959_RF",
+       [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF",
+       [PHILIPS_RF]    = "PHILIPS_RF",
+};
+
+const char *zd_rf_name(u8 type)
+{
+       if (type & 0xf0)
+               type = 0;
+       return rfs[type];
+}
+
+void zd_rf_init(struct zd_rf *rf)
+{
+       memset(rf, 0, sizeof(*rf));
+}
+
+void zd_rf_clear(struct zd_rf *rf)
+{
+       memset(rf, 0, sizeof(*rf));
+}
+
+int zd_rf_init_hw(struct zd_rf *rf, u8 type)
+{
+       int r, t;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       switch (type) {
+       case RF2959_RF:
+               r = zd_rf_init_rf2959(rf);
+               if (r)
+                       return r;
+               break;
+       case AL2230_RF:
+               r = zd_rf_init_al2230(rf);
+               if (r)
+                       return r;
+               break;
+       default:
+               dev_err(zd_chip_dev(chip),
+                       "RF %s %#x is not supported\n", zd_rf_name(type), type);
+               rf->type = 0;
+               return -ENODEV;
+       }
+
+       rf->type = type;
+
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               return r;
+       t = rf->init_hw(rf);
+       r = zd_chip_unlock_phy_regs(chip);
+       if (t)
+               r = t;
+       return r;
+}
+
+int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size)
+{
+       return scnprintf(buffer, size, "%s", zd_rf_name(rf->type));
+}
+
+int zd_rf_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+
+       ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex));
+       if (channel < MIN_CHANNEL24)
+               return -EINVAL;
+       if (channel > MAX_CHANNEL24)
+               return -EINVAL;
+       dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel);
+
+       r = rf->set_channel(rf, channel);
+       if (r >= 0)
+               rf->channel = channel;
+       return r;
+}
+
+int zd_switch_radio_on(struct zd_rf *rf)
+{
+       int r, t;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               return r;
+       t = rf->switch_radio_on(rf);
+       r = zd_chip_unlock_phy_regs(chip);
+       if (t)
+               r = t;
+       return r;
+}
+
+int zd_switch_radio_off(struct zd_rf *rf)
+{
+       int r, t;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       /* TODO: move phy regs handling to zd_chip */
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               return r;
+       t = rf->switch_radio_off(rf);
+       r = zd_chip_unlock_phy_regs(chip);
+       if (t)
+               r = t;
+       return r;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
new file mode 100644 (file)
index 0000000..ea30f69
--- /dev/null
@@ -0,0 +1,82 @@
+/* zd_rf.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ZD_RF_H
+#define _ZD_RF_H
+
+#include "zd_types.h"
+
+#define UW2451_RF                      0x2
+#define UCHIP_RF                       0x3
+#define AL2230_RF                      0x4
+#define AL7230B_RF                     0x5     /* a,b,g */
+#define THETA_RF                       0x6
+#define AL2210_RF                      0x7
+#define MAXIM_NEW_RF                   0x8
+#define UW2453_RF                      0x9
+#define AL2230S_RF                     0xa
+#define RALINK_RF                      0xb
+#define INTERSIL_RF                    0xc
+#define RF2959_RF                      0xd
+#define MAXIM_NEW2_RF                  0xe
+#define PHILIPS_RF                     0xf
+
+#define RF_CHANNEL(ch) [(ch)-1]
+
+/* Provides functions of the RF transceiver. */
+
+enum {
+       RF_REG_BITS = 6,
+       RF_VALUE_BITS = 18,
+       RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS,
+};
+
+struct zd_rf {
+       u8 type;
+
+       u8 channel;
+       /*
+        * Whether this RF should patch the 6M band edge
+        * (assuming E2P_POD agrees)
+        */
+       u8 patch_6m_band_edge:1;
+
+       /* RF-specific functions */
+       int (*init_hw)(struct zd_rf *rf);
+       int (*set_channel)(struct zd_rf *rf, u8 channel);
+       int (*switch_radio_on)(struct zd_rf *rf);
+       int (*switch_radio_off)(struct zd_rf *rf);
+};
+
+const char *zd_rf_name(u8 type);
+void zd_rf_init(struct zd_rf *rf);
+void zd_rf_clear(struct zd_rf *rf);
+int zd_rf_init_hw(struct zd_rf *rf, u8 type);
+
+int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size);
+
+int zd_rf_set_channel(struct zd_rf *rf, u8 channel);
+
+int zd_switch_radio_on(struct zd_rf *rf);
+int zd_switch_radio_off(struct zd_rf *rf);
+
+/* Functions for individual RF chips */
+
+int zd_rf_init_rf2959(struct zd_rf *rf);
+int zd_rf_init_al2230(struct zd_rf *rf);
+
+#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
new file mode 100644 (file)
index 0000000..0948b25
--- /dev/null
@@ -0,0 +1,308 @@
+/* zd_rf_al2230.c: Functions for the AL2230 RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+static const u32 al2230_table[][3] = {
+       RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
+       RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
+       RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, },
+       RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, },
+       RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, },
+       RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, },
+       RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, },
+       RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
+};
+
+static int zd1211_al2230_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR15,   0x20 }, { CR23,   0x40 }, { CR24,  0x20 },
+               { CR26,   0x11 }, { CR28,   0x3e }, { CR29,  0x00 },
+               { CR44,   0x33 }, { CR106,  0x2a }, { CR107, 0x1a },
+               { CR109,  0x09 }, { CR110,  0x27 }, { CR111, 0x2b },
+               { CR112,  0x2b }, { CR119,  0x0a }, { CR10,  0x89 },
+               /* for newest (3rd cut) AL2300 */
+               { CR17,   0x28 },
+               { CR26,   0x93 }, { CR34,   0x30 },
+               /* for newest (3rd cut) AL2300 */
+               { CR35,   0x3e },
+               { CR41,   0x24 }, { CR44,   0x32 },
+               /* for newest (3rd cut) AL2300 */
+               { CR46,   0x96 },
+               { CR47,   0x1e }, { CR79,   0x58 }, { CR80,  0x30 },
+               { CR81,   0x30 }, { CR87,   0x0a }, { CR89,  0x04 },
+               { CR92,   0x0a }, { CR99,   0x28 }, { CR100, 0x00 },
+               { CR101,  0x13 }, { CR102,  0x27 }, { CR106, 0x24 },
+               { CR107,  0x2a }, { CR109,  0x09 }, { CR110, 0x13 },
+               { CR111,  0x1f }, { CR112,  0x1f }, { CR113, 0x27 },
+               { CR114,  0x27 },
+               /* for newest (3rd cut) AL2300 */
+               { CR115,  0x24 },
+               { CR116,  0x24 }, { CR117,  0xf4 }, { CR118, 0xfc },
+               { CR119,  0x10 }, { CR120,  0x4f }, { CR121, 0x77 },
+               { CR122,  0xe0 }, { CR137,  0x88 }, { CR252, 0xff },
+               { CR253,  0xff },
+
+               /* These following happen separately in the vendor driver */
+               { },
+
+               /* shdnb(PLL_ON)=0 */
+               { CR251,  0x2f },
+               /* shdnb(PLL_ON)=1 */
+               { CR251,  0x3f },
+               { CR138,  0x28 }, { CR203,  0x06 },
+       };
+
+       static const u32 rv[] = {
+               /* Channel 1 */
+               0x03f790,
+               0x033331,
+               0x00000d,
+
+               0x0b3331,
+               0x03b812,
+               0x00fff3,
+               0x000da4,
+               0x0f4dc5, /* fix freq shift, 0x04edc5 */
+               0x0805b6,
+               0x011687,
+               0x000688,
+               0x0403b9, /* external control TX power (CR31) */
+               0x00dbba,
+               0x00099b,
+               0x0bdffc,
+               0x00000d,
+               0x00500f,
+
+               /* These writes happen separately in the vendor driver */
+               0x00d00f,
+               0x004c0f,
+               0x00540f,
+               0x00700f,
+               0x00500f,
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int zd1211b_al2230_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs1[] = {
+               { CR10,  0x89 }, { CR15,  0x20 },
+               { CR17,  0x2B }, /* for newest(3rd cut) AL2230 */
+               { CR23,  0x40 }, { CR24,  0x20 }, { CR26,  0x93 },
+               { CR28,  0x3e }, { CR29,  0x00 },
+               { CR33,  0x28 }, /* 5621 */
+               { CR34,  0x30 },
+               { CR35,  0x3e }, /* for newest(3rd cut) AL2230 */
+               { CR41,  0x24 }, { CR44,  0x32 },
+               { CR46,  0x99 }, /* for newest(3rd cut) AL2230 */
+               { CR47,  0x1e },
+
+               /* ZD1211B 05.06.10 */
+               { CR48,  0x00 }, { CR49,  0x00 }, { CR51,  0x01 },
+               { CR52,  0x80 }, { CR53,  0x7e }, { CR65,  0x00 },
+               { CR66,  0x00 }, { CR67,  0x00 }, { CR68,  0x00 },
+               { CR69,  0x28 },
+
+               { CR79,  0x58 }, { CR80,  0x30 }, { CR81,  0x30 },
+               { CR87,  0x0a }, { CR89,  0x04 },
+               { CR91,  0x00 }, /* 5621 */
+               { CR92,  0x0a },
+               { CR98,  0x8d }, /* 4804,  for 1212 new algorithm */
+               { CR99,  0x00 }, /* 5621 */
+               { CR101, 0x13 }, { CR102, 0x27 },
+               { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */
+               { CR107, 0x2a },
+               { CR109, 0x13 }, /* 4804, for 1212 new algorithm */
+               { CR110, 0x1f }, /* 4804, for 1212 new algorithm */
+               { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 },
+               { CR114, 0x27 },
+               { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */
+               { CR116, 0x24 },
+               { CR117, 0xfa }, /* for 1211b */
+               { CR118, 0xfa }, /* for 1211b */
+               { CR119, 0x10 },
+               { CR120, 0x4f },
+               { CR121, 0x6c }, /* for 1211b */
+               { CR122, 0xfc }, /* E0->FC at 4902 */
+               { CR123, 0x57 }, /* 5623 */
+               { CR125, 0xad }, /* 4804, for 1212 new algorithm */
+               { CR126, 0x6c }, /* 5614 */
+               { CR127, 0x03 }, /* 4804, for 1212 new algorithm */
+               { CR137, 0x50 }, /* 5614 */
+               { CR138, 0xa8 },
+               { CR144, 0xac }, /* 5621 */
+               { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 },
+       };
+
+       static const u32 rv1[] = {
+               /* channel 1 */
+               0x03f790,
+               0x033331,
+               0x00000d,
+
+               0x0b3331,
+               0x03b812,
+               0x00fff3,
+               0x0005a4,
+               0x0f4dc5, /* fix freq shift 0x044dc5 */
+               0x0805b6,
+               0x0146c7,
+               0x000688,
+               0x0403b9, /* External control TX power (CR31) */
+               0x00dbba,
+               0x00099b,
+               0x0bdffc,
+               0x00000d,
+               0x00580f,
+       };
+
+       static const struct zd_ioreq16 ioreqs2[] = {
+               { CR47,  0x1e }, { CR_RFCFG, 0x03 },
+       };
+
+       static const u32 rv2[] = {
+               0x00880f,
+               0x00080f,
+       };
+
+       static const struct zd_ioreq16 ioreqs3[] = {
+               { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f },
+       };
+
+       static const u32 rv3[] = {
+               0x00d80f,
+               0x00780f,
+               0x00580f,
+       };
+
+       static const struct zd_ioreq16 ioreqs4[] = {
+               { CR138, 0x28 }, { CR203, 0x06 },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
+       if (r)
+               return r;
+       r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
+       if (r)
+               return r;
+       r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+       if (r)
+               return r;
+       r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
+       if (r)
+               return r;
+       r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
+       if (r)
+               return r;
+       r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
+       if (r)
+               return r;
+       return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4));
+}
+
+static int al2230_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       const u32 *rv = al2230_table[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR138, 0x28 },
+               { CR203, 0x06 },
+       };
+
+       r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS);
+       if (r)
+               return r;
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR11,  0x00 },
+               { CR251, 0x3f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR11,  0x00 },
+               { CR251, 0x7f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int al2230_switch_radio_off(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR11,  0x04 },
+               { CR251, 0x2f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_al2230(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       rf->set_channel = al2230_set_channel;
+       rf->switch_radio_off = al2230_switch_radio_off;
+       if (chip->is_zd1211b) {
+               rf->init_hw = zd1211b_al2230_init_hw;
+               rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
+       } else {
+               rf->init_hw = zd1211_al2230_init_hw;
+               rf->switch_radio_on = zd1211_al2230_switch_radio_on;
+       }
+       rf->patch_6m_band_edge = 1;
+       return 0;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
new file mode 100644 (file)
index 0000000..5824727
--- /dev/null
@@ -0,0 +1,279 @@
+/* zd_rf_rfmd.c: Functions for the RFMD RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+static u32 rf2959_table[][2] = {
+       RF_CHANNEL( 1) = { 0x181979, 0x1e6666 },
+       RF_CHANNEL( 2) = { 0x181989, 0x1e6666 },
+       RF_CHANNEL( 3) = { 0x181999, 0x1e6666 },
+       RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 },
+       RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 },
+       RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 },
+       RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 },
+       RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 },
+       RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 },
+       RF_CHANNEL(10) = { 0x181a09, 0x1e6666 },
+       RF_CHANNEL(11) = { 0x181a19, 0x1e6666 },
+       RF_CHANNEL(12) = { 0x181a29, 0x1e6666 },
+       RF_CHANNEL(13) = { 0x181a39, 0x1e6666 },
+       RF_CHANNEL(14) = { 0x181a60, 0x1c0000 },
+};
+
+#if 0
+static int bits(u32 rw, int from, int to)
+{
+       rw &= ~(0xffffffffU << (to+1));
+       rw >>= from;
+       return rw;
+}
+
+static int bit(u32 rw, int bit)
+{
+       return bits(rw, bit, bit);
+}
+
+static void dump_regwrite(u32 rw)
+{
+       int reg = bits(rw, 18, 22);
+       int rw_flag = bits(rw, 23, 23);
+       PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag);
+
+       switch (reg) {
+       case 0:
+               PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d"
+                      " if_vco_reg_en %d if_vga_en %d",
+                      bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1),
+                      bit(rw, 0));
+               break;
+       case 1:
+               PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d"
+                      " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d"
+                      " ifloopc %d dac1 %d",
+                      bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
+                      bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
+                      bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3));
+               break;
+       case 2:
+               PDEBUG("reg2 IFPLL2 n1 %d num1 %d",
+                      bits(rw, 6, 17), bits(rw, 0, 5));
+               break;
+       case 3:
+               PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17));
+               break;
+       case 4:
+               PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d",
+                      bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
+               break;
+       case 5:
+               PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d"
+                      " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d"
+                      " dac %d",
+                      bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
+                      bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
+                      bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3));
+               break;
+       case 6:
+               PDEBUG("reg6 RFPLL2 n %d num %d",
+                      bits(rw, 6, 17), bits(rw, 0, 5));
+               break;
+       case 7:
+               PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17));
+               break;
+       case 8:
+               PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d",
+                      bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
+               break;
+       case 9:
+               PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d",
+                      bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7),
+                      bits(rw, 0, 2));
+               break;
+       case 10:
+               PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d"
+                      " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d"
+                      " intbiasen %d tybypass %d",
+                      bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14),
+                      bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2),
+                      bit(rw, 1), bit(rw, 0));
+               break;
+       case 11:
+               PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d"
+                       " tx_delay %d",
+                       bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8),
+                       bits(rw, 0, 2));
+               break;
+       case 12:
+               PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d",
+                      bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5));
+               break;
+       case 13:
+               PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d"
+                      " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d"
+                      " rf_biasvco %d",
+                      bit(rw, 17), bit(rw, 16), bit(rw, 15),
+                      bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4),
+                      bits(rw, 0, 2));
+               break;
+       case 14:
+               PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d"
+                      " tx_acal %d tx_pcal %d",
+                      bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8),
+                      bits(rw, 0, 3));
+               break;
+       }
+}
+#endif /* 0 */
+
+static int rf2959_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR2,   0x1E }, { CR9,   0x20 }, { CR10,  0x89 },
+               { CR11,  0x00 }, { CR15,  0xD0 }, { CR17,  0x68 },
+               { CR19,  0x4a }, { CR20,  0x0c }, { CR21,  0x0E },
+               { CR23,  0x48 },
+               /* normal size for cca threshold */
+               { CR24,  0x14 },
+               /* { CR24,  0x20 }, */
+               { CR26,  0x90 }, { CR27,  0x30 }, { CR29,  0x20 },
+               { CR31,  0xb2 }, { CR32,  0x43 }, { CR33,  0x28 },
+               { CR38,  0x30 }, { CR34,  0x0f }, { CR35,  0xF0 },
+               { CR41,  0x2a }, { CR46,  0x7F }, { CR47,  0x1E },
+               { CR51,  0xc5 }, { CR52,  0xc5 }, { CR53,  0xc5 },
+               { CR79,  0x58 }, { CR80,  0x30 }, { CR81,  0x30 },
+               { CR82,  0x00 }, { CR83,  0x24 }, { CR84,  0x04 },
+               { CR85,  0x00 }, { CR86,  0x10 }, { CR87,  0x2A },
+               { CR88,  0x10 }, { CR89,  0x24 }, { CR90,  0x18 },
+               /* { CR91,  0x18 }, */
+               /* should solve continous CTS frame problems */
+               { CR91,  0x00 },
+               { CR92,  0x0a }, { CR93,  0x00 }, { CR94,  0x01 },
+               { CR95,  0x00 }, { CR96,  0x40 }, { CR97,  0x37 },
+               { CR98,  0x05 }, { CR99,  0x28 }, { CR100, 0x00 },
+               { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 },
+               { CR104, 0x18 }, { CR105, 0x12 },
+               /* normal size */
+               { CR106, 0x1a },
+               /* { CR106, 0x22 }, */
+               { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 },
+               { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 },
+               { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 },
+               { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 },
+               { CR119, 0x16 },
+               /* no TX continuation */
+               { CR122, 0x00 },
+               /* { CR122, 0xff }, */
+               { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 },
+               { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB },
+               { CR170, 0xBB },
+       };
+
+       static const u32 rv[] = {
+               0x000007,  /* REG0(CFG1) */
+               0x07dd43,  /* REG1(IFPLL1) */
+               0x080959,  /* REG2(IFPLL2) */
+               0x0e6666,
+               0x116a57,  /* REG4 */
+               0x17dd43,  /* REG5 */
+               0x1819f9,  /* REG6 */
+               0x1e6666,
+               0x214554,
+               0x25e7fa,
+               0x27fffa,
+               /* The Zydas driver somehow forgets to set this value. It's
+                * only set for Japan. We are using internal power control
+                * for now.
+                */
+               0x294128, /* internal power */
+               /* 0x28252c, */ /* External control TX power */
+               /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */
+               0x2c0000,
+               0x300000,
+               0x340000,  /* REG13(0xD) */
+               0x381e0f,  /* REG14(0xE) */
+               /* Bogus, RF2959's data sheet doesn't know register 27, which is
+                * actually referenced here. The commented 0x11 is 17.
+                */
+               0x6c180f,  /* REG27(0x11) */
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int rf2959_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int i, r;
+       u32 *rv = rf2959_table[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       for (i = 0; i < 2; i++) {
+               r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS);
+               if (r)
+                       return r;
+       }
+       return 0;
+}
+
+static int rf2959_switch_radio_on(struct zd_rf *rf)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR10, 0x89 },
+               { CR11, 0x00 },
+       };
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int rf2959_switch_radio_off(struct zd_rf *rf)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { CR10, 0x15 },
+               { CR11, 0x81 },
+       };
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_rf2959(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       if (chip->is_zd1211b) {
+               dev_err(zd_chip_dev(chip),
+                      "RF2959 is currently not supported for ZD1211B"
+                      " devices\n");
+               return -ENODEV;
+       }
+       rf->init_hw = rf2959_init_hw;
+       rf->set_channel = rf2959_set_channel;
+       rf->switch_radio_on = rf2959_switch_radio_on;
+       rf->switch_radio_off = rf2959_switch_radio_off;
+       return 0;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_types.h b/drivers/net/wireless/zd1211rw/zd_types.h
new file mode 100644 (file)
index 0000000..0155a15
--- /dev/null
@@ -0,0 +1,71 @@
+/* zd_types.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ZD_TYPES_H
+#define _ZD_TYPES_H
+
+#include <linux/types.h>
+
+/* We have three register spaces mapped into the overall USB address space of
+ * 64K words (16-bit values). There is the control register space of
+ * double-word registers, the eeprom register space and the firmware register
+ * space. The control register space is byte mapped, the others are word
+ * mapped.
+ *
+ * For that reason, we are using byte offsets for control registers and word
+ * offsets for everything else.
+ */
+
+typedef u32 __nocast zd_addr_t;
+
+enum {
+       ADDR_BASE_MASK          = 0xff000000,
+       ADDR_OFFSET_MASK        = 0x0000ffff,
+       ADDR_ZERO_MASK          = 0x00ff0000,
+       NULL_BASE               = 0x00000000,
+       USB_BASE                = 0x01000000,
+       CR_BASE                 = 0x02000000,
+       CR_MAX_OFFSET           = 0x0b30,
+       E2P_BASE                = 0x03000000,
+       E2P_MAX_OFFSET          = 0x007e,
+       FW_BASE                 = 0x04000000,
+       FW_MAX_OFFSET           = 0x0005,
+};
+
+#define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK)
+#define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK)
+
+#define ZD_ADDR(base, offset) \
+       ((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK)))
+
+#define ZD_NULL_ADDR    ((zd_addr_t)0)
+#define USB_REG(offset)  ZD_ADDR(USB_BASE, offset)     /* word addressing */
+#define CTL_REG(offset)  ZD_ADDR(CR_BASE, offset)      /* byte addressing */
+#define E2P_REG(offset)  ZD_ADDR(E2P_BASE, offset)     /* word addressing */
+#define FW_REG(offset)   ZD_ADDR(FW_BASE, offset)      /* word addressing */
+
+static inline zd_addr_t zd_inc_word(zd_addr_t addr)
+{
+       u32 base = ZD_ADDR_BASE(addr);
+       u32 offset = ZD_OFFSET(addr);
+
+       offset += base == CR_BASE ? 2 : 1;
+
+       return base | offset;
+}
+
+#endif /* _ZD_TYPES_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
new file mode 100644 (file)
index 0000000..6320984
--- /dev/null
@@ -0,0 +1,1309 @@
+/* zd_usb.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/unaligned.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <net/ieee80211.h>
+
+#include "zd_def.h"
+#include "zd_netdev.h"
+#include "zd_mac.h"
+#include "zd_usb.h"
+#include "zd_util.h"
+
+static struct usb_device_id usb_ids[] = {
+       /* ZD1211 */
+       { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
+       /* ZD1211B */
+       { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
+       {}
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip.");
+MODULE_AUTHOR("Ulrich Kunitz");
+MODULE_AUTHOR("Daniel Drake");
+MODULE_VERSION("1.0");
+MODULE_DEVICE_TABLE(usb, usb_ids);
+
+#define FW_ZD1211_PREFIX       "zd1211/zd1211_"
+#define FW_ZD1211B_PREFIX      "zd1211/zd1211b_"
+
+/* register address handling */
+
+#ifdef DEBUG
+static int check_addr(struct zd_usb *usb, zd_addr_t addr)
+{
+       u32 base = ZD_ADDR_BASE(addr);
+       u32 offset = ZD_OFFSET(addr);
+
+       if ((u32)addr & ADDR_ZERO_MASK)
+               goto invalid_address;
+       switch (base) {
+       case USB_BASE:
+               break;
+       case CR_BASE:
+               if (offset > CR_MAX_OFFSET) {
+                       dev_dbg(zd_usb_dev(usb),
+                               "CR offset %#010x larger than"
+                               " CR_MAX_OFFSET %#10x\n",
+                               offset, CR_MAX_OFFSET);
+                       goto invalid_address;
+               }
+               if (offset & 1) {
+                       dev_dbg(zd_usb_dev(usb),
+                               "CR offset %#010x is not a multiple of 2\n",
+                               offset);
+                       goto invalid_address;
+               }
+               break;
+       case E2P_BASE:
+               if (offset > E2P_MAX_OFFSET) {
+                       dev_dbg(zd_usb_dev(usb),
+                               "E2P offset %#010x larger than"
+                               " E2P_MAX_OFFSET %#010x\n",
+                               offset, E2P_MAX_OFFSET);
+                       goto invalid_address;
+               }
+               break;
+       case FW_BASE:
+               if (!usb->fw_base_offset) {
+                       dev_dbg(zd_usb_dev(usb),
+                              "ERROR: fw base offset has not been set\n");
+                       return -EAGAIN;
+               }
+               if (offset > FW_MAX_OFFSET) {
+                       dev_dbg(zd_usb_dev(usb),
+                               "FW offset %#10x is larger than"
+                               " FW_MAX_OFFSET %#010x\n",
+                               offset, FW_MAX_OFFSET);
+                       goto invalid_address;
+               }
+               break;
+       default:
+               dev_dbg(zd_usb_dev(usb),
+                       "address has unsupported base %#010x\n", addr);
+               goto invalid_address;
+       }
+
+       return 0;
+invalid_address:
+       dev_dbg(zd_usb_dev(usb),
+               "ERROR: invalid address: %#010x\n", addr);
+       return -EINVAL;
+}
+#endif /* DEBUG */
+
+static u16 usb_addr(struct zd_usb *usb, zd_addr_t addr)
+{
+       u32 base;
+       u16 offset;
+
+       base = ZD_ADDR_BASE(addr);
+       offset = ZD_OFFSET(addr);
+
+       ZD_ASSERT(check_addr(usb, addr) == 0);
+
+       switch (base) {
+       case CR_BASE:
+               offset += CR_BASE_OFFSET;
+               break;
+       case E2P_BASE:
+               offset += E2P_BASE_OFFSET;
+               break;
+       case FW_BASE:
+               offset += usb->fw_base_offset;
+               break;
+       }
+
+       return offset;
+}
+
+/* USB device initialization */
+
+static int request_fw_file(
+       const struct firmware **fw, const char *name, struct device *device)
+{
+       int r;
+
+       dev_dbg_f(device, "fw name %s\n", name);
+
+       r = request_firmware(fw, name, device);
+       if (r)
+               dev_err(device,
+                      "Could not load firmware file %s. Error number %d\n",
+                      name, r);
+       return r;
+}
+
+static inline u16 get_bcdDevice(const struct usb_device *udev)
+{
+       return le16_to_cpu(udev->descriptor.bcdDevice);
+}
+
+enum upload_code_flags {
+       REBOOT = 1,
+};
+
+/* Ensures that MAX_TRANSFER_SIZE is even. */
+#define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1)
+
+static int upload_code(struct usb_device *udev,
+       const u8 *data, size_t size, u16 code_offset, int flags)
+{
+       u8 *p;
+       int r;
+
+       /* USB request blocks need "kmalloced" buffers.
+        */
+       p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL);
+       if (!p) {
+               dev_err(&udev->dev, "out of memory\n");
+               r = -ENOMEM;
+               goto error;
+       }
+
+       size &= ~1;
+       while (size > 0) {
+               size_t transfer_size = size <= MAX_TRANSFER_SIZE ?
+                       size : MAX_TRANSFER_SIZE;
+
+               dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size);
+
+               memcpy(p, data, transfer_size);
+               r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       USB_REQ_FIRMWARE_DOWNLOAD,
+                       USB_DIR_OUT | USB_TYPE_VENDOR,
+                       code_offset, 0, p, transfer_size, 1000 /* ms */);
+               if (r < 0) {
+                       dev_err(&udev->dev,
+                              "USB control request for firmware upload"
+                              " failed. Error number %d\n", r);
+                       goto error;
+               }
+               transfer_size = r & ~1;
+
+               size -= transfer_size;
+               data += transfer_size;
+               code_offset += transfer_size/sizeof(u16);
+       }
+
+       if (flags & REBOOT) {
+               u8 ret;
+
+               r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                       USB_REQ_FIRMWARE_CONFIRM,
+                       USB_DIR_IN | USB_TYPE_VENDOR,
+                       0, 0, &ret, sizeof(ret), 5000 /* ms */);
+               if (r != sizeof(ret)) {
+                       dev_err(&udev->dev,
+                               "control request firmeware confirmation failed."
+                               " Return value %d\n", r);
+                       if (r >= 0)
+                               r = -ENODEV;
+                       goto error;
+               }
+               if (ret & 0x80) {
+                       dev_err(&udev->dev,
+                               "Internal error while downloading."
+                               " Firmware confirm return value %#04x\n",
+                               (unsigned int)ret);
+                       r = -ENODEV;
+                       goto error;
+               }
+               dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n",
+                       (unsigned int)ret);
+       }
+
+       r = 0;
+error:
+       kfree(p);
+       return r;
+}
+
+static u16 get_word(const void *data, u16 offset)
+{
+       const __le16 *p = data;
+       return le16_to_cpu(p[offset]);
+}
+
+static char *get_fw_name(char *buffer, size_t size, u8 device_type,
+                      const char* postfix)
+{
+       scnprintf(buffer, size, "%s%s",
+               device_type == DEVICE_ZD1211B ?
+                       FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
+               postfix);
+       return buffer;
+}
+
+static int upload_firmware(struct usb_device *udev, u8 device_type)
+{
+       int r;
+       u16 fw_bcdDevice;
+       u16 bcdDevice;
+       const struct firmware *ub_fw = NULL;
+       const struct firmware *uph_fw = NULL;
+       char fw_name[128];
+
+       bcdDevice = get_bcdDevice(udev);
+
+       r = request_fw_file(&ub_fw,
+               get_fw_name(fw_name, sizeof(fw_name), device_type,  "ub"),
+               &udev->dev);
+       if (r)
+               goto error;
+
+       fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET);
+
+       /* FIXME: do we have any reason to perform the kludge that the vendor
+        * driver does when there is a version mismatch? (their driver uploads
+        * different firmwares and stuff)
+        */
+       if (fw_bcdDevice != bcdDevice) {
+               dev_info(&udev->dev,
+                       "firmware device id %#06x and actual device id "
+                       "%#06x differ, continuing anyway\n",
+                       fw_bcdDevice, bcdDevice);
+       } else {
+               dev_dbg_f(&udev->dev,
+                       "firmware device id %#06x is equal to the "
+                       "actual device id\n", fw_bcdDevice);
+       }
+
+
+       r = request_fw_file(&uph_fw,
+               get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"),
+               &udev->dev);
+       if (r)
+               goto error;
+
+       r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START_OFFSET,
+                       REBOOT);
+       if (r) {
+               dev_err(&udev->dev,
+                       "Could not upload firmware code uph. Error number %d\n",
+                       r);
+       }
+
+       /* FALL-THROUGH */
+error:
+       release_firmware(ub_fw);
+       release_firmware(uph_fw);
+       return r;
+}
+
+static void disable_read_regs_int(struct zd_usb *usb)
+{
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock(&intr->lock);
+       intr->read_regs_enabled = 0;
+       spin_unlock(&intr->lock);
+}
+
+#define urb_dev(urb) (&(urb)->dev->dev)
+
+static inline void handle_regs_int(struct urb *urb)
+{
+       struct zd_usb *usb = urb->context;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       int len;
+
+       ZD_ASSERT(in_interrupt());
+       spin_lock(&intr->lock);
+
+       if (intr->read_regs_enabled) {
+               intr->read_regs.length = len = urb->actual_length;
+
+               if (len > sizeof(intr->read_regs.buffer))
+                       len = sizeof(intr->read_regs.buffer);
+               memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
+               intr->read_regs_enabled = 0;
+               complete(&intr->read_regs.completion);
+               goto out;
+       }
+
+       dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n");
+out:
+       spin_unlock(&intr->lock);
+}
+
+static inline void handle_retry_failed_int(struct urb *urb)
+{
+       dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
+}
+
+
+static void int_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+{
+       int r;
+       struct usb_int_header *hdr;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+       case -EINVAL:
+       case -ENODEV:
+       case -ENOENT:
+       case -ECONNRESET:
+       case -EPIPE:
+               goto kfree;
+       default:
+               goto resubmit;
+       }
+
+       if (urb->actual_length < sizeof(hdr)) {
+               dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb);
+               goto resubmit;
+       }
+
+       hdr = urb->transfer_buffer;
+       if (hdr->type != USB_INT_TYPE) {
+               dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb);
+               goto resubmit;
+       }
+
+       switch (hdr->id) {
+       case USB_INT_ID_REGS:
+               handle_regs_int(urb);
+               break;
+       case USB_INT_ID_RETRY_FAILED:
+               handle_retry_failed_int(urb);
+               break;
+       default:
+               dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb,
+                       (unsigned int)hdr->id);
+               goto resubmit;
+       }
+
+resubmit:
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r) {
+               dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb);
+               goto kfree;
+       }
+       return;
+kfree:
+       kfree(urb->transfer_buffer);
+}
+
+static inline int int_urb_interval(struct usb_device *udev)
+{
+       switch (udev->speed) {
+       case USB_SPEED_HIGH:
+               return 4;
+       case USB_SPEED_LOW:
+               return 10;
+       case USB_SPEED_FULL:
+       default:
+               return 1;
+       }
+}
+
+static inline int usb_int_enabled(struct zd_usb *usb)
+{
+       unsigned long flags;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct urb *urb;
+
+       spin_lock_irqsave(&intr->lock, flags);
+       urb = intr->urb;
+       spin_unlock_irqrestore(&intr->lock, flags);
+       return urb != NULL;
+}
+
+int zd_usb_enable_int(struct zd_usb *usb)
+{
+       int r;
+       struct usb_device *udev;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       void *transfer_buffer = NULL;
+       struct urb *urb;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       urb = usb_alloc_urb(0, GFP_NOFS);
+       if (!urb) {
+               r = -ENOMEM;
+               goto out;
+       }
+
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&intr->lock);
+       if (intr->urb) {
+               spin_unlock_irq(&intr->lock);
+               r = 0;
+               goto error_free_urb;
+       }
+       intr->urb = urb;
+       spin_unlock_irq(&intr->lock);
+
+       /* TODO: make it a DMA buffer */
+       r = -ENOMEM;
+       transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_NOFS);
+       if (!transfer_buffer) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "couldn't allocate transfer_buffer\n");
+               goto error_set_urb_null;
+       }
+
+       udev = zd_usb_to_usbdev(usb);
+       usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN),
+                        transfer_buffer, USB_MAX_EP_INT_BUFFER,
+                        int_urb_complete, usb,
+                        intr->interval);
+
+       dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
+       r = usb_submit_urb(urb, GFP_NOFS);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "Couldn't submit urb. Error number %d\n", r);
+               goto error;
+       }
+
+       return 0;
+error:
+       kfree(transfer_buffer);
+error_set_urb_null:
+       spin_lock_irq(&intr->lock);
+       intr->urb = NULL;
+       spin_unlock_irq(&intr->lock);
+error_free_urb:
+       usb_free_urb(urb);
+out:
+       return r;
+}
+
+void zd_usb_disable_int(struct zd_usb *usb)
+{
+       unsigned long flags;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct urb *urb;
+
+       spin_lock_irqsave(&intr->lock, flags);
+       urb = intr->urb;
+       if (!urb) {
+               spin_unlock_irqrestore(&intr->lock, flags);
+               return;
+       }
+       intr->urb = NULL;
+       spin_unlock_irqrestore(&intr->lock, flags);
+
+       usb_kill_urb(urb);
+       dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb);
+       usb_free_urb(urb);
+}
+
+static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
+                            unsigned int length)
+{
+       int i;
+       struct zd_mac *mac = zd_usb_to_mac(usb);
+       const struct rx_length_info *length_info;
+
+       if (length < sizeof(struct rx_length_info)) {
+               /* It's not a complete packet anyhow. */
+               return;
+       }
+       length_info = (struct rx_length_info *)
+               (buffer + length - sizeof(struct rx_length_info));
+
+       /* It might be that three frames are merged into a single URB
+        * transaction. We have to check for the length info tag.
+        *
+        * While testing we discovered that length_info might be unaligned,
+        * because if USB transactions are merged, the last packet will not
+        * be padded. Unaligned access might also happen if the length_info
+        * structure is not present.
+        */
+       if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG))
+       {
+               unsigned int l, k, n;
+               for (i = 0, l = 0;; i++) {
+                       k = le16_to_cpu(get_unaligned(&length_info->length[i]));
+                       n = l+k;
+                       if (n > length)
+                               return;
+                       zd_mac_rx(mac, buffer+l, k);
+                       if (i >= 2)
+                               return;
+                       l = (n+3) & ~3;
+               }
+       } else {
+               zd_mac_rx(mac, buffer, length);
+       }
+}
+
+static void rx_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+{
+       struct zd_usb *usb;
+       struct zd_usb_rx *rx;
+       const u8 *buffer;
+       unsigned int length;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+       case -EINVAL:
+       case -ENODEV:
+       case -ENOENT:
+       case -ECONNRESET:
+       case -EPIPE:
+               return;
+       default:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               goto resubmit;
+       }
+
+       buffer = urb->transfer_buffer;
+       length = urb->actual_length;
+       usb = urb->context;
+       rx = &usb->rx;
+
+       if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
+               /* If there is an old first fragment, we don't care. */
+               dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
+               ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment));
+               spin_lock(&rx->lock);
+               memcpy(rx->fragment, buffer, length);
+               rx->fragment_length = length;
+               spin_unlock(&rx->lock);
+               goto resubmit;
+       }
+
+       spin_lock(&rx->lock);
+       if (rx->fragment_length > 0) {
+               /* We are on a second fragment, we believe */
+               ZD_ASSERT(length + rx->fragment_length <=
+                         ARRAY_SIZE(rx->fragment));
+               dev_dbg_f(urb_dev(urb), "*** second fragment ***\n");
+               memcpy(rx->fragment+rx->fragment_length, buffer, length);
+               handle_rx_packet(usb, rx->fragment,
+                                rx->fragment_length + length);
+               rx->fragment_length = 0;
+               spin_unlock(&rx->lock);
+       } else {
+               spin_unlock(&rx->lock);
+               handle_rx_packet(usb, buffer, length);
+       }
+
+resubmit:
+       usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+struct urb *alloc_urb(struct zd_usb *usb)
+{
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       struct urb *urb;
+       void *buffer;
+
+       urb = usb_alloc_urb(0, GFP_NOFS);
+       if (!urb)
+               return NULL;
+       buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_NOFS,
+                                 &urb->transfer_dma);
+       if (!buffer) {
+               usb_free_urb(urb);
+               return NULL;
+       }
+
+       usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
+                         buffer, USB_MAX_RX_SIZE,
+                         rx_urb_complete, usb);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       return urb;
+}
+
+void free_urb(struct urb *urb)
+{
+       if (!urb)
+               return;
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                       urb->transfer_buffer, urb->transfer_dma);
+       usb_free_urb(urb);
+}
+
+int zd_usb_enable_rx(struct zd_usb *usb)
+{
+       int i, r;
+       struct zd_usb_rx *rx = &usb->rx;
+       struct urb **urbs;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       r = -ENOMEM;
+       urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_NOFS);
+       if (!urbs)
+               goto error;
+       for (i = 0; i < URBS_COUNT; i++) {
+               urbs[i] = alloc_urb(usb);
+               if (!urbs[i])
+                       goto error;
+       }
+
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&rx->lock);
+       if (rx->urbs) {
+               spin_unlock_irq(&rx->lock);
+               r = 0;
+               goto error;
+       }
+       rx->urbs = urbs;
+       rx->urbs_count = URBS_COUNT;
+       spin_unlock_irq(&rx->lock);
+
+       for (i = 0; i < URBS_COUNT; i++) {
+               r = usb_submit_urb(urbs[i], GFP_NOFS);
+               if (r)
+                       goto error_submit;
+       }
+
+       return 0;
+error_submit:
+       for (i = 0; i < URBS_COUNT; i++) {
+               usb_kill_urb(urbs[i]);
+       }
+       spin_lock_irq(&rx->lock);
+       rx->urbs = NULL;
+       rx->urbs_count = 0;
+       spin_unlock_irq(&rx->lock);
+error:
+       if (urbs) {
+               for (i = 0; i < URBS_COUNT; i++)
+                       free_urb(urbs[i]);
+       }
+       return r;
+}
+
+void zd_usb_disable_rx(struct zd_usb *usb)
+{
+       int i;
+       unsigned long flags;
+       struct urb **urbs;
+       unsigned int count;
+       struct zd_usb_rx *rx = &usb->rx;
+
+       spin_lock_irqsave(&rx->lock, flags);
+       urbs = rx->urbs;
+       count = rx->urbs_count;
+       spin_unlock_irqrestore(&rx->lock, flags);
+       if (!urbs)
+               return;
+
+       for (i = 0; i < count; i++) {
+               usb_kill_urb(urbs[i]);
+               free_urb(urbs[i]);
+       }
+       kfree(urbs);
+
+       spin_lock_irqsave(&rx->lock, flags);
+       rx->urbs = NULL;
+       rx->urbs_count = 0;
+       spin_unlock_irqrestore(&rx->lock, flags);
+}
+
+static void tx_urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+{
+       int r;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+       case -EINVAL:
+       case -ENODEV:
+       case -ENOENT:
+       case -ECONNRESET:
+       case -EPIPE:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               break;
+       default:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               goto resubmit;
+       }
+free_urb:
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                       urb->transfer_buffer, urb->transfer_dma);
+       usb_free_urb(urb);
+       return;
+resubmit:
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r) {
+               dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
+               goto free_urb;
+       }
+}
+
+/* Puts the frame on the USB endpoint. It doesn't wait for
+ * completion. The frame must contain the control set.
+ */
+int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length)
+{
+       int r;
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       struct urb *urb;
+       void *buffer;
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               r = -ENOMEM;
+               goto out;
+       }
+
+       buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC,
+                                 &urb->transfer_dma);
+       if (!buffer) {
+               r = -ENOMEM;
+               goto error_free_urb;
+       }
+       memcpy(buffer, frame, length);
+
+       usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
+                         buffer, length, tx_urb_complete, NULL);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r)
+               goto error;
+       return 0;
+error:
+       usb_buffer_free(zd_usb_to_usbdev(usb), length, buffer,
+                       urb->transfer_dma);
+error_free_urb:
+       usb_free_urb(urb);
+out:
+       return r;
+}
+
+static inline void init_usb_interrupt(struct zd_usb *usb)
+{
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock_init(&intr->lock);
+       intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
+       init_completion(&intr->read_regs.completion);
+       intr->read_regs.cr_int_addr = cpu_to_le16(usb_addr(usb, CR_INTERRUPT));
+}
+
+static inline void init_usb_rx(struct zd_usb *usb)
+{
+       struct zd_usb_rx *rx = &usb->rx;
+       spin_lock_init(&rx->lock);
+       if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
+               rx->usb_packet_size = 512;
+       } else {
+               rx->usb_packet_size = 64;
+       }
+       ZD_ASSERT(rx->fragment_length == 0);
+}
+
+static inline void init_usb_tx(struct zd_usb *usb)
+{
+       /* FIXME: at this point we will allocate a fixed number of urb's for
+        * use in a cyclic scheme */
+}
+
+void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
+                struct usb_interface *intf)
+{
+       memset(usb, 0, sizeof(*usb));
+       usb->intf = usb_get_intf(intf);
+       usb_set_intfdata(usb->intf, netdev);
+       init_usb_interrupt(usb);
+       init_usb_tx(usb);
+       init_usb_rx(usb);
+}
+
+int zd_usb_init_hw(struct zd_usb *usb)
+{
+       int r;
+       struct zd_chip *chip = zd_usb_to_chip(usb);
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread16_locked(chip, &usb->fw_base_offset,
+                       USB_REG((u16)FW_BASE_ADDR_OFFSET));
+       if (r)
+               return r;
+       dev_dbg_f(zd_usb_dev(usb), "fw_base_offset: %#06hx\n",
+                usb->fw_base_offset);
+
+       return 0;
+}
+
+void zd_usb_clear(struct zd_usb *usb)
+{
+       usb_set_intfdata(usb->intf, NULL);
+       usb_put_intf(usb->intf);
+       memset(usb, 0, sizeof(*usb));
+       /* FIXME: usb_interrupt, usb_tx, usb_rx? */
+}
+
+static const char *speed(enum usb_device_speed speed)
+{
+       switch (speed) {
+       case USB_SPEED_LOW:
+               return "low";
+       case USB_SPEED_FULL:
+               return "full";
+       case USB_SPEED_HIGH:
+               return "high";
+       default:
+               return "unknown speed";
+       }
+}
+
+static int scnprint_id(struct usb_device *udev, char *buffer, size_t size)
+{
+       return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s",
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               get_bcdDevice(udev),
+               speed(udev->speed));
+}
+
+int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size)
+{
+       struct usb_device *udev = interface_to_usbdev(usb->intf);
+       return scnprint_id(udev, buffer, size);
+}
+
+#ifdef DEBUG
+static void print_id(struct usb_device *udev)
+{
+       char buffer[40];
+
+       scnprint_id(udev, buffer, sizeof(buffer));
+       buffer[sizeof(buffer)-1] = 0;
+       dev_dbg_f(&udev->dev, "%s\n", buffer);
+}
+#else
+#define print_id(udev) do { } while (0)
+#endif
+
+static int probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       int r;
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct net_device *netdev = NULL;
+
+       print_id(udev);
+
+       switch (udev->speed) {
+       case USB_SPEED_LOW:
+       case USB_SPEED_FULL:
+       case USB_SPEED_HIGH:
+               break;
+       default:
+               dev_dbg_f(&intf->dev, "Unknown USB speed\n");
+               r = -ENODEV;
+               goto error;
+       }
+
+       netdev = zd_netdev_alloc(intf);
+       if (netdev == NULL) {
+               r = -ENOMEM;
+               goto error;
+       }
+
+       r = upload_firmware(udev, id->driver_info);
+       if (r) {
+               dev_err(&intf->dev,
+                      "couldn't load firmware. Error number %d\n", r);
+               goto error;
+       }
+
+       r = usb_reset_configuration(udev);
+       if (r) {
+               dev_dbg_f(&intf->dev,
+                       "couldn't reset configuration. Error number %d\n", r);
+               goto error;
+       }
+
+       /* At this point the interrupt endpoint is not generally enabled. We
+        * save the USB bandwidth until the network device is opened. But
+        * notify that the initialization of the MAC will require the
+        * interrupts to be temporary enabled.
+        */
+       r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info);
+       if (r) {
+               dev_dbg_f(&intf->dev,
+                        "couldn't initialize mac. Error number %d\n", r);
+               goto error;
+       }
+
+       r = register_netdev(netdev);
+       if (r) {
+               dev_dbg_f(&intf->dev,
+                        "couldn't register netdev. Error number %d\n", r);
+               goto error;
+       }
+
+       dev_dbg_f(&intf->dev, "successful\n");
+       dev_info(&intf->dev,"%s\n", netdev->name);
+       return 0;
+error:
+       usb_reset_device(interface_to_usbdev(intf));
+       zd_netdev_free(netdev);
+       return r;
+}
+
+static void disconnect(struct usb_interface *intf)
+{
+       struct net_device *netdev = zd_intf_to_netdev(intf);
+       struct zd_mac *mac = zd_netdev_mac(netdev);
+       struct zd_usb *usb = &mac->chip.usb;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       zd_netdev_disconnect(netdev);
+
+       /* Just in case something has gone wrong! */
+       zd_usb_disable_rx(usb);
+       zd_usb_disable_int(usb);
+
+       /* If the disconnect has been caused by a removal of the
+        * driver module, the reset allows reloading of the driver. If the
+        * reset will not be executed here, the upload of the firmware in the
+        * probe function caused by the reloading of the driver will fail.
+        */
+       usb_reset_device(interface_to_usbdev(intf));
+
+       /* If somebody still waits on this lock now, this is an error. */
+       zd_netdev_free(netdev);
+       dev_dbg(&intf->dev, "disconnected\n");
+}
+
+static struct usb_driver driver = {
+       .name           = "zd1211rw",
+       .id_table       = usb_ids,
+       .probe          = probe,
+       .disconnect     = disconnect,
+};
+
+static int __init usb_init(void)
+{
+       int r;
+
+       pr_debug("usb_init()\n");
+
+       r = usb_register(&driver);
+       if (r) {
+               printk(KERN_ERR "usb_register() failed. Error number %d\n", r);
+               return r;
+       }
+
+       pr_debug("zd1211rw initialized\n");
+       return 0;
+}
+
+static void __exit usb_exit(void)
+{
+       pr_debug("usb_exit()\n");
+       usb_deregister(&driver);
+}
+
+module_init(usb_init);
+module_exit(usb_exit);
+
+static int usb_int_regs_length(unsigned int count)
+{
+       return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
+}
+
+static void prepare_read_regs_int(struct zd_usb *usb)
+{
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock(&intr->lock);
+       intr->read_regs_enabled = 1;
+       INIT_COMPLETION(intr->read_regs.completion);
+       spin_unlock(&intr->lock);
+}
+
+static int get_results(struct zd_usb *usb, u16 *values,
+                      struct usb_req_read_regs *req, unsigned int count)
+{
+       int r;
+       int i;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct read_regs_int *rr = &intr->read_regs;
+       struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+       spin_lock(&intr->lock);
+
+       r = -EIO;
+       /* The created block size seems to be larger than expected.
+        * However results appear to be correct.
+        */
+       if (rr->length < usb_int_regs_length(count)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: actual length %d less than expected %d\n",
+                        rr->length, usb_int_regs_length(count));
+               goto error_unlock;
+       }
+       if (rr->length > sizeof(rr->buffer)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: actual length %d exceeds buffer size %zu\n",
+                        rr->length, sizeof(rr->buffer));
+               goto error_unlock;
+       }
+
+       for (i = 0; i < count; i++) {
+               struct reg_data *rd = &regs->regs[i];
+               if (rd->addr != req->addr[i]) {
+                       dev_dbg_f(zd_usb_dev(usb),
+                                "rd[%d] addr %#06hx expected %#06hx\n", i,
+                                le16_to_cpu(rd->addr),
+                                le16_to_cpu(req->addr[i]));
+                       goto error_unlock;
+               }
+               values[i] = le16_to_cpu(rd->value);
+       }
+
+       r = 0;
+error_unlock:
+       spin_unlock(&intr->lock);
+       return r;
+}
+
+int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
+                    const zd_addr_t *addresses, unsigned int count)
+{
+       int r;
+       int i, req_len, actual_req_len;
+       struct usb_device *udev;
+       struct usb_req_read_regs *req = NULL;
+       unsigned long timeout;
+
+       if (count < 1) {
+               dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
+               return -EINVAL;
+       }
+       if (count > USB_MAX_IOREAD16_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: count %u exceeds possible max %u\n",
+                        count, USB_MAX_IOREAD16_COUNT);
+               return -EINVAL;
+       }
+       if (in_atomic()) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: io in atomic context not supported\n");
+               return -EWOULDBLOCK;
+       }
+       if (!usb_int_enabled(usb)) {
+                dev_dbg_f(zd_usb_dev(usb),
+                         "error: usb interrupt not enabled\n");
+               return -EWOULDBLOCK;
+       }
+
+       req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
+       req = kmalloc(req_len, GFP_NOFS);
+       if (!req)
+               return -ENOMEM;
+       req->id = cpu_to_le16(USB_REQ_READ_REGS);
+       for (i = 0; i < count; i++)
+               req->addr[i] = cpu_to_le16(usb_addr(usb, addresses[i]));
+
+       udev = zd_usb_to_usbdev(usb);
+       prepare_read_regs_int(usb);
+       r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
+                        req, req_len, &actual_req_len, 1000 /* ms */);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in usb_bulk_msg(). Error number %d\n", r);
+               goto error;
+       }
+       if (req_len != actual_req_len) {
+               dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n"
+                       " req_len %d != actual_req_len %d\n",
+                       req_len, actual_req_len);
+               r = -EIO;
+               goto error;
+       }
+
+       timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion,
+                                             msecs_to_jiffies(1000));
+       if (!timeout) {
+               disable_read_regs_int(usb);
+               dev_dbg_f(zd_usb_dev(usb), "read timed out\n");
+               r = -ETIMEDOUT;
+               goto error;
+       }
+
+       r = get_results(usb, values, req, count);
+error:
+       kfree(req);
+       return r;
+}
+
+int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+                     unsigned int count)
+{
+       int r;
+       struct usb_device *udev;
+       struct usb_req_write_regs *req = NULL;
+       int i, req_len, actual_req_len;
+
+       if (count == 0)
+               return 0;
+       if (count > USB_MAX_IOWRITE16_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: count %u exceeds possible max %u\n",
+                       count, USB_MAX_IOWRITE16_COUNT);
+               return -EINVAL;
+       }
+       if (in_atomic()) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: io in atomic context not supported\n");
+               return -EWOULDBLOCK;
+       }
+
+       req_len = sizeof(struct usb_req_write_regs) +
+                 count * sizeof(struct reg_data);
+       req = kmalloc(req_len, GFP_NOFS);
+       if (!req)
+               return -ENOMEM;
+
+       req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
+       for (i = 0; i < count; i++) {
+               struct reg_data *rw  = &req->reg_writes[i];
+               rw->addr = cpu_to_le16(usb_addr(usb, ioreqs[i].addr));
+               rw->value = cpu_to_le16(ioreqs[i].value);
+       }
+
+       udev = zd_usb_to_usbdev(usb);
+       r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
+                        req, req_len, &actual_req_len, 1000 /* ms */);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in usb_bulk_msg(). Error number %d\n", r);
+               goto error;
+       }
+       if (req_len != actual_req_len) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in usb_bulk_msg()"
+                       " req_len %d != actual_req_len %d\n",
+                       req_len, actual_req_len);
+               r = -EIO;
+               goto error;
+       }
+
+       /* FALL-THROUGH with r == 0 */
+error:
+       kfree(req);
+       return r;
+}
+
+int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
+{
+       int r;
+       struct usb_device *udev;
+       struct usb_req_rfwrite *req = NULL;
+       int i, req_len, actual_req_len;
+       u16 bit_value_template;
+
+       if (in_atomic()) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: io in atomic context not supported\n");
+               return -EWOULDBLOCK;
+       }
+       if (bits < USB_MIN_RFWRITE_BIT_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: bits %d are smaller than"
+                       " USB_MIN_RFWRITE_BIT_COUNT %d\n",
+                       bits, USB_MIN_RFWRITE_BIT_COUNT);
+               return -EINVAL;
+       }
+       if (bits > USB_MAX_RFWRITE_BIT_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n",
+                       bits, USB_MAX_RFWRITE_BIT_COUNT);
+               return -EINVAL;
+       }
+#ifdef DEBUG
+       if (value & (~0UL << bits)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: value %#09x has bits >= %d set\n",
+                       value, bits);
+               return -EINVAL;
+       }
+#endif /* DEBUG */
+
+       dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits);
+
+       r = zd_usb_ioread16(usb, &bit_value_template, CR203);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error %d: Couldn't read CR203\n", r);
+               goto out;
+       }
+       bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
+
+       req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
+       req = kmalloc(req_len, GFP_NOFS);
+       if (!req)
+               return -ENOMEM;
+
+       req->id = cpu_to_le16(USB_REQ_WRITE_RF);
+       /* 1: 3683a, but not used in ZYDAS driver */
+       req->value = cpu_to_le16(2);
+       req->bits = cpu_to_le16(bits);
+
+       for (i = 0; i < bits; i++) {
+               u16 bv = bit_value_template;
+               if (value & (1 << (bits-1-i)))
+                       bv |= RF_DATA;
+               req->bit_values[i] = cpu_to_le16(bv);
+       }
+
+       udev = zd_usb_to_usbdev(usb);
+       r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
+                        req, req_len, &actual_req_len, 1000 /* ms */);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in usb_bulk_msg(). Error number %d\n", r);
+               goto out;
+       }
+       if (req_len != actual_req_len) {
+               dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()"
+                       " req_len %d != actual_req_len %d\n",
+                       req_len, actual_req_len);
+               r = -EIO;
+               goto out;
+       }
+
+       /* FALL-THROUGH with r == 0 */
+out:
+       kfree(req);
+       return r;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
new file mode 100644 (file)
index 0000000..d642028
--- /dev/null
@@ -0,0 +1,240 @@
+/* zd_usb.h: Header for USB interface implemented by ZD1211 chip
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 _ZD_USB_H
+#define _ZD_USB_H
+
+#include <linux/completion.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+
+#include "zd_def.h"
+#include "zd_types.h"
+
+enum devicetype {
+       DEVICE_ZD1211  = 0,
+       DEVICE_ZD1211B = 1,
+};
+
+enum endpoints {
+       EP_CTRL     = 0,
+       EP_DATA_OUT = 1,
+       EP_DATA_IN  = 2,
+       EP_INT_IN   = 3,
+       EP_REGS_OUT = 4,
+};
+
+enum {
+       USB_MAX_TRANSFER_SIZE           = 4096, /* bytes */
+       /* FIXME: The original driver uses this value. We have to check,
+        * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be
+        * used if one combined frame is split over two USB transactions.
+        */
+       USB_MAX_RX_SIZE                 = 4800, /* bytes */
+       USB_MAX_IOWRITE16_COUNT         = 15,
+       USB_MAX_IOWRITE32_COUNT         = USB_MAX_IOWRITE16_COUNT/2,
+       USB_MAX_IOREAD16_COUNT          = 15,
+       USB_MAX_IOREAD32_COUNT          = USB_MAX_IOREAD16_COUNT/2,
+       USB_MIN_RFWRITE_BIT_COUNT       = 16,
+       USB_MAX_RFWRITE_BIT_COUNT       = 28,
+       USB_MAX_EP_INT_BUFFER           = 64,
+       USB_ZD1211B_BCD_DEVICE          = 0x4810,
+};
+
+enum control_requests {
+       USB_REQ_WRITE_REGS              = 0x21,
+       USB_REQ_READ_REGS               = 0x22,
+       USB_REQ_WRITE_RF                = 0x23,
+       USB_REQ_PROG_FLASH              = 0x24,
+       USB_REQ_EEPROM_START            = 0x0128, /* ? request is a byte */
+       USB_REQ_EEPROM_MID              = 0x28,
+       USB_REQ_EEPROM_END              = 0x0228, /* ? request is a byte */
+       USB_REQ_FIRMWARE_DOWNLOAD       = 0x30,
+       USB_REQ_FIRMWARE_CONFIRM        = 0x31,
+       USB_REQ_FIRMWARE_READ_DATA      = 0x32,
+};
+
+struct usb_req_read_regs {
+       __le16 id;
+       __le16 addr[0];
+} __attribute__((packed));
+
+struct reg_data {
+       __le16 addr;
+       __le16 value;
+} __attribute__((packed));
+
+struct usb_req_write_regs {
+       __le16 id;
+       struct reg_data reg_writes[0];
+} __attribute__((packed));
+
+enum {
+       RF_IF_LE = 0x02,
+       RF_CLK   = 0x04,
+       RF_DATA  = 0x08,
+};
+
+struct usb_req_rfwrite {
+       __le16 id;
+       __le16 value;
+       /* 1: 3683a */
+       /* 2: other (default) */
+       __le16 bits;
+       /* RF2595: 24 */
+       __le16 bit_values[0];
+       /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
+} __attribute__((packed));
+
+/* USB interrupt */
+
+enum usb_int_id {
+       USB_INT_TYPE                    = 0x01,
+       USB_INT_ID_REGS                 = 0x90,
+       USB_INT_ID_RETRY_FAILED         = 0xa0,
+};
+
+enum usb_int_flags {
+       USB_INT_READ_REGS_EN            = 0x01,
+};
+
+struct usb_int_header {
+       u8 type;        /* must always be 1 */
+       u8 id;
+} __attribute__((packed));
+
+struct usb_int_regs {
+       struct usb_int_header hdr;
+       struct reg_data regs[0];
+} __attribute__((packed));
+
+struct usb_int_retry_fail {
+       struct usb_int_header hdr;
+       u8 new_rate;
+       u8 _dummy;
+       u8 addr[ETH_ALEN];
+       u8 ibss_wakeup_dest;
+} __attribute__((packed));
+
+struct read_regs_int {
+       struct completion completion;
+       /* Stores the USB int structure and contains the USB address of the
+        * first requested register before request.
+        */
+       u8 buffer[USB_MAX_EP_INT_BUFFER];
+       int length;
+       __le16 cr_int_addr;
+};
+
+struct zd_ioreq16 {
+       zd_addr_t addr;
+       u16 value;
+};
+
+struct zd_ioreq32 {
+       zd_addr_t addr;
+       u32 value;
+};
+
+struct zd_usb_interrupt {
+       struct read_regs_int read_regs;
+       spinlock_t lock;
+       struct urb *urb;
+       int interval;
+       u8 read_regs_enabled:1;
+};
+
+static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
+{
+       return (struct usb_int_regs *)intr->read_regs.buffer;
+}
+
+#define URBS_COUNT 5
+
+struct zd_usb_rx {
+       spinlock_t lock;
+       u8 fragment[2*USB_MAX_RX_SIZE];
+       unsigned int fragment_length;
+       unsigned int usb_packet_size;
+       struct urb **urbs;
+       int urbs_count;
+};
+
+struct zd_usb_tx {
+       spinlock_t lock;
+};
+
+/* Contains the usb parts. The structure doesn't require a lock, because intf
+ * and fw_base_offset, will not be changed after initialization.
+ */
+struct zd_usb {
+       struct zd_usb_interrupt intr;
+       struct zd_usb_rx rx;
+       struct zd_usb_tx tx;
+       struct usb_interface *intf;
+       u16 fw_base_offset;
+};
+
+#define zd_usb_dev(usb) (&usb->intf->dev)
+
+static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb)
+{
+       return interface_to_usbdev(usb->intf);
+}
+
+static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf)
+{
+       return usb_get_intfdata(intf);
+}
+
+static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb)
+{
+       return zd_intf_to_netdev(usb->intf);
+}
+
+void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
+                struct usb_interface *intf);
+int zd_usb_init_hw(struct zd_usb *usb);
+void zd_usb_clear(struct zd_usb *usb);
+
+int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
+
+int zd_usb_enable_int(struct zd_usb *usb);
+void zd_usb_disable_int(struct zd_usb *usb);
+
+int zd_usb_enable_rx(struct zd_usb *usb);
+void zd_usb_disable_rx(struct zd_usb *usb);
+
+int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length);
+
+int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
+                const zd_addr_t *addresses, unsigned int count);
+
+static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value,
+                             const zd_addr_t addr)
+{
+       return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1);
+}
+
+int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+                     unsigned int count);
+
+int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
+
+#endif /* _ZD_USB_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_util.c b/drivers/net/wireless/zd1211rw/zd_util.c
new file mode 100644 (file)
index 0000000..d20036c
--- /dev/null
@@ -0,0 +1,82 @@
+/* zd_util.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Utility program
+ */
+
+#include "zd_def.h"
+#include "zd_util.h"
+
+#ifdef DEBUG
+static char hex(u8 v)
+{
+       v &= 0xf;
+       return (v < 10 ? '0' : 'a' - 10) + v;
+}
+
+static char hex_print(u8 c)
+{
+       return (0x20 <= c && c < 0x7f) ? c : '.';
+}
+
+static void dump_line(const u8 *bytes, size_t size)
+{
+       char c;
+       size_t i;
+
+       size = size <= 8 ? size : 8;
+       printk(KERN_DEBUG "zd1211 %p ", bytes);
+       for (i = 0; i < 8; i++) {
+               switch (i) {
+               case 1:
+               case 5:
+                       c = '.';
+                       break;
+               case 3:
+                       c = ':';
+                       break;
+               default:
+                       c = ' ';
+               }
+               if (i < size) {
+                       printk("%c%c%c", hex(bytes[i] >> 4), hex(bytes[i]), c);
+               } else {
+                       printk("  %c", c);
+               }
+       }
+
+       for (i = 0; i < size; i++)
+               printk("%c", hex_print(bytes[i]));
+       printk("\n");
+}
+
+void zd_hexdump(const void *bytes, size_t size)
+{
+       size_t i = 0;
+
+       do {
+               dump_line((u8 *)bytes + i, size-i);
+               i += 8;
+       } while (i < size);
+}
+#endif /* DEBUG */
+
+void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size)
+{
+       if (buffer_size < tail_size)
+               return NULL;
+       return (u8 *)buffer + (buffer_size - tail_size);
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_util.h b/drivers/net/wireless/zd1211rw/zd_util.h
new file mode 100644 (file)
index 0000000..ce26f7a
--- /dev/null
@@ -0,0 +1,29 @@
+/* zd_util.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ZD_UTIL_H
+#define _ZD_UTIL_H
+
+void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size);
+
+#ifdef DEBUG
+void zd_hexdump(const void *bytes, size_t size);
+#else
+#define zd_hexdump(bytes, size)
+#endif /* DEBUG */
+
+#endif /* _ZD_UTIL_H */
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
new file mode 100644 (file)
index 0000000..1850632
--- /dev/null
@@ -0,0 +1,443 @@
+/* linux/drivers/parport/parport_ax88796.c
+ *
+ * (c) 2005,2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/parport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define AX_SPR_BUSY            (1<<7)
+#define AX_SPR_ACK             (1<<6)
+#define AX_SPR_PE              (1<<5)
+#define AX_SPR_SLCT            (1<<4)
+#define AX_SPR_ERR             (1<<3)
+
+#define AX_CPR_nDOE            (1<<5)
+#define AX_CPR_SLCTIN          (1<<3)
+#define AX_CPR_nINIT           (1<<2)
+#define AX_CPR_ATFD            (1<<1)
+#define AX_CPR_STRB            (1<<0)
+
+struct ax_drvdata {
+       struct parport          *parport;
+       struct parport_state     suspend;
+
+       struct device           *dev;
+       struct resource         *io;
+
+       unsigned char            irq_enabled;
+
+       void __iomem            *base;
+       void __iomem            *spp_data;
+       void __iomem            *spp_spr;
+       void __iomem            *spp_cpr;
+};
+
+static inline struct ax_drvdata *pp_to_drv(struct parport *p)
+{
+       return p->private_data;
+}
+
+static unsigned char
+parport_ax88796_read_data(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       return readb(dd->spp_data);
+}
+
+static void
+parport_ax88796_write_data(struct parport *p, unsigned char data)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       writeb(data, dd->spp_data);
+}
+
+static unsigned char
+parport_ax88796_read_control(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       unsigned int cpr = readb(dd->spp_cpr);
+       unsigned int ret = 0;
+
+       if (!(cpr & AX_CPR_STRB))
+               ret |= PARPORT_CONTROL_STROBE;
+
+       if (!(cpr & AX_CPR_ATFD))
+               ret |= PARPORT_CONTROL_AUTOFD;
+
+       if (cpr & AX_CPR_nINIT)
+               ret |= PARPORT_CONTROL_INIT;
+
+       if (!(cpr & AX_CPR_SLCTIN))
+               ret |= PARPORT_CONTROL_SELECT;
+
+       return ret;
+}
+
+static void
+parport_ax88796_write_control(struct parport *p, unsigned char control)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       unsigned int cpr = readb(dd->spp_cpr);
+
+       cpr &= AX_CPR_nDOE;
+
+       if (!(control & PARPORT_CONTROL_STROBE))
+               cpr |= AX_CPR_STRB;
+
+       if (!(control & PARPORT_CONTROL_AUTOFD))
+               cpr |= AX_CPR_ATFD;
+
+       if (control & PARPORT_CONTROL_INIT)
+               cpr |= AX_CPR_nINIT;
+
+       if (!(control & PARPORT_CONTROL_SELECT))
+               cpr |= AX_CPR_SLCTIN;
+
+       dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr);
+       writeb(cpr, dd->spp_cpr);
+
+       if (parport_ax88796_read_control(p) != control) {
+               dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n",
+                       parport_ax88796_read_control(p), control);
+       }
+}
+
+static unsigned char
+parport_ax88796_read_status(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       unsigned int status = readb(dd->spp_spr);
+       unsigned int ret = 0;
+
+       if (status & AX_SPR_BUSY)
+               ret |= PARPORT_STATUS_BUSY;
+
+       if (status & AX_SPR_ACK)
+               ret |= PARPORT_STATUS_ACK;
+
+       if (status & AX_SPR_ERR)
+               ret |= PARPORT_STATUS_ERROR;
+
+       if (status & AX_SPR_SLCT)
+               ret |= PARPORT_STATUS_SELECT;
+
+       if (status & AX_SPR_PE)
+               ret |= PARPORT_STATUS_PAPEROUT;
+
+       return ret;
+}
+
+static unsigned char
+parport_ax88796_frob_control(struct parport *p, unsigned char mask,
+                            unsigned char val)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       unsigned char old = parport_ax88796_read_control(p);
+
+       dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n",
+               mask, val, old);
+
+       parport_ax88796_write_control(p, (old & ~mask) | val);
+       return old;
+}
+
+static void
+parport_ax88796_enable_irq(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (!dd->irq_enabled) {
+               enable_irq(p->irq);
+               dd->irq_enabled = 1;
+       }
+       local_irq_restore(flags);
+}
+
+static void
+parport_ax88796_disable_irq(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (dd->irq_enabled) {
+               disable_irq(p->irq);
+               dd->irq_enabled = 0;
+       }
+       local_irq_restore(flags);
+}
+
+static void
+parport_ax88796_data_forward(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       void __iomem *cpr = dd->spp_cpr;
+
+       writeb((readb(cpr) & ~AX_CPR_nDOE), cpr);
+}
+
+static void
+parport_ax88796_data_reverse(struct parport *p)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+       void __iomem *cpr = dd->spp_cpr;
+
+       writeb(readb(cpr) | AX_CPR_nDOE, cpr);
+}
+
+static void
+parport_ax88796_init_state(struct pardevice *d, struct parport_state *s)
+{
+       struct ax_drvdata *dd = pp_to_drv(d->port);
+
+       memset(s, 0, sizeof(struct parport_state));
+
+       dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s);
+       s->u.ax88796.cpr = readb(dd->spp_cpr);
+}
+
+static void
+parport_ax88796_save_state(struct parport *p, struct parport_state *s)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s);
+       s->u.ax88796.cpr = readb(dd->spp_cpr);
+}
+
+static void
+parport_ax88796_restore_state(struct parport *p, struct parport_state *s)
+{
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s);
+       writeb(s->u.ax88796.cpr, dd->spp_cpr);
+}
+
+static irqreturn_t
+parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+        parport_generic_irq(irq, dev_id, regs);
+        return IRQ_HANDLED;
+}
+
+
+static struct parport_operations parport_ax88796_ops = {
+       .write_data     = parport_ax88796_write_data,
+       .read_data      = parport_ax88796_read_data,
+
+       .write_control  = parport_ax88796_write_control,
+       .read_control   = parport_ax88796_read_control,
+       .frob_control   = parport_ax88796_frob_control,
+
+       .read_status    = parport_ax88796_read_status,
+
+       .enable_irq     = parport_ax88796_enable_irq,
+       .disable_irq    = parport_ax88796_disable_irq,
+
+       .data_forward   = parport_ax88796_data_forward,
+       .data_reverse   = parport_ax88796_data_reverse,
+
+       .init_state     = parport_ax88796_init_state,
+       .save_state     = parport_ax88796_save_state,
+       .restore_state  = parport_ax88796_restore_state,
+
+       .epp_write_data = parport_ieee1284_epp_write_data,
+       .epp_read_data  = parport_ieee1284_epp_read_data,
+       .epp_write_addr = parport_ieee1284_epp_write_addr,
+       .epp_read_addr  = parport_ieee1284_epp_read_addr,
+
+       .ecp_write_data = parport_ieee1284_ecp_write_data,
+       .ecp_read_data  = parport_ieee1284_ecp_read_data,
+       .ecp_write_addr = parport_ieee1284_ecp_write_addr,
+
+       .compat_write_data      = parport_ieee1284_write_compat,
+       .nibble_read_data       = parport_ieee1284_read_nibble,
+       .byte_read_data         = parport_ieee1284_read_byte,
+
+       .owner          = THIS_MODULE,
+};
+
+static int parport_ax88796_probe(struct platform_device *pdev)
+{
+       struct device *_dev = &pdev->dev;
+       struct ax_drvdata *dd;
+       struct parport *pp = NULL;
+       struct resource *res;
+       unsigned long size;
+       int spacing;
+       int irq;
+       int ret;
+
+       dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL);
+       if (dd == NULL) {
+               dev_err(_dev, "no memory for private data\n");
+               return -ENOMEM;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(_dev, "no MEM specified\n");
+               ret = -ENXIO;
+               goto exit_mem;
+       }
+
+       size = (res->end - res->start) + 1;
+       spacing = size / 3;
+
+       dd->io = request_mem_region(res->start, size, pdev->name);
+       if (dd->io == NULL) {
+               dev_err(_dev, "cannot reserve memory\n");
+               ret = -ENXIO;
+               goto exit_mem;
+       }
+
+       dd->base = ioremap(res->start, size);
+       if (dd->base == NULL) {
+               dev_err(_dev, "cannot ioremap region\n");
+               ret = -ENXIO;
+               goto exit_res;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               irq = PARPORT_IRQ_NONE;
+
+       pp = parport_register_port((unsigned long)dd->base, irq,
+                                  PARPORT_DMA_NONE,
+                                  &parport_ax88796_ops);
+
+       if (pp == NULL) {
+               dev_err(_dev, "failed to register parallel port\n");
+               ret = -ENOMEM;
+               goto exit_unmap;
+       }
+
+       pp->private_data = dd;
+       dd->parport = pp;
+       dd->dev = _dev;
+
+       dd->spp_data = dd->base;
+       dd->spp_spr  = dd->base + (spacing * 1);
+       dd->spp_cpr  = dd->base + (spacing * 2);
+
+       /* initialise the port controls */
+       writeb(AX_CPR_STRB, dd->spp_cpr);
+
+       if (irq >= 0) {
+               /* request irq */
+               ret = request_irq(irq, parport_ax88796_interrupt,
+                                 IRQF_TRIGGER_FALLING, pdev->name, pp);
+
+               if (ret < 0)
+                       goto exit_port;
+
+               dd->irq_enabled = 1;
+       }
+
+       platform_set_drvdata(pdev, pp);
+
+       dev_info(_dev, "attached parallel port driver\n");
+       parport_announce_port(pp);
+
+       return 0;
+
+ exit_port:
+       parport_remove_port(pp);
+ exit_unmap:
+       iounmap(dd->base);
+ exit_res:
+       release_resource(dd->io);
+       kfree(dd->io);
+ exit_mem:
+       kfree(dd);
+       return ret;
+}
+
+static int parport_ax88796_remove(struct platform_device *pdev)
+{
+       struct parport *p = platform_get_drvdata(pdev);
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       free_irq(p->irq, p);
+       parport_remove_port(p);
+       iounmap(dd->base);
+       release_resource(dd->io);
+       kfree(dd->io);
+       kfree(dd);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int parport_ax88796_suspend(struct platform_device *dev,
+                                  pm_message_t state)
+{
+       struct parport *p = platform_get_drvdata(dev);
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       parport_ax88796_save_state(p, &dd->suspend);
+       writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr);
+       return 0;
+}
+
+static int parport_ax88796_resume(struct platform_device *dev)
+{
+       struct parport *p = platform_get_drvdata(dev);
+       struct ax_drvdata *dd = pp_to_drv(p);
+
+       parport_ax88796_restore_state(p, &dd->suspend);
+       return 0;
+}
+
+#else
+#define parport_ax88796_suspend NULL
+#define parport_ax88796_resume  NULL
+#endif
+
+static struct platform_driver axdrv = {
+       .driver         = {
+               .name   = "ax88796-pp",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = parport_ax88796_probe,
+       .remove         = parport_ax88796_remove,
+       .suspend        = parport_ax88796_suspend,
+       .resume         = parport_ax88796_resume,
+};
+
+static int __init parport_ax88796_init(void)
+{
+       return platform_driver_register(&axdrv);
+}
+
+static void __exit parport_ax88796_exit(void)
+{
+       platform_driver_unregister(&axdrv);
+}
+
+module_init(parport_ax88796_init)
+module_exit(parport_ax88796_exit)
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("AX88796 Parport parallel port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c
new file mode 100644 (file)
index 0000000..bed4183
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * 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) 2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/cpumask.h>
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/nodepda.h>
+
+#include "msi.h"
+
+struct sn_msi_info {
+       u64 pci_addr;
+       struct sn_irq_info *sn_irq_info;
+};
+
+static struct sn_msi_info *sn_msi_info;
+
+static void
+sn_msi_teardown(unsigned int vector)
+{
+       nasid_t nasid;
+       int widget;
+       struct pci_dev *pdev;
+       struct pcidev_info *sn_pdev;
+       struct sn_irq_info *sn_irq_info;
+       struct pcibus_bussoft *bussoft;
+       struct sn_pcibus_provider *provider;
+
+       sn_irq_info = sn_msi_info[vector].sn_irq_info;
+       if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+               return;
+
+       sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+       pdev = sn_pdev->pdi_linux_pcidev;
+       provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+       (*provider->dma_unmap)(pdev,
+                              sn_msi_info[vector].pci_addr,
+                              PCI_DMA_FROMDEVICE);
+       sn_msi_info[vector].pci_addr = 0;
+
+       bussoft = SN_PCIDEV_BUSSOFT(pdev);
+       nasid = NASID_GET(bussoft->bs_base);
+       widget = (nasid & 1) ?
+                       TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+                       SWIN_WIDGETNUM(bussoft->bs_base);
+
+       sn_intr_free(nasid, widget, sn_irq_info);
+       sn_msi_info[vector].sn_irq_info = NULL;
+
+       return;
+}
+
+int
+sn_msi_setup(struct pci_dev *pdev, unsigned int vector,
+            u32 *addr_hi, u32 *addr_lo, u32 *data)
+{
+       int widget;
+       int status;
+       nasid_t nasid;
+       u64 bus_addr;
+       struct sn_irq_info *sn_irq_info;
+       struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+       if (bussoft == NULL)
+               return -EINVAL;
+
+       if (provider == NULL || provider->dma_map_consistent == NULL)
+               return -EINVAL;
+
+       /*
+        * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
+        * decide which cpu to direct this msi at by default.
+        */
+
+       nasid = NASID_GET(bussoft->bs_base);
+       widget = (nasid & 1) ?
+                       TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+                       SWIN_WIDGETNUM(bussoft->bs_base);
+
+       sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+       if (! sn_irq_info)
+               return -ENOMEM;
+
+       status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1);
+       if (status) {
+               kfree(sn_irq_info);
+               return -ENOMEM;
+       }
+
+       sn_irq_info->irq_int_bit = -1;          /* mark this as an MSI irq */
+       sn_irq_fixup(pdev, sn_irq_info);
+
+       /* Prom probably should fill these in, but doesn't ... */
+       sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
+       sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
+
+       /*
+        * Map the xio address into bus space
+        */
+       bus_addr = (*provider->dma_map_consistent)(pdev,
+                                       sn_irq_info->irq_xtalkaddr,
+                                       sizeof(sn_irq_info->irq_xtalkaddr),
+                                       SN_DMA_MSI|SN_DMA_ADDR_XIO);
+       if (! bus_addr) {
+               sn_intr_free(nasid, widget, sn_irq_info);
+               kfree(sn_irq_info);
+               return -ENOMEM;
+       }
+
+       sn_msi_info[vector].sn_irq_info = sn_irq_info;
+       sn_msi_info[vector].pci_addr = bus_addr;
+
+       *addr_hi = (u32)(bus_addr >> 32);
+       *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+       /*
+        * In the SN platform, bit 16 is a "send vector" bit which
+        * must be present in order to move the vector through the system.
+        */
+       *data = 0x100 + (unsigned int)vector;
+
+#ifdef CONFIG_SMP
+       set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0);
+#endif
+
+       return 0;
+}
+
+static void
+sn_msi_target(unsigned int vector, unsigned int cpu,
+             u32 *addr_hi, u32 *addr_lo)
+{
+       int slice;
+       nasid_t nasid;
+       u64 bus_addr;
+       struct pci_dev *pdev;
+       struct pcidev_info *sn_pdev;
+       struct sn_irq_info *sn_irq_info;
+       struct sn_irq_info *new_irq_info;
+       struct sn_pcibus_provider *provider;
+
+       sn_irq_info = sn_msi_info[vector].sn_irq_info;
+       if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+               return;
+
+       /*
+        * Release XIO resources for the old MSI PCI address
+        */
+
+        sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+       pdev = sn_pdev->pdi_linux_pcidev;
+       provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+       bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo);
+       (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
+       sn_msi_info[vector].pci_addr = 0;
+
+       nasid = cpuid_to_nasid(cpu);
+       slice = cpuid_to_slice(cpu);
+
+       new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
+       sn_msi_info[vector].sn_irq_info = new_irq_info;
+       if (new_irq_info == NULL)
+               return;
+
+       /*
+        * Map the xio address into bus space
+        */
+
+       bus_addr = (*provider->dma_map_consistent)(pdev,
+                                       new_irq_info->irq_xtalkaddr,
+                                       sizeof(new_irq_info->irq_xtalkaddr),
+                                       SN_DMA_MSI|SN_DMA_ADDR_XIO);
+
+       sn_msi_info[vector].pci_addr = bus_addr;
+       *addr_hi = (u32)(bus_addr >> 32);
+       *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+}
+
+struct msi_ops sn_msi_ops = {
+       .setup = sn_msi_setup,
+       .teardown = sn_msi_teardown,
+#ifdef CONFIG_SMP
+       .target = sn_msi_target,
+#endif
+};
+
+int
+sn_msi_init(void)
+{
+       sn_msi_info =
+               kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL);
+       if (! sn_msi_info)
+               return -ENOMEM;
+
+       msi_register(&sn_msi_ops);
+       return 0;
+}
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
new file mode 100644 (file)
index 0000000..5ed798b
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * MSI hooks for standard x86 apic
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/smp.h>
+
+#include "msi.h"
+
+/*
+ * Shifts for APIC-based data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT          0
+#define            MSI_DATA_VECTOR(v)          (((u8)v) << MSI_DATA_VECTOR_SHIFT)
+
+#define MSI_DATA_DELIVERY_SHIFT                8
+#define     MSI_DATA_DELIVERY_FIXED    (0 << MSI_DATA_DELIVERY_SHIFT)
+#define     MSI_DATA_DELIVERY_LOWPRI   (1 << MSI_DATA_DELIVERY_SHIFT)
+
+#define MSI_DATA_LEVEL_SHIFT           14
+#define     MSI_DATA_LEVEL_DEASSERT    (0 << MSI_DATA_LEVEL_SHIFT)
+#define     MSI_DATA_LEVEL_ASSERT      (1 << MSI_DATA_LEVEL_SHIFT)
+
+#define MSI_DATA_TRIGGER_SHIFT         15
+#define     MSI_DATA_TRIGGER_EDGE      (0 << MSI_DATA_TRIGGER_SHIFT)
+#define     MSI_DATA_TRIGGER_LEVEL     (1 << MSI_DATA_TRIGGER_SHIFT)
+
+/*
+ * Shift/mask fields for APIC-based bus address
+ */
+
+#define MSI_ADDR_HEADER                        0xfee00000
+
+#define MSI_ADDR_DESTID_MASK           0xfff0000f
+#define     MSI_ADDR_DESTID_CPU(cpu)   ((cpu) << MSI_TARGET_CPU_SHIFT)
+
+#define MSI_ADDR_DESTMODE_SHIFT                2
+#define     MSI_ADDR_DESTMODE_PHYS     (0 << MSI_ADDR_DESTMODE_SHIFT)
+#define            MSI_ADDR_DESTMODE_LOGIC     (1 << MSI_ADDR_DESTMODE_SHIFT)
+
+#define MSI_ADDR_REDIRECTION_SHIFT     3
+#define     MSI_ADDR_REDIRECTION_CPU   (0 << MSI_ADDR_REDIRECTION_SHIFT)
+#define     MSI_ADDR_REDIRECTION_LOWPRI        (1 << MSI_ADDR_REDIRECTION_SHIFT)
+
+
+static void
+msi_target_apic(unsigned int vector,
+               unsigned int dest_cpu,
+               u32 *address_hi,        /* in/out */
+               u32 *address_lo)        /* in/out */
+{
+       u32 addr = *address_lo;
+
+       addr &= MSI_ADDR_DESTID_MASK;
+       addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu));
+
+       *address_lo = addr;
+}
+
+static int
+msi_setup_apic(struct pci_dev *pdev,   /* unused in generic */
+               unsigned int vector,
+               u32 *address_hi,
+               u32 *address_lo,
+               u32 *data)
+{
+       unsigned long   dest_phys_id;
+
+       dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
+
+       *address_hi = 0;
+       *address_lo =   MSI_ADDR_HEADER |
+                       MSI_ADDR_DESTMODE_PHYS |
+                       MSI_ADDR_REDIRECTION_CPU |
+                       MSI_ADDR_DESTID_CPU(dest_phys_id);
+
+       *data = MSI_DATA_TRIGGER_EDGE |
+               MSI_DATA_LEVEL_ASSERT |
+               MSI_DATA_DELIVERY_FIXED |
+               MSI_DATA_VECTOR(vector);
+
+       return 0;
+}
+
+static void
+msi_teardown_apic(unsigned int vector)
+{
+       return;         /* no-op */
+}
+
+/*
+ * Generic ops used on most IA archs/platforms.  Set with msi_register()
+ */
+
+struct msi_ops msi_apic_ops = {
+       .setup = msi_setup_apic,
+       .teardown = msi_teardown_apic,
+       .target = msi_target_apic,
+};
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c
new file mode 100644 (file)
index 0000000..dfd0ce8
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ *     Real Time Clock interface for Linux on Atmel AT91RM9200
+ *
+ *     Copyright (C) 2002 Rick Bronson
+ *
+ *     Converted to RTC class model by Andrew Victor
+ *
+ *     Ported to Linux 2.6 by Steven Scholz
+ *     Based on s3c2410-rtc.c Simtec Electronics
+ *
+ *     Based on sa1100-rtc.c by Nils Faerber
+ *     Based on rtc.c 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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/completion.h>
+
+#include <asm/uaccess.h>
+#include <asm/rtc.h>
+
+#include <asm/mach/time.h>
+
+
+#define AT91_RTC_FREQ          1
+#define AT91_RTC_EPOCH         1900UL  /* just like arch/arm/common/rtctime.c */
+
+static DECLARE_COMPLETION(at91_rtc_updated);
+static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
+
+/*
+ * Decode time/date into rtc_time structure
+ */
+static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
+                               struct rtc_time *tm)
+{
+       unsigned int time, date;
+
+       /* must read twice in case it changes */
+       do {
+               time = at91_sys_read(timereg);
+               date = at91_sys_read(calreg);
+       } while ((time != at91_sys_read(timereg)) ||
+                       (date != at91_sys_read(calreg)));
+
+       tm->tm_sec  = BCD2BIN((time & AT91_RTC_SEC) >> 0);
+       tm->tm_min  = BCD2BIN((time & AT91_RTC_MIN) >> 8);
+       tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16);
+
+       /*
+        * The Calendar Alarm register does not have a field for
+        * the year - so these will return an invalid value.  When an
+        * alarm is set, at91_alarm_year wille store the current year.
+        */
+       tm->tm_year  = BCD2BIN(date & AT91_RTC_CENT) * 100;     /* century */
+       tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8);    /* year */
+
+       tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
+       tm->tm_mon  = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1;
+       tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24);
+}
+
+/*
+ * Read current time and date in RTC
+ */
+static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+       at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
+       tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+       tm->tm_year = tm->tm_year - 1900;
+
+       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+               1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       return 0;
+}
+
+/*
+ * Set current time and date in RTC
+ */
+static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+       unsigned long cr;
+
+       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+               1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       /* Stop Time/Calendar from counting */
+       cr = at91_sys_read(AT91_RTC_CR);
+       at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
+
+       at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD);
+       wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */
+       at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
+
+       at91_sys_write(AT91_RTC_TIMR,
+                         BIN2BCD(tm->tm_sec) << 0
+                       | BIN2BCD(tm->tm_min) << 8
+                       | BIN2BCD(tm->tm_hour) << 16);
+
+       at91_sys_write(AT91_RTC_CALR,
+                         BIN2BCD((tm->tm_year + 1900) / 100)   /* century */
+                       | BIN2BCD(tm->tm_year % 100) << 8       /* year */
+                       | BIN2BCD(tm->tm_mon + 1) << 16         /* tm_mon starts at zero */
+                       | BIN2BCD(tm->tm_wday + 1) << 21        /* day of the week [0-6], Sunday=0 */
+                       | BIN2BCD(tm->tm_mday) << 24);
+
+       /* Restart Time/Calendar */
+       cr = at91_sys_read(AT91_RTC_CR);
+       at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
+
+       return 0;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rtc_time *tm = &alrm->time;
+
+       at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
+       tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+       tm->tm_year = at91_alarm_year - 1900;
+
+       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+               1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       return 0;
+}
+
+/*
+ * Set alarm time and date in RTC
+ */
+static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rtc_time tm;
+
+       at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);
+
+       at91_alarm_year = tm.tm_year;
+
+       tm.tm_hour = alrm->time.tm_hour;
+       tm.tm_min = alrm->time.tm_min;
+       tm.tm_sec = alrm->time.tm_sec;
+
+       at91_sys_write(AT91_RTC_TIMALR,
+                 BIN2BCD(tm.tm_sec) << 0
+               | BIN2BCD(tm.tm_min) << 8
+               | BIN2BCD(tm.tm_hour) << 16
+               | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
+       at91_sys_write(AT91_RTC_CALALR,
+                 BIN2BCD(tm.tm_mon + 1) << 16          /* tm_mon starts at zero */
+               | BIN2BCD(tm.tm_mday) << 24
+               | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
+
+       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+               at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
+               tm.tm_min, tm.tm_sec);
+
+       return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
+                       unsigned long arg)
+{
+       int ret = 0;
+
+       pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg);
+
+       switch (cmd) {
+       case RTC_AIE_OFF:       /* alarm off */
+               at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
+               break;
+       case RTC_AIE_ON:        /* alarm on */
+               at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+               break;
+       case RTC_UIE_OFF:       /* update off */
+       case RTC_PIE_OFF:       /* periodic off */
+               at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
+               break;
+       case RTC_UIE_ON:        /* update on */
+       case RTC_PIE_ON:        /* periodic on */
+               at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
+               break;
+       case RTC_IRQP_READ:     /* read periodic alarm frequency */
+               ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
+               break;
+       case RTC_IRQP_SET:      /* set periodic alarm frequency */
+               if (arg != AT91_RTC_FREQ)
+                       ret = -EINVAL;
+               break;
+       default:
+               ret = -ENOIOCTLCMD;
+               break;
+       }
+
+       return ret;
+}
+
+/*
+ * Provide additional RTC information in /proc/driver/rtc
+ */
+static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       unsigned long imr = at91_sys_read(AT91_RTC_IMR);
+
+       seq_printf(seq, "alarm_IRQ\t: %s\n",
+                       (imr & AT91_RTC_ALARM) ? "yes" : "no");
+       seq_printf(seq, "update_IRQ\t: %s\n",
+                       (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;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id,
+                                       struct pt_regs *regs)
+{
+       struct platform_device *pdev = dev_id;
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
+       unsigned int rtsr;
+       unsigned long events = 0;
+
+       rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR);
+       if (rtsr) {             /* this interrupt is shared!  Is it ours? */
+               if (rtsr & AT91_RTC_ALARM)
+                       events |= (RTC_AF | RTC_IRQF);
+               if (rtsr & AT91_RTC_SECEV)
+                       events |= (RTC_UF | RTC_IRQF);
+               if (rtsr & AT91_RTC_ACKUPD)
+                       complete(&at91_rtc_updated);
+
+               at91_sys_write(AT91_RTC_SCCR, rtsr);    /* clear status reg */
+
+               rtc_update_irq(&rtc->class_dev, 1, events);
+
+               pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__,
+                       events >> 8, events & 0x000000FF);
+
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;                /* not handled */
+}
+
+static struct rtc_class_ops at91_rtc_ops = {
+       .ioctl          = at91_rtc_ioctl,
+       .read_time      = at91_rtc_readtime,
+       .set_time       = at91_rtc_settime,
+       .read_alarm     = at91_rtc_readalarm,
+       .set_alarm      = at91_rtc_setalarm,
+       .proc           = at91_rtc_proc,
+};
+
+/*
+ * Initialize and install RTC driver
+ */
+static int __init at91_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       int ret;
+
+       at91_sys_write(AT91_RTC_CR, 0);
+       at91_sys_write(AT91_RTC_MR, 0);         /* 24 hour mode */
+
+       /* Disable all interrupts */
+       at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+                                       AT91_RTC_SECEV | AT91_RTC_TIMEV |
+                                       AT91_RTC_CALEV);
+
+       ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
+                               IRQF_SHARED, "at91_rtc", pdev);
+       if (ret) {
+               printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
+                               AT91_ID_SYS);
+               return ret;
+       }
+
+       rtc = rtc_device_register(pdev->name, &pdev->dev,
+                               &at91_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               free_irq(AT91_ID_SYS, pdev);
+               return PTR_ERR(rtc);
+       }
+       platform_set_drvdata(pdev, rtc);
+
+       printk(KERN_INFO "AT91 Real Time Clock driver.\n");
+       return 0;
+}
+
+/*
+ * Disable and remove the RTC driver
+ */
+static int __devexit at91_rtc_remove(struct platform_device *pdev)
+{
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+       /* Disable all interrupts */
+       at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+                                       AT91_RTC_SECEV | AT91_RTC_TIMEV |
+                                       AT91_RTC_CALEV);
+       free_irq(AT91_ID_SYS, pdev);
+
+       rtc_device_unregister(rtc);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* AT91RM9200 RTC Power management control */
+
+static struct timespec at91_rtc_delta;
+
+static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rtc_time tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+
+       /* calculate time delta for suspend */
+       at91_rtc_readtime(&pdev->dev, &tm);
+       rtc_tm_to_time(&tm, &time.tv_sec);
+       save_time_delta(&at91_rtc_delta, &time);
+
+       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+               1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+       return 0;
+}
+
+static int at91_rtc_resume(struct platform_device *pdev)
+{
+       struct rtc_time tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+
+       at91_rtc_readtime(&pdev->dev, &tm);
+       rtc_tm_to_time(&tm, &time.tv_sec);
+       restore_time_delta(&at91_rtc_delta, &time);
+
+       pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+               1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
+               tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+       return 0;
+}
+#else
+#define at91_rtc_suspend NULL
+#define at91_rtc_resume  NULL
+#endif
+
+static struct platform_driver at91_rtc_driver = {
+       .probe          = at91_rtc_probe,
+       .remove         = at91_rtc_remove,
+       .suspend        = at91_rtc_suspend,
+       .resume         = at91_rtc_resume,
+       .driver         = {
+               .name   = "at91_rtc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init at91_rtc_init(void)
+{
+       return platform_driver_register(&at91_rtc_driver);
+}
+
+static void __exit at91_rtc_exit(void)
+{
+       platform_driver_unregister(&at91_rtc_driver);
+}
+
+module_init(at91_rtc_init);
+module_exit(at91_rtc_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
new file mode 100644 (file)
index 0000000..e8afb93
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips.
+ *
+ *  Copyright (C) 2005 James Chapman (ds1337 core)
+ *  Copyright (C) 2006 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+
+
+/* We can't determine type by probing, but if we expect pre-Linux code
+ * 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.
+ *
+ * If the I2C "force" mechanism is used, we assume the chip is a ds1337.
+ * (Much better would be board-specific tables of I2C devices, along with
+ * the platform_data drivers would use to sort such issues out.)
+ */
+enum ds_type {
+       unknown = 0,
+       ds_1307,                /* or ds1338, ... */
+       ds_1337,                /* or ds1339, ... */
+       ds_1340,                /* or st m41t00, ... */
+       // rs5c372 too?  different address...
+};
+
+static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+
+
+/* RTC registers don't differ much, except for the century flag */
+#define DS1307_REG_SECS                0x00    /* 00-59 */
+#      define DS1307_BIT_CH            0x80
+#define DS1307_REG_MIN         0x01    /* 00-59 */
+#define DS1307_REG_HOUR                0x02    /* 00-23, or 1-12{am,pm} */
+#      define DS1340_BIT_CENTURY_EN    0x80    /* in REG_HOUR */
+#      define DS1340_BIT_CENTURY       0x40    /* in REG_HOUR */
+#define DS1307_REG_WDAY                0x03    /* 01-07 */
+#define DS1307_REG_MDAY                0x04    /* 01-31 */
+#define DS1307_REG_MONTH       0x05    /* 01-12 */
+#      define DS1337_BIT_CENTURY       0x80    /* in REG_MONTH */
+#define DS1307_REG_YEAR                0x06    /* 00-99 */
+
+/* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
+ * start at 7, and they differ a lot. Only control and status matter for RTC;
+ * be careful using them.
+ */
+#define DS1307_REG_CONTROL     0x07
+#      define DS1307_BIT_OUT           0x80
+#      define DS1307_BIT_SQWE          0x10
+#      define DS1307_BIT_RS1           0x02
+#      define DS1307_BIT_RS0           0x01
+#define DS1337_REG_CONTROL     0x0e
+#      define DS1337_BIT_nEOSC         0x80
+#      define DS1337_BIT_RS2           0x10
+#      define DS1337_BIT_RS1           0x08
+#      define DS1337_BIT_INTCN         0x04
+#      define DS1337_BIT_A2IE          0x02
+#      define DS1337_BIT_A1IE          0x01
+#define DS1337_REG_STATUS      0x0f
+#      define DS1337_BIT_OSF           0x80
+#      define DS1337_BIT_A2I           0x02
+#      define DS1337_BIT_A1I           0x01
+#define DS1339_REG_TRICKLE     0x10
+
+
+
+struct ds1307 {
+       u8                      reg_addr;
+       u8                      regs[8];
+       enum ds_type            type;
+       struct i2c_msg          msg[2];
+       struct i2c_client       client;
+       struct rtc_device       *rtc;
+};
+
+
+static int ds1307_get_time(struct device *dev, struct rtc_time *t)
+{
+       struct ds1307   *ds1307 = dev_get_drvdata(dev);
+       int             tmp;
+
+       /* read the RTC registers all at once */
+       ds1307->msg[1].flags = I2C_M_RD;
+       ds1307->msg[1].len = 7;
+
+       tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2);
+       if (tmp != 2) {
+               dev_err(dev, "%s error %d\n", "read", tmp);
+               return -EIO;
+       }
+
+       dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+                       "read",
+                       ds1307->regs[0], ds1307->regs[1],
+                       ds1307->regs[2], ds1307->regs[3],
+                       ds1307->regs[4], ds1307->regs[5],
+                       ds1307->regs[6]);
+
+       t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f);
+       t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+       tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
+       t->tm_hour = BCD2BIN(tmp);
+       t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
+       t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+       tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
+       t->tm_mon = BCD2BIN(tmp) - 1;
+
+       /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
+       t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100;
+
+       dev_dbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+               "read", t->tm_sec, t->tm_min,
+               t->tm_hour, t->tm_mday,
+               t->tm_mon, t->tm_year, t->tm_wday);
+
+       return 0;
+}
+
+static int ds1307_set_time(struct device *dev, struct rtc_time *t)
+{
+       struct ds1307   *ds1307 = dev_get_drvdata(dev);
+       int             result;
+       int             tmp;
+       u8              *buf = ds1307->regs;
+
+       dev_dbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+               "write", dt->tm_sec, dt->tm_min,
+               dt->tm_hour, dt->tm_mday,
+               dt->tm_mon, dt->tm_year, dt->tm_wday);
+
+       *buf++ = 0;             /* first register addr */
+       buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec);
+       buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min);
+       buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour);
+       buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1);
+       buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday);
+       buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1);
+
+       /* assume 20YY not 19YY */
+       tmp = t->tm_year - 100;
+       buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
+
+       if (ds1307->type == ds_1337)
+               buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
+       else if (ds1307->type == ds_1340)
+               buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
+                               | DS1340_BIT_CENTURY;
+
+       ds1307->msg[1].flags = 0;
+       ds1307->msg[1].len = 8;
+
+       dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+               "write", buf[0], buf[1], buf[2], buf[3],
+               buf[4], buf[5], buf[6]);
+
+       result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1);
+       if (result != 1) {
+               dev_err(dev, "%s error %d\n", "write", tmp);
+               return -EIO;
+       }
+       return 0;
+}
+
+static struct rtc_class_ops ds13xx_rtc_ops = {
+       .read_time      = ds1307_get_time,
+       .set_time       = ds1307_set_time,
+};
+
+static struct i2c_driver ds1307_driver;
+
+static int __devinit
+ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct ds1307           *ds1307;
+       int                     err = -ENODEV;
+       struct i2c_client       *client;
+       int                     tmp;
+
+       if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       client = &ds1307->client;
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &ds1307_driver;
+       client->flags = 0;
+
+       i2c_set_clientdata(client, ds1307);
+
+       ds1307->msg[0].addr = client->addr;
+       ds1307->msg[0].flags = 0;
+       ds1307->msg[0].len = 1;
+       ds1307->msg[0].buf = &ds1307->reg_addr;
+
+       ds1307->msg[1].addr = client->addr;
+       ds1307->msg[1].flags = I2C_M_RD;
+       ds1307->msg[1].len = sizeof(ds1307->regs);
+       ds1307->msg[1].buf = ds1307->regs;
+
+       /* HACK: "force" implies "needs ds1337-style-oscillator setup" */
+       if (kind >= 0) {
+               ds1307->type = ds_1337;
+
+               ds1307->reg_addr = DS1337_REG_CONTROL;
+               ds1307->msg[1].len = 2;
+
+               tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+               if (tmp != 2) {
+                       pr_debug("read error %d\n", tmp);
+                       err = -EIO;
+                       goto exit_free;
+               }
+
+               ds1307->reg_addr = 0;
+               ds1307->msg[1].len = sizeof(ds1307->regs);
+
+               /* oscillator is off; need to turn it on */
+               if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
+                               || (ds1307->regs[1] & DS1337_BIT_OSF)) {
+                       printk(KERN_ERR "no ds1337 oscillator code\n");
+                       goto exit_free;
+               }
+       } else
+               ds1307->type = ds_1307;
+
+read_rtc:
+       /* read RTC registers */
+
+       tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+       if (tmp != 2) {
+               pr_debug("read error %d\n", tmp);
+               err = -EIO;
+               goto exit_free;
+       }
+
+       /* minimal sanity checking; some chips (like DS1340) don't
+        * specify the extra bits as must-be-zero, but there are
+        * still a few values that are clearly out-of-range.
+        */
+       tmp = ds1307->regs[DS1307_REG_SECS];
+       if (tmp & DS1307_BIT_CH) {
+               if (ds1307->type && ds1307->type != ds_1307) {
+                       pr_debug("not a ds1307?\n");
+                       goto exit_free;
+               }
+               ds1307->type = ds_1307;
+
+               /* this partial initialization should work for ds1307,
+                * ds1338, ds1340, st m41t00, and more.
+                */
+               dev_warn(&client->dev, "oscillator started; SET TIME!\n");
+               i2c_smbus_write_byte_data(client, 0, 0);
+               goto read_rtc;
+       }
+       tmp = BCD2BIN(tmp & 0x7f);
+       if (tmp > 60)
+               goto exit_free;
+       tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+       if (tmp > 60)
+               goto exit_free;
+
+       tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+       if (tmp == 0 || tmp > 31)
+               goto exit_free;
+
+       tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
+       if (tmp == 0 || tmp > 12)
+               goto exit_free;
+
+       /* force into in 24 hour mode (most chips) or
+        * disable century bit (ds1340)
+        */
+       tmp = ds1307->regs[DS1307_REG_HOUR];
+       if (tmp & (1 << 6)) {
+               if (tmp & (1 << 5))
+                       tmp = BCD2BIN(tmp & 0x1f) + 12;
+               else
+                       tmp = BCD2BIN(tmp);
+               i2c_smbus_write_byte_data(client,
+                               DS1307_REG_HOUR,
+                               BIN2BCD(tmp));
+       }
+
+       /* FIXME chips like 1337 can generate alarm irqs too; those are
+        * worth exposing through the API (especially when the irq is
+        * wakeup-capable).
+        */
+
+       switch (ds1307->type) {
+       case unknown:
+               strlcpy(client->name, "unknown", I2C_NAME_SIZE);
+               break;
+       case ds_1307:
+               strlcpy(client->name, "ds1307", I2C_NAME_SIZE);
+               break;
+       case ds_1337:
+               strlcpy(client->name, "ds1337", I2C_NAME_SIZE);
+               break;
+       case ds_1340:
+               strlcpy(client->name, "ds1340", I2C_NAME_SIZE);
+               break;
+       }
+
+       /* Tell the I2C layer a new client has arrived */
+       if ((err = i2c_attach_client(client)))
+               goto exit_free;
+
+       ds1307->rtc = rtc_device_register(client->name, &client->dev,
+                               &ds13xx_rtc_ops, THIS_MODULE);
+       if (IS_ERR(ds1307->rtc)) {
+               err = PTR_ERR(ds1307->rtc);
+               dev_err(&client->dev,
+                       "unable to register the class device\n");
+               goto exit_detach;
+       }
+
+       return 0;
+
+exit_detach:
+       i2c_detach_client(client);
+exit_free:
+       kfree(ds1307);
+exit:
+       return err;
+}
+
+static int __devinit
+ds1307_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+               return 0;
+       return i2c_probe(adapter, &addr_data, ds1307_detect);
+}
+
+static int __devexit ds1307_detach_client(struct i2c_client *client)
+{
+       int             err;
+       struct ds1307   *ds1307 = i2c_get_clientdata(client);
+
+       rtc_device_unregister(ds1307->rtc);
+       if ((err = i2c_detach_client(client)))
+               return err;
+       kfree(ds1307);
+       return 0;
+}
+
+static struct i2c_driver ds1307_driver = {
+       .driver = {
+               .name   = "ds1307",
+               .owner  = THIS_MODULE,
+       },
+       .attach_adapter = ds1307_attach_adapter,
+       .detach_client  = __devexit_p(ds1307_detach_client),
+};
+
+static int __init ds1307_init(void)
+{
+       return i2c_add_driver(&ds1307_driver);
+}
+module_init(ds1307_init);
+
+static void __exit ds1307_exit(void)
+{
+       i2c_del_driver(&ds1307_driver);
+}
+module_exit(ds1307_exit);
+
+MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
new file mode 100644 (file)
index 0000000..2090014
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * An rtc driver for the Dallas DS1553
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * This program is free software; you can 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/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.1"
+
+#define RTC_REG_SIZE           0x2000
+#define RTC_OFFSET             0x1ff0
+
+#define RTC_FLAGS              (RTC_OFFSET + 0)
+#define RTC_SECONDS_ALARM      (RTC_OFFSET + 2)
+#define RTC_MINUTES_ALARM      (RTC_OFFSET + 3)
+#define RTC_HOURS_ALARM                (RTC_OFFSET + 4)
+#define RTC_DATE_ALARM         (RTC_OFFSET + 5)
+#define RTC_INTERRUPTS         (RTC_OFFSET + 6)
+#define RTC_WATCHDOG           (RTC_OFFSET + 7)
+#define RTC_CONTROL            (RTC_OFFSET + 8)
+#define RTC_CENTURY            (RTC_OFFSET + 8)
+#define RTC_SECONDS            (RTC_OFFSET + 9)
+#define RTC_MINUTES            (RTC_OFFSET + 10)
+#define RTC_HOURS              (RTC_OFFSET + 11)
+#define RTC_DAY                        (RTC_OFFSET + 12)
+#define RTC_DATE               (RTC_OFFSET + 13)
+#define RTC_MONTH              (RTC_OFFSET + 14)
+#define RTC_YEAR               (RTC_OFFSET + 15)
+
+#define RTC_CENTURY_MASK       0x3f
+#define RTC_SECONDS_MASK       0x7f
+#define RTC_DAY_MASK           0x07
+
+/* Bits in the Control/Century register */
+#define RTC_WRITE              0x80
+#define RTC_READ               0x40
+
+/* Bits in the Seconds register */
+#define RTC_STOP               0x80
+
+/* Bits in the Flags register */
+#define RTC_FLAGS_AF           0x40
+#define RTC_FLAGS_BLF          0x10
+
+/* Bits in the Interrupts register */
+#define RTC_INTS_AE            0x80
+
+struct rtc_plat_data {
+       struct rtc_device *rtc;
+       void __iomem *ioaddr;
+       unsigned long baseaddr;
+       unsigned long last_jiffies;
+       int irq;
+       unsigned int irqen;
+       int alrm_sec;
+       int alrm_min;
+       int alrm_hour;
+       int alrm_mday;
+};
+
+static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       u8 century;
+
+       century = BIN2BCD((tm->tm_year + 1900) / 100);
+
+       writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL);
+
+       writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
+       writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+       writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+       writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
+       writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
+       writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
+       writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+
+       /* RTC_CENTURY and RTC_CONTROL share same register */
+       writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
+       writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+       return 0;
+}
+
+static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       unsigned int year, month, day, hour, minute, second, week;
+       unsigned int century;
+
+       /* give enough time to update RTC in case of continuous read */
+       if (pdata->last_jiffies == jiffies)
+               msleep(1);
+       pdata->last_jiffies = jiffies;
+       writeb(RTC_READ, ioaddr + RTC_CONTROL);
+       second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
+       minute = readb(ioaddr + RTC_MINUTES);
+       hour = readb(ioaddr + RTC_HOURS);
+       day = readb(ioaddr + RTC_DATE);
+       week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
+       month = readb(ioaddr + RTC_MONTH);
+       year = readb(ioaddr + RTC_YEAR);
+       century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+       writeb(0, ioaddr + RTC_CONTROL);
+       tm->tm_sec = BCD2BIN(second);
+       tm->tm_min = BCD2BIN(minute);
+       tm->tm_hour = BCD2BIN(hour);
+       tm->tm_mday = BCD2BIN(day);
+       tm->tm_wday = BCD2BIN(week);
+       tm->tm_mon = BCD2BIN(month) - 1;
+       /* year is 1900 + tm->tm_year */
+       tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+
+       if (rtc_valid_tm(tm) < 0) {
+               dev_err(dev, "retrieved date/time is not valid.\n");
+               rtc_time_to_tm(0, tm);
+       }
+       return 0;
+}
+
+static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
+{
+       void __iomem *ioaddr = pdata->ioaddr;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
+       writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
+              0x80 : BIN2BCD(pdata->alrm_mday),
+              ioaddr + RTC_DATE_ALARM);
+       writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
+              0x80 : BIN2BCD(pdata->alrm_hour),
+              ioaddr + RTC_HOURS_ALARM);
+       writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
+              0x80 : BIN2BCD(pdata->alrm_min),
+              ioaddr + RTC_MINUTES_ALARM);
+       writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
+              0x80 : BIN2BCD(pdata->alrm_sec),
+              ioaddr + RTC_SECONDS_ALARM);
+       writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
+       readb(ioaddr + RTC_FLAGS);      /* clear interrupts */
+       spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
+}
+
+static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+       if (pdata->irq < 0)
+               return -EINVAL;
+       pdata->alrm_mday = alrm->time.tm_mday;
+       pdata->alrm_hour = alrm->time.tm_hour;
+       pdata->alrm_min = alrm->time.tm_min;
+       pdata->alrm_sec = alrm->time.tm_sec;
+       if (alrm->enabled)
+               pdata->irqen |= RTC_AF;
+       ds1553_rtc_update_alarm(pdata);
+       return 0;
+}
+
+static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+       if (pdata->irq < 0)
+               return -EINVAL;
+       alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
+       alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
+       alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
+       alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec;
+       alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0;
+       return 0;
+}
+
+static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id,
+                                       struct pt_regs *regs)
+{
+       struct platform_device *pdev = dev_id;
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       unsigned long events = RTC_IRQF;
+
+       /* read and clear interrupt */
+       if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF))
+               return IRQ_NONE;
+       if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
+               events |= RTC_UF;
+       else
+               events |= RTC_AF;
+       rtc_update_irq(&pdata->rtc->class_dev, 1, events);
+       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)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+       if (pdata->irq < 0)
+               return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
+       switch (cmd) {
+       case RTC_AIE_OFF:
+               pdata->irqen &= ~RTC_AF;
+               ds1553_rtc_update_alarm(pdata);
+               break;
+       case RTC_AIE_ON:
+               pdata->irqen |= RTC_AF;
+               ds1553_rtc_update_alarm(pdata);
+               break;
+       case RTC_UIE_OFF:
+               pdata->irqen &= ~RTC_UF;
+               ds1553_rtc_update_alarm(pdata);
+               break;
+       case RTC_UIE_ON:
+               pdata->irqen |= RTC_UF;
+               ds1553_rtc_update_alarm(pdata);
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static struct rtc_class_ops ds1553_rtc_ops = {
+       .read_time      = ds1553_rtc_read_time,
+       .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,
+};
+
+static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
+                                loff_t pos, size_t size)
+{
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       ssize_t count;
+
+       for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+               *buf++ = readb(ioaddr + pos++);
+       return count;
+}
+
+static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
+                                 loff_t pos, size_t size)
+{
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       ssize_t count;
+
+       for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+               writeb(*buf++, ioaddr + pos++);
+       return count;
+}
+
+static struct bin_attribute ds1553_nvram_attr = {
+       .attr = {
+               .name = "nvram",
+               .mode = S_IRUGO | S_IWUGO,
+               .owner = THIS_MODULE,
+       },
+       .size = RTC_OFFSET,
+       .read = ds1553_nvram_read,
+       .write = ds1553_nvram_write,
+};
+
+static int __init ds1553_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       struct resource *res;
+       unsigned int cen, sec;
+       struct rtc_plat_data *pdata = NULL;
+       void __iomem *ioaddr = NULL;
+       int ret = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+       pdata->irq = -1;
+       if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+               ret = -EBUSY;
+               goto out;
+       }
+       pdata->baseaddr = res->start;
+       ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+       if (!ioaddr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       pdata->ioaddr = ioaddr;
+       pdata->irq = platform_get_irq(pdev, 0);
+
+       /* turn RTC on if it was not on */
+       sec = readb(ioaddr + RTC_SECONDS);
+       if (sec & RTC_STOP) {
+               sec &= RTC_SECONDS_MASK;
+               cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+               writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+               writeb(sec, ioaddr + RTC_SECONDS);
+               writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+       }
+       if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
+               dev_warn(&pdev->dev, "voltage-low detected.\n");
+
+       if (pdata->irq >= 0) {
+               writeb(0, ioaddr + RTC_INTERRUPTS);
+               if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED,
+                               pdev->name, pdev) < 0) {
+                       dev_warn(&pdev->dev, "interrupt not available.\n");
+                       pdata->irq = -1;
+               }
+       }
+
+       rtc = rtc_device_register(pdev->name, &pdev->dev,
+                                 &ds1553_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               goto out;
+       }
+       pdata->rtc = rtc;
+       pdata->last_jiffies = jiffies;
+       platform_set_drvdata(pdev, pdata);
+       sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+       return 0;
+ out:
+       if (pdata->irq >= 0)
+               free_irq(pdata->irq, pdev);
+       if (ioaddr)
+               iounmap(ioaddr);
+       if (pdata->baseaddr)
+               release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+       kfree(pdata);
+       return ret;
+}
+
+static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
+{
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+       sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+       rtc_device_unregister(pdata->rtc);
+       if (pdata->irq >= 0) {
+               writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
+               free_irq(pdata->irq, pdev);
+       }
+       iounmap(pdata->ioaddr);
+       release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+       kfree(pdata);
+       return 0;
+}
+
+static struct platform_driver ds1553_rtc_driver = {
+       .probe          = ds1553_rtc_probe,
+       .remove         = __devexit_p(ds1553_rtc_remove),
+       .driver         = {
+               .name   = "ds1553",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static __init int ds1553_init(void)
+{
+       return platform_driver_register(&ds1553_rtc_driver);
+}
+
+static __exit void ds1553_exit(void)
+{
+       return platform_driver_unregister(&ds1553_rtc_driver);
+}
+
+module_init(ds1553_init);
+module_exit(ds1553_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Dallas DS1553 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
new file mode 100644 (file)
index 0000000..8e47e5a
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * An rtc driver for the Dallas DS1742
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * This program is free software; you can 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/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.1"
+
+#define RTC_REG_SIZE           0x800
+#define RTC_OFFSET             0x7f8
+
+#define RTC_CONTROL            (RTC_OFFSET + 0)
+#define RTC_CENTURY            (RTC_OFFSET + 0)
+#define RTC_SECONDS            (RTC_OFFSET + 1)
+#define RTC_MINUTES            (RTC_OFFSET + 2)
+#define RTC_HOURS              (RTC_OFFSET + 3)
+#define RTC_DAY                        (RTC_OFFSET + 4)
+#define RTC_DATE               (RTC_OFFSET + 5)
+#define RTC_MONTH              (RTC_OFFSET + 6)
+#define RTC_YEAR               (RTC_OFFSET + 7)
+
+#define RTC_CENTURY_MASK       0x3f
+#define RTC_SECONDS_MASK       0x7f
+#define RTC_DAY_MASK           0x07
+
+/* Bits in the Control/Century register */
+#define RTC_WRITE              0x80
+#define RTC_READ               0x40
+
+/* Bits in the Seconds register */
+#define RTC_STOP               0x80
+
+/* Bits in the Day register */
+#define RTC_BATT_FLAG          0x80
+
+struct rtc_plat_data {
+       struct rtc_device *rtc;
+       void __iomem *ioaddr;
+       unsigned long baseaddr;
+       unsigned long last_jiffies;
+};
+
+static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       u8 century;
+
+       century = BIN2BCD((tm->tm_year + 1900) / 100);
+
+       writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+
+       writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
+       writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+       writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+       writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
+       writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
+       writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
+       writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+
+       /* RTC_CENTURY and RTC_CONTROL share same register */
+       writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
+       writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+       return 0;
+}
+
+static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       unsigned int year, month, day, hour, minute, second, week;
+       unsigned int century;
+
+       /* give enough time to update RTC in case of continuous read */
+       if (pdata->last_jiffies == jiffies)
+               msleep(1);
+       pdata->last_jiffies = jiffies;
+       writeb(RTC_READ, ioaddr + RTC_CONTROL);
+       second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
+       minute = readb(ioaddr + RTC_MINUTES);
+       hour = readb(ioaddr + RTC_HOURS);
+       day = readb(ioaddr + RTC_DATE);
+       week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
+       month = readb(ioaddr + RTC_MONTH);
+       year = readb(ioaddr + RTC_YEAR);
+       century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+       writeb(0, ioaddr + RTC_CONTROL);
+       tm->tm_sec = BCD2BIN(second);
+       tm->tm_min = BCD2BIN(minute);
+       tm->tm_hour = BCD2BIN(hour);
+       tm->tm_mday = BCD2BIN(day);
+       tm->tm_wday = BCD2BIN(week);
+       tm->tm_mon = BCD2BIN(month) - 1;
+       /* year is 1900 + tm->tm_year */
+       tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+
+       if (rtc_valid_tm(tm) < 0) {
+               dev_err(dev, "retrieved date/time is not valid.\n");
+               rtc_time_to_tm(0, tm);
+       }
+       return 0;
+}
+
+static struct rtc_class_ops ds1742_rtc_ops = {
+       .read_time      = ds1742_rtc_read_time,
+       .set_time       = ds1742_rtc_set_time,
+};
+
+static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
+                                loff_t pos, size_t size)
+{
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       ssize_t count;
+
+       for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+               *buf++ = readb(ioaddr + pos++);
+       return count;
+}
+
+static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
+                                 loff_t pos, size_t size)
+{
+       struct platform_device *pdev =
+               to_platform_device(container_of(kobj, struct device, kobj));
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+       void __iomem *ioaddr = pdata->ioaddr;
+       ssize_t count;
+
+       for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+               writeb(*buf++, ioaddr + pos++);
+       return count;
+}
+
+static struct bin_attribute ds1742_nvram_attr = {
+       .attr = {
+               .name = "nvram",
+               .mode = S_IRUGO | S_IWUGO,
+               .owner = THIS_MODULE,
+       },
+       .size = RTC_OFFSET,
+       .read = ds1742_nvram_read,
+       .write = ds1742_nvram_write,
+};
+
+static int __init ds1742_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       struct resource *res;
+       unsigned int cen, sec;
+       struct rtc_plat_data *pdata = NULL;
+       void __iomem *ioaddr = NULL;
+       int ret = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+       if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+               ret = -EBUSY;
+               goto out;
+       }
+       pdata->baseaddr = res->start;
+       ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+       if (!ioaddr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       pdata->ioaddr = ioaddr;
+
+       /* turn RTC on if it was not on */
+       sec = readb(ioaddr + RTC_SECONDS);
+       if (sec & RTC_STOP) {
+               sec &= RTC_SECONDS_MASK;
+               cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+               writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+               writeb(sec, ioaddr + RTC_SECONDS);
+               writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+       }
+       if (readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)
+               dev_warn(&pdev->dev, "voltage-low detected.\n");
+
+       rtc = rtc_device_register(pdev->name, &pdev->dev,
+                                 &ds1742_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               goto out;
+       }
+       pdata->rtc = rtc;
+       pdata->last_jiffies = jiffies;
+       platform_set_drvdata(pdev, pdata);
+       sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+       return 0;
+ out:
+       if (ioaddr)
+               iounmap(ioaddr);
+       if (pdata->baseaddr)
+               release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+       kfree(pdata);
+       return ret;
+}
+
+static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
+{
+       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+       sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+       rtc_device_unregister(pdata->rtc);
+       iounmap(pdata->ioaddr);
+       release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+       kfree(pdata);
+       return 0;
+}
+
+static struct platform_driver ds1742_rtc_driver = {
+       .probe          = ds1742_rtc_probe,
+       .remove         = __devexit_p(ds1742_rtc_remove),
+       .driver         = {
+               .name   = "ds1742",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static __init int ds1742_init(void)
+{
+       return platform_driver_register(&ds1742_rtc_driver);
+}
+
+static __exit void ds1742_exit(void)
+{
+       return platform_driver_unregister(&ds1742_rtc_driver);
+}
+
+module_init(ds1742_init);
+module_exit(ds1742_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
new file mode 100644 (file)
index 0000000..f324d0a
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * Intersil ISL1208 rtc class driver
+ *
+ * Copyright 2005,2006 Hebert Valerio Riedel <hvr@gnu.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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+
+#define DRV_NAME "isl1208"
+#define DRV_VERSION "0.2"
+
+/* Register map */
+/* rtc section */
+#define ISL1208_REG_SC  0x00
+#define ISL1208_REG_MN  0x01
+#define ISL1208_REG_HR  0x02
+#define ISL1208_REG_HR_MIL     (1<<7) /* 24h/12h mode */
+#define ISL1208_REG_HR_PM      (1<<5) /* PM/AM bit in 12h mode */
+#define ISL1208_REG_DT  0x03
+#define ISL1208_REG_MO  0x04
+#define ISL1208_REG_YR  0x05
+#define ISL1208_REG_DW  0x06
+#define ISL1208_RTC_SECTION_LEN 7
+
+/* control/status section */
+#define ISL1208_REG_SR  0x07
+#define ISL1208_REG_SR_ARST    (1<<7) /* auto reset */
+#define ISL1208_REG_SR_XTOSCB  (1<<6) /* crystal oscillator */
+#define ISL1208_REG_SR_WRTC    (1<<4) /* write rtc */
+#define ISL1208_REG_SR_ALM     (1<<2) /* alarm */
+#define ISL1208_REG_SR_BAT     (1<<1) /* battery */
+#define ISL1208_REG_SR_RTCF    (1<<0) /* rtc fail */
+#define ISL1208_REG_INT 0x08
+#define ISL1208_REG_09  0x09 /* reserved */
+#define ISL1208_REG_ATR 0x0a
+#define ISL1208_REG_DTR 0x0b
+
+/* alarm section */
+#define ISL1208_REG_SCA 0x0c
+#define ISL1208_REG_MNA 0x0d
+#define ISL1208_REG_HRA 0x0e
+#define ISL1208_REG_DTA 0x0f
+#define ISL1208_REG_MOA 0x10
+#define ISL1208_REG_DWA 0x11
+#define ISL1208_ALARM_SECTION_LEN 6
+
+/* user section */
+#define ISL1208_REG_USR1 0x12
+#define ISL1208_REG_USR2 0x13
+#define ISL1208_USR_SECTION_LEN 2
+
+/* i2c configuration */
+#define ISL1208_I2C_ADDR 0xde
+
+static unsigned short normal_i2c[] = {
+       ISL1208_I2C_ADDR>>1, I2C_CLIENT_END
+};
+I2C_CLIENT_INSMOD; /* defines addr_data */
+
+static int isl1208_attach_adapter(struct i2c_adapter *adapter);
+static int isl1208_detach_client(struct i2c_client *client);
+
+static struct i2c_driver isl1208_driver = {
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+       .id             = I2C_DRIVERID_ISL1208,
+       .attach_adapter = &isl1208_attach_adapter,
+       .detach_client  = &isl1208_detach_client,
+};
+
+/* block read */
+static int
+isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
+                      unsigned len)
+{
+       u8 reg_addr[1] = { reg };
+       struct i2c_msg msgs[2] = {
+               { client->addr, client->flags, sizeof(reg_addr), reg_addr },
+               { client->addr, client->flags | I2C_M_RD, len, buf }
+       };
+       int ret;
+
+       BUG_ON(len == 0);
+       BUG_ON(reg > ISL1208_REG_USR2);
+       BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+
+       ret = i2c_transfer(client->adapter, msgs, 2);
+       if (ret > 0)
+               ret = 0;
+       return ret;
+}
+
+/* block write */
+static int
+isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+                      unsigned len)
+{
+       u8 i2c_buf[ISL1208_REG_USR2 + 2];
+       struct i2c_msg msgs[1] = {
+               { client->addr, client->flags, len + 1, i2c_buf }
+       };
+       int ret;
+
+       BUG_ON(len == 0);
+       BUG_ON(reg > ISL1208_REG_USR2);
+       BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+
+       i2c_buf[0] = reg;
+       memcpy(&i2c_buf[1], &buf[0], len);
+
+       ret = i2c_transfer(client->adapter, msgs, 1);
+       if (ret > 0)
+               ret = 0;
+       return ret;
+}
+
+/* simple check to see wether we have a isl1208 */
+static int isl1208_i2c_validate_client(struct i2c_client *client)
+{
+       u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+       u8 zero_mask[ISL1208_RTC_SECTION_LEN] = {
+               0x80, 0x80, 0x40, 0xc0, 0xe0, 0x00, 0xf8
+       };
+       int i;
+       int ret;
+
+       ret = isl1208_i2c_read_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < ISL1208_RTC_SECTION_LEN; ++i) {
+               if (regs[i] & zero_mask[i]) /* check if bits are cleared */
+                       return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int isl1208_i2c_get_sr(struct i2c_client *client)
+{
+       return i2c_smbus_read_byte_data(client, ISL1208_REG_SR) == -1 ? -EIO:0;
+}
+
+static int isl1208_i2c_get_atr(struct i2c_client *client)
+{
+       int atr = i2c_smbus_read_byte_data(client, ISL1208_REG_ATR);
+
+       if (atr < 0)
+               return -EIO;
+
+       /* The 6bit value in the ATR register controls the load
+        * capacitance C_load * in steps of 0.25pF
+        *
+        * bit (1<<5) of the ATR register is inverted
+        *
+        * C_load(ATR=0x20) =  4.50pF
+        * C_load(ATR=0x00) = 12.50pF
+        * C_load(ATR=0x1f) = 20.25pF
+        *
+        */
+
+       atr &= 0x3f; /* mask out lsb */
+       atr ^= 1<<5; /* invert 6th bit */
+       atr += 2*9; /* add offset of 4.5pF; unit[atr] = 0.25pF */
+
+       return atr;
+}
+
+static int isl1208_i2c_get_dtr(struct i2c_client *client)
+{
+       int dtr = i2c_smbus_read_byte_data(client, ISL1208_REG_DTR);
+
+       if (dtr < 0)
+               return -EIO;
+
+       /* dtr encodes adjustments of {-60,-40,-20,0,20,40,60} ppm */
+       dtr = ((dtr & 0x3) * 20) * (dtr & (1<<2) ? -1 : 1);
+
+       return dtr;
+}
+
+static int isl1208_i2c_get_usr(struct i2c_client *client)
+{
+       u8 buf[ISL1208_USR_SECTION_LEN] = { 0, };
+       int ret;
+
+       ret = isl1208_i2c_read_regs (client, ISL1208_REG_USR1, buf,
+                                  ISL1208_USR_SECTION_LEN);
+       if (ret < 0)
+               return ret;
+
+       return (buf[1] << 8) | buf[0];
+}
+
+static int isl1208_i2c_set_usr(struct i2c_client *client, u16 usr)
+{
+       u8 buf[ISL1208_USR_SECTION_LEN];
+
+       buf[0] = usr & 0xff;
+       buf[1] = (usr >> 8) & 0xff;
+
+       return isl1208_i2c_set_regs (client, ISL1208_REG_USR1, buf,
+                                    ISL1208_USR_SECTION_LEN);
+}
+
+static int isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       struct i2c_client *const client = to_i2c_client(dev);
+       int sr, dtr, atr, usr;
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       seq_printf(seq, "status_reg\t:%s%s%s%s%s%s (0x%.2x)\n",
+                  (sr & ISL1208_REG_SR_RTCF) ? " RTCF" : "",
+                  (sr & ISL1208_REG_SR_BAT) ? " BAT" : "",
+                  (sr & ISL1208_REG_SR_ALM) ? " ALM" : "",
+                  (sr & ISL1208_REG_SR_WRTC) ? " WRTC" : "",
+                  (sr & ISL1208_REG_SR_XTOSCB) ? " XTOSCB" : "",
+                  (sr & ISL1208_REG_SR_ARST) ? " ARST" : "",
+                  sr);
+
+       seq_printf(seq, "batt_status\t: %s\n",
+                  (sr & ISL1208_REG_SR_RTCF) ? "bad" : "okay");
+
+       dtr = isl1208_i2c_get_dtr(client);
+       if (dtr >= 0 -1)
+               seq_printf(seq, "digital_trim\t: %d ppm\n", dtr);
+
+       atr = isl1208_i2c_get_atr(client);
+       if (atr >= 0)
+               seq_printf(seq, "analog_trim\t: %d.%.2d pF\n",
+                          atr>>2, (atr&0x3)*25);
+
+       usr = isl1208_i2c_get_usr(client);
+       if (usr >= 0)
+               seq_printf(seq, "user_data\t: 0x%.4x\n", usr);
+
+       return 0;
+}
+
+
+static int isl1208_i2c_read_time(struct i2c_client *client,
+                                struct rtc_time *tm)
+{
+       int sr;
+       u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+               return -EIO;
+       }
+
+       sr = isl1208_i2c_read_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: reading RTC section failed\n",
+                       __func__);
+               return sr;
+       }
+
+       tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]);
+       tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]);
+       { /* HR field has a more complex interpretation */
+               const u8 _hr = regs[ISL1208_REG_HR];
+               if (_hr & ISL1208_REG_HR_MIL) /* 24h format */
+                       tm->tm_hour = BCD2BIN(_hr & 0x3f);
+               else { // 12h format
+                       tm->tm_hour = BCD2BIN(_hr & 0x1f);
+                       if (_hr & ISL1208_REG_HR_PM) /* PM flag set */
+                               tm->tm_hour += 12;
+               }
+       }
+
+       tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]);
+       tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
+       tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100;
+       tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]);
+
+       return 0;
+}
+
+static int isl1208_i2c_read_alarm(struct i2c_client *client,
+                                 struct rtc_wkalrm *alarm)
+{
+       struct rtc_time *const tm = &alarm->time;
+       u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
+       int sr;
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       sr = isl1208_i2c_read_regs(client, ISL1208_REG_SCA, regs,
+                                 ISL1208_ALARM_SECTION_LEN);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: reading alarm section failed\n",
+                       __func__);
+               return sr;
+       }
+
+       /* MSB of each alarm register is an enable bit */
+       tm->tm_sec  = BCD2BIN(regs[ISL1208_REG_SCA-ISL1208_REG_SCA] & 0x7f);
+       tm->tm_min  = BCD2BIN(regs[ISL1208_REG_MNA-ISL1208_REG_SCA] & 0x7f);
+       tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA-ISL1208_REG_SCA] & 0x3f);
+       tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA-ISL1208_REG_SCA] & 0x3f);
+       tm->tm_mon  = BCD2BIN(regs[ISL1208_REG_MOA-ISL1208_REG_SCA] & 0x1f)-1;
+       tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA-ISL1208_REG_SCA] & 0x03);
+
+       return 0;
+}
+
+static int isl1208_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       return isl1208_i2c_read_time(to_i2c_client(dev), tm);
+}
+
+static int isl1208_i2c_set_time(struct i2c_client *client,
+                               struct rtc_time const *tm)
+{
+       int sr;
+       u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+
+       regs[ISL1208_REG_SC] = BIN2BCD(tm->tm_sec);
+       regs[ISL1208_REG_MN] = BIN2BCD(tm->tm_min);
+       regs[ISL1208_REG_HR] = BIN2BCD(tm->tm_hour) | ISL1208_REG_HR_MIL;
+
+       regs[ISL1208_REG_DT] = BIN2BCD(tm->tm_mday);
+       regs[ISL1208_REG_MO] = BIN2BCD(tm->tm_mon + 1);
+       regs[ISL1208_REG_YR] = BIN2BCD(tm->tm_year - 100);
+
+       regs[ISL1208_REG_DW] = BIN2BCD(tm->tm_wday & 7);
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       /* set WRTC */
+       sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR,
+                                      sr | ISL1208_REG_SR_WRTC);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: writing SR failed\n", __func__);
+               return sr;
+       }
+
+       /* write RTC registers */
+       sr = isl1208_i2c_set_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: writing RTC section failed\n",
+                       __func__);
+               return sr;
+       }
+
+       /* clear WRTC again */
+       sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR,
+                                      sr & ~ISL1208_REG_SR_WRTC);
+       if (sr < 0) {
+               dev_err(&client->dev, "%s: writing SR failed\n", __func__);
+               return sr;
+       }
+
+       return 0;
+}
+
+
+static int isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       return isl1208_i2c_set_time(to_i2c_client(dev), tm);
+}
+
+static int isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm);
+}
+
+static struct rtc_class_ops isl1208_rtc_ops = {
+       .proc           = isl1208_rtc_proc,
+       .read_time      = isl1208_rtc_read_time,
+       .set_time       = isl1208_rtc_set_time,
+       .read_alarm     = isl1208_rtc_read_alarm,
+       //.set_alarm    = isl1208_rtc_set_alarm,
+};
+
+/* sysfs interface */
+
+static ssize_t isl1208_sysfs_show_atrim(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       int atr;
+
+       atr = isl1208_i2c_get_atr(to_i2c_client(dev));
+       if (atr < 0)
+               return atr;
+
+       return sprintf(buf, "%d.%.2d pF\n", atr>>2, (atr&0x3)*25);
+}
+static DEVICE_ATTR(atrim, S_IRUGO, isl1208_sysfs_show_atrim, NULL);
+
+static ssize_t isl1208_sysfs_show_dtrim(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       int dtr;
+
+       dtr = isl1208_i2c_get_dtr(to_i2c_client(dev));
+       if (dtr < 0)
+               return dtr;
+
+       return sprintf(buf, "%d ppm\n", dtr);
+}
+static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL);
+
+static ssize_t isl1208_sysfs_show_usr(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       int usr;
+
+       usr = isl1208_i2c_get_usr(to_i2c_client(dev));
+       if (usr < 0)
+               return usr;
+
+       return sprintf(buf, "0x%.4x\n", usr);
+}
+
+static ssize_t isl1208_sysfs_store_usr(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       int usr = -1;
+
+       if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) {
+               if (sscanf(buf, "%x", &usr) != 1)
+                       return -EINVAL;
+       } else {
+               if (sscanf(buf, "%d", &usr) != 1)
+                       return -EINVAL;
+       }
+
+       if (usr < 0 || usr > 0xffff)
+               return -EINVAL;
+
+       return isl1208_i2c_set_usr(to_i2c_client(dev), usr) ? -EIO : count;
+}
+static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr,
+                  isl1208_sysfs_store_usr);
+
+static int
+isl1208_probe(struct i2c_adapter *adapter, int addr, int kind)
+{
+       int rc = 0;
+       struct i2c_client *new_client = NULL;
+       struct rtc_device *rtc = NULL;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+               rc = -ENODEV;
+               goto failout;
+       }
+
+       new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (new_client == NULL) {
+               rc = -ENOMEM;
+               goto failout;
+       }
+
+       new_client->addr = addr;
+       new_client->adapter = adapter;
+       new_client->driver = &isl1208_driver;
+       new_client->flags = 0;
+       strcpy(new_client->name, DRV_NAME);
+
+       if (kind < 0) {
+               rc = isl1208_i2c_validate_client(new_client);
+               if (rc < 0)
+                       goto failout;
+       }
+
+       rc = i2c_attach_client(new_client);
+       if (rc < 0)
+               goto failout;
+
+       dev_info(&new_client->dev,
+                "chip found, driver version " DRV_VERSION "\n");
+
+       rtc = rtc_device_register(isl1208_driver.driver.name,
+                                 &new_client->dev,
+                                 &isl1208_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc)) {
+               rc = PTR_ERR(rtc);
+               goto failout_detach;
+       }
+
+       i2c_set_clientdata(new_client, rtc);
+
+       rc = isl1208_i2c_get_sr(new_client);
+       if (rc < 0) {
+               dev_err(&new_client->dev, "reading status failed\n");
+               goto failout_unregister;
+       }
+
+       if (rc & ISL1208_REG_SR_RTCF)
+               dev_warn(&new_client->dev, "rtc power failure detected, "
+                        "please set clock.\n");
+
+       rc = device_create_file(&new_client->dev, &dev_attr_atrim);
+       if (rc < 0)
+               goto failout_unregister;
+       rc = device_create_file(&new_client->dev, &dev_attr_dtrim);
+       if (rc < 0)
+               goto failout_atrim;
+       rc = device_create_file(&new_client->dev, &dev_attr_usr);
+       if (rc < 0)
+               goto failout_dtrim;
+
+       return 0;
+
+ failout_dtrim:
+       device_remove_file(&new_client->dev, &dev_attr_dtrim);
+ failout_atrim:
+       device_remove_file(&new_client->dev, &dev_attr_atrim);
+ failout_unregister:
+       rtc_device_unregister(rtc);
+ failout_detach:
+       i2c_detach_client(new_client);
+ failout:
+       kfree(new_client);
+       return rc;
+}
+
+static int
+isl1208_attach_adapter (struct i2c_adapter *adapter)
+{
+       return i2c_probe(adapter, &addr_data, isl1208_probe);
+}
+
+static int
+isl1208_detach_client(struct i2c_client *client)
+{
+       int rc;
+       struct rtc_device *const rtc = i2c_get_clientdata(client);
+
+       if (rtc)
+               rtc_device_unregister(rtc); /* do we need to kfree? */
+
+       rc = i2c_detach_client(client);
+       if (rc)
+               return rc;
+
+       kfree(client);
+
+       return 0;
+}
+
+/* module management */
+
+static int __init isl1208_init(void)
+{
+       return i2c_add_driver(&isl1208_driver);
+}
+
+static void __exit isl1208_exit(void)
+{
+       i2c_del_driver(&isl1208_driver);
+}
+
+MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>");
+MODULE_DESCRIPTION("Intersil ISL1208 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(isl1208_init);
+module_exit(isl1208_exit);
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
new file mode 100644 (file)
index 0000000..480ce6c
--- /dev/null
@@ -0,0 +1,285 @@
+/* drivers/char/max6902.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 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.
+ *
+ * Driver for MAX6902 spi RTC
+ *
+ * Changelog:
+ *
+ * 24-May-2006: Raphael Assenat <raph@8d.com>
+ *                - Major rework
+ *                             Converted to rtc_device and uses the SPI layer.
+ *
+ * ??-???-2005: Someone at Compulab
+ *                - Initial driver creation.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+#include <linux/delay.h>
+
+#define MAX6902_REG_SECONDS            0x01
+#define MAX6902_REG_MINUTES            0x03
+#define MAX6902_REG_HOURS              0x05
+#define MAX6902_REG_DATE               0x07
+#define MAX6902_REG_MONTH              0x09
+#define MAX6902_REG_DAY                        0x0B
+#define MAX6902_REG_YEAR               0x0D
+#define MAX6902_REG_CONTROL            0x0F
+#define MAX6902_REG_CENTURY            0x13
+
+#undef MAX6902_DEBUG
+
+struct max6902 {
+       struct rtc_device *rtc;
+       u8 buf[9]; /* Burst read cmd + 8 registers */
+       u8 tx_buf[2];
+       u8 rx_buf[2];
+};
+
+static void max6902_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 '0' to write */
+       buf[0] = address & 0x7f;
+       buf[1] = data;
+
+       spi_write(spi, buf, 2);
+}
+
+static int max6902_get_reg(struct device *dev, unsigned char address,
+                               unsigned char *data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct max6902 *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));
+       xfer.len = 2;
+       /* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */
+       xfer.tx_buf = chip->tx_buf;
+       xfer.rx_buf = chip->rx_buf;
+
+       /* Set MSB to indicate read */
+       chip->tx_buf[0] = address | 0x80;
+
+       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 max6902_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+       unsigned char tmp;
+       int century;
+       int err;
+       struct spi_device *spi = to_spi_device(dev);
+       struct max6902 *chip = dev_get_drvdata(dev);
+       struct spi_message message;
+       struct spi_transfer xfer;
+       int status;
+
+       err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &tmp);
+       if (err)
+               return err;
+
+       /* build the message */
+       spi_message_init(&message);
+       memset(&xfer, 0, sizeof(xfer));
+       xfer.len = 1 + 7;       /* Burst read command + 7 registers */
+       xfer.tx_buf = chip->buf;
+       xfer.rx_buf = chip->buf;
+       chip->buf[0] = 0xbf;    /* Burst read */
+       spi_message_add_tail(&xfer, &message);
+
+       /* do the i/o */
+       status = spi_sync(spi, &message);
+       if (status == 0)
+               status = message.status;
+       else
+               return status;
+
+       /* The chip sends data in this order:
+        * Seconds, Minutes, Hours, Date, Month, Day, Year */
+       dt->tm_sec      = BCD2BIN(chip->buf[1]);
+       dt->tm_min      = BCD2BIN(chip->buf[2]);
+       dt->tm_hour     = BCD2BIN(chip->buf[3]);
+       dt->tm_mday     = BCD2BIN(chip->buf[4]);
+       dt->tm_mon      = BCD2BIN(chip->buf[5]) - 1;
+       dt->tm_wday     = BCD2BIN(chip->buf[6]);
+       dt->tm_year = BCD2BIN(chip->buf[7]);
+
+       century = BCD2BIN(tmp) * 100;
+
+       dt->tm_year += century;
+       dt->tm_year -= 1900;
+
+#ifdef MAX6902_DEBUG
+       printk("\n%s : Read RTC values\n",__FUNCTION__);
+       printk("tm_hour: %i\n",dt->tm_hour);
+       printk("tm_min : %i\n",dt->tm_min);
+       printk("tm_sec : %i\n",dt->tm_sec);
+       printk("tm_year: %i\n",dt->tm_year);
+       printk("tm_mon : %i\n",dt->tm_mon);
+       printk("tm_mday: %i\n",dt->tm_mday);
+       printk("tm_wday: %i\n",dt->tm_wday);
+#endif
+
+       return 0;
+}
+
+static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+       dt->tm_year = dt->tm_year+1900;
+
+#ifdef MAX6902_DEBUG
+       printk("\n%s : Setting RTC values\n",__FUNCTION__);
+       printk("tm_sec : %i\n",dt->tm_sec);
+       printk("tm_min : %i\n",dt->tm_min);
+       printk("tm_hour: %i\n",dt->tm_hour);
+       printk("tm_mday: %i\n",dt->tm_mday);
+       printk("tm_wday: %i\n",dt->tm_wday);
+       printk("tm_year: %i\n",dt->tm_year);
+#endif
+
+       /* Remove write protection */
+       max6902_set_reg(dev, 0xF, 0);
+
+       max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec));
+       max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min));
+       max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour));
+
+       max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday));
+       max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1));
+       max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday));
+       max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100));
+       max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100));
+
+       /* Compulab used a delay here. However, the datasheet
+        * does not mention a delay being required anywhere... */
+       /* delay(2000); */
+
+       /* Write protect */
+       max6902_set_reg(dev, 0xF, 0x80);
+
+       return 0;
+}
+
+static int max6902_read_time(struct device *dev, struct rtc_time *tm)
+{
+       return max6902_get_datetime(dev, tm);
+}
+
+static int max6902_set_time(struct device *dev, struct rtc_time *tm)
+{
+       return max6902_set_datetime(dev, tm);
+}
+
+static struct rtc_class_ops max6902_rtc_ops = {
+       .read_time      = max6902_read_time,
+       .set_time       = max6902_set_time,
+};
+
+static int __devinit max6902_probe(struct spi_device *spi)
+{
+       struct rtc_device *rtc;
+       unsigned char tmp;
+       struct max6902 *chip;
+       int res;
+
+       rtc = rtc_device_register("max6902",
+                               &spi->dev, &max6902_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 *chip, GFP_KERNEL);
+       if (!chip) {
+               rtc_device_unregister(rtc);
+               return -ENOMEM;
+       }
+       chip->rtc = rtc;
+       dev_set_drvdata(&spi->dev, chip);
+
+       res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp);
+       if (res) {
+               rtc_device_unregister(rtc);
+               return res;
+       }
+
+       return 0;
+}
+
+static int __devexit max6902_remove(struct spi_device *spi)
+{
+       struct max6902 *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 max6902_driver = {
+       .driver = {
+               .name   = "max6902",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = max6902_probe,
+       .remove = __devexit_p(max6902_remove),
+};
+
+static __init int max6902_init(void)
+{
+       printk("max6902 spi driver\n");
+       return spi_register_driver(&max6902_driver);
+}
+module_init(max6902_init);
+
+static __exit void max6902_exit(void)
+{
+       spi_unregister_driver(&max6902_driver);
+}
+module_exit(max6902_exit);
+
+MODULE_DESCRIPTION ("max6902 spi RTC driver");
+MODULE_AUTHOR ("Raphael Assenat");
+MODULE_LICENSE ("GPL");
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
new file mode 100644 (file)
index 0000000..b235a30
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ *  drivers/rtc/rtc-pcf8583.c
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Driver for PCF8583 RTC & RAM chip
+ *
+ *  Converted to the generic RTC susbsystem by G. Liakhovetski (2006)
+ */
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/bcd.h>
+
+struct rtc_mem {
+       unsigned int    loc;
+       unsigned int    nr;
+       unsigned char   *data;
+};
+
+struct pcf8583 {
+       struct i2c_client client;
+       struct rtc_device *rtc;
+       unsigned char ctrl;
+};
+
+#define CTRL_STOP      0x80
+#define CTRL_HOLD      0x40
+#define CTRL_32KHZ     0x00
+#define CTRL_MASK      0x08
+#define CTRL_ALARMEN   0x04
+#define CTRL_ALARM     0x02
+#define CTRL_TIMER     0x01
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Module parameters */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver pcf8583_driver;
+
+#define get_ctrl(x)    ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl
+#define set_ctrl(x, v) get_ctrl(x) = v
+
+#define CMOS_YEAR      (64 + 128)
+#define CMOS_CHECKSUM  (63)
+
+static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+       unsigned char buf[8], addr[1] = { 1 };
+       struct i2c_msg msgs[2] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = addr,
+               }, {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 6,
+                       .buf = buf,
+               }
+       };
+       int ret;
+
+       memset(buf, 0, sizeof(buf));
+
+       ret = i2c_transfer(client->adapter, msgs, 2);
+       if (ret == 2) {
+               dt->tm_year = buf[4] >> 6;
+               dt->tm_wday = buf[5] >> 5;
+
+               buf[4] &= 0x3f;
+               buf[5] &= 0x1f;
+
+               dt->tm_sec = BCD_TO_BIN(buf[1]);
+               dt->tm_min = BCD_TO_BIN(buf[2]);
+               dt->tm_hour = BCD_TO_BIN(buf[3]);
+               dt->tm_mday = BCD_TO_BIN(buf[4]);
+               dt->tm_mon = BCD_TO_BIN(buf[5]);
+       }
+
+       return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
+{
+       unsigned char buf[8];
+       int ret, len = 6;
+
+       buf[0] = 0;
+       buf[1] = get_ctrl(client) | 0x80;
+       buf[2] = 0;
+       buf[3] = BIN_TO_BCD(dt->tm_sec);
+       buf[4] = BIN_TO_BCD(dt->tm_min);
+       buf[5] = BIN_TO_BCD(dt->tm_hour);
+
+       if (datetoo) {
+               len = 8;
+               buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6);
+               buf[7] = BIN_TO_BCD(dt->tm_mon)  | (dt->tm_wday << 5);
+       }
+
+       ret = i2c_master_send(client, (char *)buf, len);
+       if (ret != len)
+               return -EIO;
+
+       buf[1] = get_ctrl(client);
+       ret = i2c_master_send(client, (char *)buf, 2);
+
+       return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+       *ctrl = get_ctrl(client);
+       return 0;
+}
+
+static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+       unsigned char buf[2];
+
+       buf[0] = 0;
+       buf[1] = *ctrl;
+       set_ctrl(client, *ctrl);
+
+       return i2c_master_send(client, (char *)buf, 2);
+}
+
+static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+       unsigned char addr[1];
+       struct i2c_msg msgs[2] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = addr,
+               }, {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = mem->nr,
+                       .buf = mem->data,
+               }
+       };
+
+       if (mem->loc < 8)
+               return -EINVAL;
+
+       addr[0] = mem->loc;
+
+       return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+       unsigned char addr[1];
+       struct i2c_msg msgs[2] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = addr,
+               }, {
+                       .addr = client->addr,
+                       .flags = I2C_M_NOSTART,
+                       .len = mem->nr,
+                       .buf = mem->data,
+               }
+       };
+
+       if (mem->loc < 8)
+               return -EINVAL;
+
+       addr[0] = mem->loc;
+
+       return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char ctrl, year[2];
+       struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
+       int real_year, year_offset, err;
+
+       /*
+        * Ensure that the RTC is running.
+        */
+       pcf8583_get_ctrl(client, &ctrl);
+       if (ctrl & (CTRL_STOP | CTRL_HOLD)) {
+               unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD);
+
+               printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
+                      ctrl, new_ctrl);
+
+               if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0)
+                       return err;
+       }
+
+       if (pcf8583_get_datetime(client, tm) ||
+           pcf8583_read_mem(client, &mem))
+               return -EIO;
+
+       real_year = year[0];
+
+       /*
+        * The RTC year holds the LSB two bits of the current
+        * year, which should reflect the LSB two bits of the
+        * CMOS copy of the year.  Any difference indicates
+        * that we have to correct the CMOS version.
+        */
+       year_offset = tm->tm_year - (real_year & 3);
+       if (year_offset < 0)
+               /*
+                * RTC year wrapped.  Adjust it appropriately.
+                */
+               year_offset += 4;
+
+       tm->tm_year = real_year + year_offset + year[1] * 100;
+
+       return 0;
+}
+
+static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char year[2], chk;
+       struct rtc_mem cmos_year  = { CMOS_YEAR, sizeof(year), year };
+       struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+       int ret;
+
+       /*
+        * The RTC's own 2-bit year must reflect the least
+        * significant two bits of the CMOS year.
+        */
+
+       ret = pcf8583_set_datetime(client, tm, 1);
+       if (ret)
+               return ret;
+
+       ret = pcf8583_read_mem(client, &cmos_check);
+       if (ret)
+               return ret;
+
+       ret = pcf8583_read_mem(client, &cmos_year);
+       if (ret)
+               return ret;
+
+       chk -= year[1] + year[0];
+
+       year[1] = tm->tm_year / 100;
+       year[0] = tm->tm_year % 100;
+
+       chk += year[1] + year[0];
+
+       ret = pcf8583_write_mem(client, &cmos_year);
+
+       if (ret)
+               return ret;
+
+       ret = pcf8583_write_mem(client, &cmos_check);
+
+       return ret;
+}
+
+static struct rtc_class_ops pcf8583_rtc_ops = {
+       .read_time      = pcf8583_rtc_read_time,
+       .set_time       = pcf8583_rtc_set_time,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
+
+static int pcf8583_attach(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, pcf8583_probe);
+}
+
+static int pcf8583_detach(struct i2c_client *client)
+{
+       int err;
+       struct pcf8583 *pcf = i2c_get_clientdata(client);
+       struct rtc_device *rtc = pcf->rtc;
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+
+       if ((err = i2c_detach_client(client)))
+               return err;
+
+       kfree(pcf);
+       return 0;
+}
+
+static struct i2c_driver pcf8583_driver = {
+       .driver = {
+               .name   = "pcf8583",
+       },
+       .id             = I2C_DRIVERID_PCF8583,
+       .attach_adapter = pcf8583_attach,
+       .detach_client  = pcf8583_detach,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct pcf8583 *pcf;
+       struct i2c_client *client;
+       struct rtc_device *rtc;
+       unsigned char buf[1], ad[1] = { 0 };
+       int err;
+       struct i2c_msg msgs[2] = {
+               {
+                       .addr = addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = ad,
+               }, {
+                       .addr = addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = buf,
+               }
+       };
+
+       pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
+       if (!pcf)
+               return -ENOMEM;
+
+       client = &pcf->client;
+
+       client->addr            = addr;
+       client->adapter = adap;
+       client->driver  = &pcf8583_driver;
+
+       strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
+
+       if (i2c_transfer(client->adapter, msgs, 2) != 2) {
+               err = -EIO;
+               goto exit_kfree;
+       }
+
+       err = i2c_attach_client(client);
+
+       if (err)
+               goto exit_kfree;
+
+       rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
+                                 &pcf8583_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc)) {
+               err = PTR_ERR(rtc);
+               goto exit_detach;
+       }
+
+       pcf->rtc = rtc;
+       i2c_set_clientdata(client, pcf);
+       set_ctrl(client, buf[0]);
+
+       return 0;
+
+exit_detach:
+       i2c_detach_client(client);
+
+exit_kfree:
+       kfree(pcf);
+
+       return err;
+}
+
+static __init int pcf8583_init(void)
+{
+       return i2c_add_driver(&pcf8583_driver);
+}
+
+static __exit void pcf8583_exit(void)
+{
+       i2c_del_driver(&pcf8583_driver);
+}
+
+module_init(pcf8583_init);
+module_exit(pcf8583_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
new file mode 100644 (file)
index 0000000..d6d1c57
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * drivers/rtc/rtc-pl031.c
+ *
+ * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2006 (c) MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+
+#include <linux/amba/bus.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+/*
+ * Register definitions
+ */
+#define        RTC_DR          0x00    /* Data read register */
+#define        RTC_MR          0x04    /* Match register */
+#define        RTC_LR          0x08    /* Data load register */
+#define        RTC_CR          0x0c    /* Control register */
+#define        RTC_IMSC        0x10    /* Interrupt mask and set register */
+#define        RTC_RIS         0x14    /* Raw interrupt status register */
+#define        RTC_MIS         0x18    /* Masked interrupt status register */
+#define        RTC_ICR         0x1c    /* Interrupt clear register */
+
+struct pl031_local {
+       struct rtc_device *rtc;
+       void __iomem *base;
+};
+
+static irqreturn_t pl031_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct rtc_device *rtc = dev_id;
+
+       rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+
+       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);
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+               __raw_writel(1, ldata->base + RTC_MIS);
+               return 0;
+       case RTC_AIE_ON:
+               __raw_writel(0, ldata->base + RTC_MIS);
+               return 0;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static int pl031_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct pl031_local *ldata = dev_get_drvdata(dev);
+
+       rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm);
+
+       return 0;
+}
+
+static int pl031_set_time(struct device *dev, struct rtc_time *tm)
+{
+       unsigned long time;
+       struct pl031_local *ldata = dev_get_drvdata(dev);
+
+       rtc_tm_to_time(tm, &time);
+       __raw_writel(time, ldata->base + RTC_LR);
+
+       return 0;
+}
+
+static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       struct pl031_local *ldata = dev_get_drvdata(dev);
+
+       rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time);
+       alarm->pending = __raw_readl(ldata->base + RTC_RIS);
+       alarm->enabled = __raw_readl(ldata->base + RTC_IMSC);
+
+       return 0;
+}
+
+static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+       struct pl031_local *ldata = dev_get_drvdata(dev);
+       unsigned long time;
+
+       rtc_tm_to_time(&alarm->time, &time);
+
+       __raw_writel(time, ldata->base + RTC_MR);
+       __raw_writel(!alarm->enabled, ldata->base + RTC_MIS);
+
+       return 0;
+}
+
+static 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,
+       .read_alarm = pl031_read_alarm,
+       .set_alarm = pl031_set_alarm,
+};
+
+static int pl031_remove(struct amba_device *adev)
+{
+       struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
+
+       if (ldata) {
+               dev_set_drvdata(&adev->dev, NULL);
+               free_irq(adev->irq[0], ldata->rtc);
+               rtc_device_unregister(ldata->rtc);
+               iounmap(ldata->base);
+               kfree(ldata);
+       }
+
+       return 0;
+}
+
+static int pl031_probe(struct amba_device *adev, void *id)
+{
+       int ret;
+       struct pl031_local *ldata;
+
+
+       ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL);
+       if (!ldata) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       dev_set_drvdata(&adev->dev, ldata);
+
+       ldata->base = ioremap(adev->res.start,
+                             adev->res.end - adev->res.start + 1);
+       if (!ldata->base) {
+               ret = -ENOMEM;
+               goto out_no_remap;
+       }
+
+       if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED,
+                       "rtc-pl031", ldata->rtc)) {
+               ret = -EIO;
+               goto out_no_irq;
+       }
+
+       ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops,
+                                        THIS_MODULE);
+       if (IS_ERR(ldata->rtc)) {
+               ret = PTR_ERR(ldata->rtc);
+               goto out_no_rtc;
+       }
+
+       return 0;
+
+out_no_rtc:
+       free_irq(adev->irq[0], ldata->rtc);
+out_no_irq:
+       iounmap(ldata->base);
+out_no_remap:
+       dev_set_drvdata(&adev->dev, NULL);
+       kfree(ldata);
+out:
+       return ret;
+}
+
+static struct amba_id pl031_ids[] __initdata = {
+       {
+                .id = 0x00041031,
+               .mask = 0x000fffff, },
+       {0, 0},
+};
+
+static struct amba_driver pl031_driver = {
+       .drv = {
+               .name = "rtc-pl031",
+       },
+       .id_table = pl031_ids,
+       .probe = pl031_probe,
+       .remove = pl031_remove,
+};
+
+static int __init pl031_init(void)
+{
+       return amba_driver_register(&pl031_driver);
+}
+
+static void __exit pl031_exit(void)
+{
+       amba_driver_unregister(&pl031_driver);
+}
+
+module_init(pl031_init);
+module_exit(pl031_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net");
+MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
new file mode 100644 (file)
index 0000000..0964d1d
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * A SPI driver for the Ricoh RS5C348 RTC
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * This program is free software; you can 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 board specific init code should provide characteristics of this
+ * device:
+ *     Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS
+ */
+
+#include <linux/bcd.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+
+#define DRV_VERSION "0.1"
+
+#define RS5C348_REG_SECS       0
+#define RS5C348_REG_MINS       1
+#define RS5C348_REG_HOURS      2
+#define RS5C348_REG_WDAY       3
+#define RS5C348_REG_DAY        4
+#define RS5C348_REG_MONTH      5
+#define RS5C348_REG_YEAR       6
+#define RS5C348_REG_CTL1       14
+#define RS5C348_REG_CTL2       15
+
+#define RS5C348_SECS_MASK      0x7f
+#define RS5C348_MINS_MASK      0x7f
+#define RS5C348_HOURS_MASK     0x3f
+#define RS5C348_WDAY_MASK      0x03
+#define RS5C348_DAY_MASK       0x3f
+#define RS5C348_MONTH_MASK     0x1f
+
+#define RS5C348_BIT_PM 0x20    /* REG_HOURS */
+#define RS5C348_BIT_Y2K        0x80    /* REG_MONTH */
+#define RS5C348_BIT_24H        0x20    /* REG_CTL1 */
+#define RS5C348_BIT_XSTP       0x10    /* REG_CTL2 */
+#define RS5C348_BIT_VDET       0x40    /* REG_CTL2 */
+
+#define RS5C348_CMD_W(addr)    (((addr) << 4) | 0x08)  /* single write */
+#define RS5C348_CMD_R(addr)    (((addr) << 4) | 0x0c)  /* single read */
+#define RS5C348_CMD_MW(addr)   (((addr) << 4) | 0x00)  /* burst write */
+#define RS5C348_CMD_MR(addr)   (((addr) << 4) | 0x04)  /* burst read */
+
+struct rs5c348_plat_data {
+       struct rtc_device *rtc;
+       int rtc_24h;
+};
+
+static int
+rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+       u8 txbuf[5+7], *txp;
+       int ret;
+
+       /* Transfer 5 bytes before writing SEC.  This gives 31us for carry. */
+       txp = txbuf;
+       txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+       txbuf[1] = 0;   /* dummy */
+       txbuf[2] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+       txbuf[3] = 0;   /* dummy */
+       txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */
+       txp = &txbuf[5];
+       txp[RS5C348_REG_SECS] = BIN2BCD(tm->tm_sec);
+       txp[RS5C348_REG_MINS] = BIN2BCD(tm->tm_min);
+       if (pdata->rtc_24h) {
+               txp[RS5C348_REG_HOURS] = BIN2BCD(tm->tm_hour);
+       } else {
+               /* hour 0 is AM12, noon is PM12 */
+               txp[RS5C348_REG_HOURS] = BIN2BCD((tm->tm_hour + 11) % 12 + 1) |
+                       (tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0);
+       }
+       txp[RS5C348_REG_WDAY] = BIN2BCD(tm->tm_wday);
+       txp[RS5C348_REG_DAY] = BIN2BCD(tm->tm_mday);
+       txp[RS5C348_REG_MONTH] = BIN2BCD(tm->tm_mon + 1) |
+               (tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0);
+       txp[RS5C348_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+       /* write in one transfer to avoid data inconsistency */
+       ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0);
+       udelay(62);     /* Tcsr 62us */
+       return ret;
+}
+
+static int
+rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+       u8 txbuf[5], rxbuf[7];
+       int ret;
+
+       /* Transfer 5 byte befores reading SEC.  This gives 31us for carry. */
+       txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+       txbuf[1] = 0;   /* dummy */
+       txbuf[2] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+       txbuf[3] = 0;   /* dummy */
+       txbuf[4] = RS5C348_CMD_MR(RS5C348_REG_SECS); /* cmd, sec, ... */
+
+       /* read in one transfer to avoid data inconsistency */
+       ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
+                                 rxbuf, sizeof(rxbuf));
+       udelay(62);     /* Tcsr 62us */
+       if (ret < 0)
+               return ret;
+
+       tm->tm_sec = BCD2BIN(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK);
+       tm->tm_min = BCD2BIN(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
+       tm->tm_hour = BCD2BIN(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
+       if (!pdata->rtc_24h) {
+               tm->tm_hour %= 12;
+               if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM)
+                       tm->tm_hour += 12;
+       }
+       tm->tm_wday = BCD2BIN(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
+       tm->tm_mday = BCD2BIN(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
+       tm->tm_mon =
+               BCD2BIN(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1;
+       /* year is 1900 + tm->tm_year */
+       tm->tm_year = BCD2BIN(rxbuf[RS5C348_REG_YEAR]) +
+               ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0);
+
+       if (rtc_valid_tm(tm) < 0) {
+               dev_err(&spi->dev, "retrieved date/time is not valid.\n");
+               rtc_time_to_tm(0, tm);
+       }
+
+       return 0;
+}
+
+static struct rtc_class_ops rs5c348_rtc_ops = {
+       .read_time      = rs5c348_rtc_read_time,
+       .set_time       = rs5c348_rtc_set_time,
+};
+
+static struct spi_driver rs5c348_driver;
+
+static int __devinit rs5c348_probe(struct spi_device *spi)
+{
+       int ret;
+       struct rtc_device *rtc;
+       struct rs5c348_plat_data *pdata;
+
+       pdata = kzalloc(sizeof(struct rs5c348_plat_data), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+       spi->dev.platform_data = pdata;
+
+       /* Check D7 of SECOND register */
+       ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_SECS));
+       if (ret < 0 || (ret & 0x80)) {
+               dev_err(&spi->dev, "not found.\n");
+               goto kfree_exit;
+       }
+
+       dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
+       dev_info(&spi->dev, "spiclk %u KHz.\n",
+                (spi->max_speed_hz + 500) / 1000);
+
+       /* turn RTC on if it was not on */
+       ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2));
+       if (ret < 0)
+               goto kfree_exit;
+       if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) {
+               u8 buf[2];
+               if (ret & RS5C348_BIT_VDET)
+                       dev_warn(&spi->dev, "voltage-low detected.\n");
+               buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2);
+               buf[1] = 0;
+               ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
+               if (ret < 0)
+                       goto kfree_exit;
+       }
+
+       ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1));
+       if (ret < 0)
+               goto kfree_exit;
+       if (ret & RS5C348_BIT_24H)
+               pdata->rtc_24h = 1;
+
+       rtc = rtc_device_register(rs5c348_driver.driver.name, &spi->dev,
+                                 &rs5c348_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               goto kfree_exit;
+       }
+
+       pdata->rtc = rtc;
+
+       return 0;
+ kfree_exit:
+       kfree(pdata);
+       return ret;
+}
+
+static int __devexit rs5c348_remove(struct spi_device *spi)
+{
+       struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+       struct rtc_device *rtc = pdata->rtc;
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+       kfree(pdata);
+       return 0;
+}
+
+static struct spi_driver rs5c348_driver = {
+       .driver = {
+               .name   = "rs5c348",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe  = rs5c348_probe,
+       .remove = __devexit_p(rs5c348_remove),
+};
+
+static __init int rs5c348_init(void)
+{
+       return spi_register_driver(&rs5c348_driver);
+}
+
+static __exit void rs5c348_exit(void)
+{
+       spi_unregister_driver(&rs5c348_driver);
+}
+
+module_init(rs5c348_init);
+module_exit(rs5c348_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
new file mode 100644 (file)
index 0000000..2c7de79
--- /dev/null
@@ -0,0 +1,621 @@
+/* drivers/rtc/rtc-s3c.c
+ *
+ * Copyright (c) 2004,2006 Simtec Electronics
+ *     Ben Dooks, <ben@simtec.co.uk>
+ *     http://armlinux.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/S3C2440/S3C24XX Internal RTC Driver
+*/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+#include <asm/mach/time.h>
+
+#include <asm/arch/regs-rtc.h>
+
+/* I have yet to find an S3C implementation with more than one
+ * of these rtc blocks in */
+
+static struct resource *s3c_rtc_mem;
+
+static void __iomem *s3c_rtc_base;
+static int s3c_rtc_alarmno = NO_IRQ;
+static int s3c_rtc_tickno  = NO_IRQ;
+static int s3c_rtc_freq    = 1;
+
+static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
+static unsigned int tick_count;
+
+/* IRQ Handlers */
+
+static irqreturn_t s3c_rtc_alarmirq(int irq, void *id, struct pt_regs *r)
+{
+       struct rtc_device *rdev = id;
+
+       rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t s3c_rtc_tickirq(int irq, void *id, struct pt_regs *r)
+{
+       struct rtc_device *rdev = id;
+
+       rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF);
+       return IRQ_HANDLED;
+}
+
+/* Update control registers */
+static void s3c_rtc_setaie(int to)
+{
+       unsigned int tmp;
+
+       pr_debug("%s: aie=%d\n", __FUNCTION__, to);
+
+       tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
+
+       if (to)
+               tmp |= S3C2410_RTCALM_ALMEN;
+
+       writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
+}
+
+static void s3c_rtc_setpie(int to)
+{
+       unsigned int tmp;
+
+       pr_debug("%s: pie=%d\n", __FUNCTION__, to);
+
+       spin_lock_irq(&s3c_rtc_pie_lock);
+       tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
+
+       if (to)
+               tmp |= S3C2410_TICNT_ENABLE;
+
+       writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
+       spin_unlock_irq(&s3c_rtc_pie_lock);
+}
+
+static void s3c_rtc_setfreq(int freq)
+{
+       unsigned int tmp;
+
+       spin_lock_irq(&s3c_rtc_pie_lock);
+       tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
+
+       s3c_rtc_freq = freq;
+
+       tmp |= (128 / freq)-1;
+
+       writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
+       spin_unlock_irq(&s3c_rtc_pie_lock);
+}
+
+/* Time read/write */
+
+static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+{
+       unsigned int have_retried = 0;
+       void __iomem *base = s3c_rtc_base;
+
+ retry_get_time:
+       rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);
+       rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
+       rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);
+       rtc_tm->tm_mon  = readb(base + S3C2410_RTCMON);
+       rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
+       rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);
+
+       /* the only way to work out wether the system was mid-update
+        * when we read it is to check the second counter, and if it
+        * is zero, then we re-try the entire read
+        */
+
+       if (rtc_tm->tm_sec == 0 && !have_retried) {
+               have_retried = 1;
+               goto retry_get_time;
+       }
+
+       pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
+                rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+                rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
+       BCD_TO_BIN(rtc_tm->tm_sec);
+       BCD_TO_BIN(rtc_tm->tm_min);
+       BCD_TO_BIN(rtc_tm->tm_hour);
+       BCD_TO_BIN(rtc_tm->tm_mday);
+       BCD_TO_BIN(rtc_tm->tm_mon);
+       BCD_TO_BIN(rtc_tm->tm_year);
+
+       rtc_tm->tm_year += 100;
+       rtc_tm->tm_mon -= 1;
+
+       return 0;
+}
+
+static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+       void __iomem *base = s3c_rtc_base;
+       int year = tm->tm_year - 100;
+
+       pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+                tm->tm_year, tm->tm_mon, tm->tm_mday,
+                tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       /* we get around y2k by simply not supporting it */
+
+       if (year < 0 || year >= 100) {
+               dev_err(dev, "rtc only supports 100 years\n");
+               return -EINVAL;
+       }
+
+       writeb(BIN2BCD(tm->tm_sec),  base + S3C2410_RTCSEC);
+       writeb(BIN2BCD(tm->tm_min),  base + S3C2410_RTCMIN);
+       writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR);
+       writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE);
+       writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON);
+       writeb(BIN2BCD(year), base + S3C2410_RTCYEAR);
+
+       return 0;
+}
+
+static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rtc_time *alm_tm = &alrm->time;
+       void __iomem *base = s3c_rtc_base;
+       unsigned int alm_en;
+
+       alm_tm->tm_sec  = readb(base + S3C2410_ALMSEC);
+       alm_tm->tm_min  = readb(base + S3C2410_ALMMIN);
+       alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
+       alm_tm->tm_mon  = readb(base + S3C2410_ALMMON);
+       alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);
+       alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);
+
+       alm_en = readb(base + S3C2410_RTCALM);
+
+       pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
+                alm_en,
+                alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
+                alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
+
+
+       /* decode the alarm enable field */
+
+       if (alm_en & S3C2410_RTCALM_SECEN)
+               BCD_TO_BIN(alm_tm->tm_sec);
+       else
+               alm_tm->tm_sec = 0xff;
+
+       if (alm_en & S3C2410_RTCALM_MINEN)
+               BCD_TO_BIN(alm_tm->tm_min);
+       else
+               alm_tm->tm_min = 0xff;
+
+       if (alm_en & S3C2410_RTCALM_HOUREN)
+               BCD_TO_BIN(alm_tm->tm_hour);
+       else
+               alm_tm->tm_hour = 0xff;
+
+       if (alm_en & S3C2410_RTCALM_DAYEN)
+               BCD_TO_BIN(alm_tm->tm_mday);
+       else
+               alm_tm->tm_mday = 0xff;
+
+       if (alm_en & S3C2410_RTCALM_MONEN) {
+               BCD_TO_BIN(alm_tm->tm_mon);
+               alm_tm->tm_mon -= 1;
+       } else {
+               alm_tm->tm_mon = 0xff;
+       }
+
+       if (alm_en & S3C2410_RTCALM_YEAREN)
+               BCD_TO_BIN(alm_tm->tm_year);
+       else
+               alm_tm->tm_year = 0xffff;
+
+       return 0;
+}
+
+static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct rtc_time *tm = &alrm->time;
+       void __iomem *base = s3c_rtc_base;
+       unsigned int alrm_en;
+
+       pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
+                alrm->enabled,
+                tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
+                tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
+
+
+       alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
+       writeb(0x00, base + S3C2410_RTCALM);
+
+       if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
+               alrm_en |= S3C2410_RTCALM_SECEN;
+               writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC);
+       }
+
+       if (tm->tm_min < 60 && tm->tm_min >= 0) {
+               alrm_en |= S3C2410_RTCALM_MINEN;
+               writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN);
+       }
+
+       if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
+               alrm_en |= S3C2410_RTCALM_HOUREN;
+               writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR);
+       }
+
+       pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
+
+       writeb(alrm_en, base + S3C2410_RTCALM);
+
+       if (0) {
+               alrm_en = readb(base + S3C2410_RTCALM);
+               alrm_en &= ~S3C2410_RTCALM_ALMEN;
+               writeb(alrm_en, base + S3C2410_RTCALM);
+               disable_irq_wake(s3c_rtc_alarmno);
+       }
+
+       if (alrm->enabled)
+               enable_irq_wake(s3c_rtc_alarmno);
+       else
+               disable_irq_wake(s3c_rtc_alarmno);
+
+       return 0;
+}
+
+static int s3c_rtc_ioctl(struct device *dev,
+                        unsigned int cmd, unsigned long arg)
+{
+       unsigned int ret = -ENOIOCTLCMD;
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+       case RTC_AIE_ON:
+               s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
+               ret = 0;
+               break;
+
+       case RTC_PIE_OFF:
+       case RTC_PIE_ON:
+               tick_count = 0;
+               s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
+               ret = 0;
+               break;
+
+       case RTC_IRQP_READ:
+               ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg);
+               break;
+
+       case RTC_IRQP_SET:
+               /* check for power of 2 */
+
+               if ((arg & (arg-1)) != 0 || arg < 1) {
+                       ret = -EINVAL;
+                       goto exit;
+               }
+
+               pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
+
+               s3c_rtc_setfreq(arg);
+               ret = 0;
+               break;
+
+       case RTC_UIE_ON:
+       case RTC_UIE_OFF:
+               ret = -EINVAL;
+       }
+
+ exit:
+       return ret;
+}
+
+static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM);
+       unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
+
+       seq_printf(seq, "alarm_IRQ\t: %s\n",
+                  (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
+
+       seq_printf(seq, "periodic_IRQ\t: %s\n",
+                    (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
+
+       seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq);
+
+       return 0;
+}
+
+static int s3c_rtc_open(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq,
+                         SA_INTERRUPT,  "s3c2410-rtc alarm", rtc_dev);
+
+       if (ret) {
+               dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret);
+               return ret;
+       }
+
+       ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
+                         SA_INTERRUPT,  "s3c2410-rtc tick", rtc_dev);
+
+       if (ret) {
+               dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
+               goto tick_err;
+       }
+
+       return ret;
+
+ tick_err:
+       free_irq(s3c_rtc_alarmno, rtc_dev);
+       return ret;
+}
+
+static void s3c_rtc_release(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+
+       /* do not clear AIE here, it may be needed for wake */
+
+       s3c_rtc_setpie(0);
+       free_irq(s3c_rtc_alarmno, rtc_dev);
+       free_irq(s3c_rtc_tickno, rtc_dev);
+}
+
+static struct rtc_class_ops s3c_rtcops = {
+       .open           = s3c_rtc_open,
+       .release        = s3c_rtc_release,
+       .ioctl          = s3c_rtc_ioctl,
+       .read_time      = s3c_rtc_gettime,
+       .set_time       = s3c_rtc_settime,
+       .read_alarm     = s3c_rtc_getalarm,
+       .set_alarm      = s3c_rtc_setalarm,
+       .proc           = s3c_rtc_proc,
+};
+
+static void s3c_rtc_enable(struct platform_device *pdev, int en)
+{
+       void __iomem *base = s3c_rtc_base;
+       unsigned int tmp;
+
+       if (s3c_rtc_base == NULL)
+               return;
+
+       if (!en) {
+               tmp = readb(base + S3C2410_RTCCON);
+               writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON);
+
+               tmp = readb(base + S3C2410_TICNT);
+               writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT);
+       } else {
+               /* re-enable the device, and check it is ok */
+
+               if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
+                       dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+
+                       tmp = readb(base + S3C2410_RTCCON);
+                       writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON);
+               }
+
+               if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
+                       dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
+
+                       tmp = readb(base + S3C2410_RTCCON);
+                       writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON);
+               }
+
+               if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
+                       dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
+
+                       tmp = readb(base + S3C2410_RTCCON);
+                       writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON);
+               }
+       }
+}
+
+static int s3c_rtc_remove(struct platform_device *dev)
+{
+       struct rtc_device *rtc = platform_get_drvdata(dev);
+
+       platform_set_drvdata(dev, NULL);
+       rtc_device_unregister(rtc);
+
+       s3c_rtc_setpie(0);
+       s3c_rtc_setaie(0);
+
+       iounmap(s3c_rtc_base);
+       release_resource(s3c_rtc_mem);
+       kfree(s3c_rtc_mem);
+
+       return 0;
+}
+
+static int s3c_rtc_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       struct resource *res;
+       int ret;
+
+       pr_debug("%s: probe=%p\n", __FUNCTION__, pdev);
+
+       /* find the IRQs */
+
+       s3c_rtc_tickno = platform_get_irq(pdev, 1);
+       if (s3c_rtc_tickno < 0) {
+               dev_err(&pdev->dev, "no irq for rtc tick\n");
+               return -ENOENT;
+       }
+
+       s3c_rtc_alarmno = platform_get_irq(pdev, 0);
+       if (s3c_rtc_alarmno < 0) {
+               dev_err(&pdev->dev, "no irq for alarm\n");
+               return -ENOENT;
+       }
+
+       pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
+                s3c_rtc_tickno, s3c_rtc_alarmno);
+
+       /* get the memory region */
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region resource\n");
+               return -ENOENT;
+       }
+
+       s3c_rtc_mem = request_mem_region(res->start,
+                                        res->end-res->start+1,
+                                        pdev->name);
+
+       if (s3c_rtc_mem == NULL) {
+               dev_err(&pdev->dev, "failed to reserve memory region\n");
+               ret = -ENOENT;
+               goto err_nores;
+       }
+
+       s3c_rtc_base = ioremap(res->start, res->end - res->start + 1);
+       if (s3c_rtc_base == NULL) {
+               dev_err(&pdev->dev, "failed ioremap()\n");
+               ret = -EINVAL;
+               goto err_nomap;
+       }
+
+       /* check to see if everything is setup correctly */
+
+       s3c_rtc_enable(pdev, 1);
+
+       pr_debug("s3c2410_rtc: RTCCON=%02x\n",
+                readb(s3c_rtc_base + S3C2410_RTCCON));
+
+       s3c_rtc_setfreq(s3c_rtc_freq);
+
+       /* register RTC and exit */
+
+       rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
+                                 THIS_MODULE);
+
+       if (IS_ERR(rtc)) {
+               dev_err(&pdev->dev, "cannot attach rtc\n");
+               ret = PTR_ERR(rtc);
+               goto err_nortc;
+       }
+
+       rtc->max_user_freq = 128;
+
+       platform_set_drvdata(pdev, rtc);
+       return 0;
+
+ err_nortc:
+       s3c_rtc_enable(pdev, 0);
+       iounmap(s3c_rtc_base);
+
+ err_nomap:
+       release_resource(s3c_rtc_mem);
+
+ err_nores:
+       return ret;
+}
+
+#ifdef CONFIG_PM
+
+/* RTC Power management control */
+
+static struct timespec s3c_rtc_delta;
+
+static int ticnt_save;
+
+static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rtc_time tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+
+       /* save TICNT for anyone using periodic interrupts */
+
+       ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
+
+       /* calculate time delta for suspend */
+
+       s3c_rtc_gettime(&pdev->dev, &tm);
+       rtc_tm_to_time(&tm, &time.tv_sec);
+       save_time_delta(&s3c_rtc_delta, &time);
+       s3c_rtc_enable(pdev, 0);
+
+       return 0;
+}
+
+static int s3c_rtc_resume(struct platform_device *pdev)
+{
+       struct rtc_time tm;
+       struct timespec time;
+
+       time.tv_nsec = 0;
+
+       s3c_rtc_enable(pdev, 1);
+       s3c_rtc_gettime(&pdev->dev, &tm);
+       rtc_tm_to_time(&tm, &time.tv_sec);
+       restore_time_delta(&s3c_rtc_delta, &time);
+
+       writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
+       return 0;
+}
+#else
+#define s3c_rtc_suspend NULL
+#define s3c_rtc_resume  NULL
+#endif
+
+static struct platform_driver s3c2410_rtcdrv = {
+       .probe          = s3c_rtc_probe,
+       .remove         = s3c_rtc_remove,
+       .suspend        = s3c_rtc_suspend,
+       .resume         = s3c_rtc_resume,
+       .driver         = {
+               .name   = "s3c2410-rtc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";
+
+static int __init s3c_rtc_init(void)
+{
+       printk(banner);
+       return platform_driver_register(&s3c2410_rtcdrv);
+}
+
+static void __exit s3c_rtc_exit(void)
+{
+       platform_driver_unregister(&s3c2410_rtcdrv);
+}
+
+module_init(s3c_rtc_init);
+module_exit(s3c_rtc_exit);
+
+MODULE_DESCRIPTION("Samsung S3C RTC Driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
new file mode 100644 (file)
index 0000000..a40f400
--- /dev/null
@@ -0,0 +1,264 @@
+/* drivers/rtc/rtc-v3020.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 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.
+ *
+ * Driver for the V3020 RTC
+ *
+ * Changelog:
+ *
+ *  10-May-2006: Raphael Assenat <raph@8d.com>
+ *                             - Converted to platform driver
+ *                             - Use the generic rtc class
+ *
+ *  ??-???-2004: Someone at Compulab
+ *                     - Initial driver creation.
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+#include <linux/bcd.h>
+#include <linux/rtc-v3020.h>
+
+#include <asm/io.h>
+
+#undef DEBUG
+
+struct v3020 {
+       void __iomem *ioaddress;
+       int leftshift;
+       struct rtc_device *rtc;
+};
+
+static void v3020_set_reg(struct v3020 *chip, unsigned char address,
+                       unsigned char data)
+{
+       int i;
+       unsigned char tmp;
+
+       tmp = address;
+       for (i = 0; i < 4; i++) {
+               writel((tmp & 1) << chip->leftshift, chip->ioaddress);
+               tmp >>= 1;
+       }
+
+       /* Commands dont have data */
+       if (!V3020_IS_COMMAND(address)) {
+               for (i = 0; i < 8; i++) {
+                       writel((data & 1) << chip->leftshift, chip->ioaddress);
+                       data >>= 1;
+               }
+       }
+}
+
+static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address)
+{
+       unsigned int data=0;
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               writel((address & 1) << chip->leftshift, chip->ioaddress);
+               address >>= 1;
+       }
+
+       for (i = 0; i < 8; i++) {
+               data >>= 1;
+               if (readl(chip->ioaddress) & (1 << chip->leftshift))
+                       data |= 0x80;
+       }
+
+       return data;
+}
+
+static int v3020_read_time(struct device *dev, struct rtc_time *dt)
+{
+       struct v3020 *chip = dev_get_drvdata(dev);
+       int tmp;
+
+       /* Copy the current time to ram... */
+       v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0);
+
+       /* ...and then read constant values. */
+       tmp = v3020_get_reg(chip, V3020_SECONDS);
+       dt->tm_sec      = BCD2BIN(tmp);
+       tmp = v3020_get_reg(chip, V3020_MINUTES);
+       dt->tm_min      = BCD2BIN(tmp);
+       tmp = v3020_get_reg(chip, V3020_HOURS);
+       dt->tm_hour     = BCD2BIN(tmp);
+       tmp = v3020_get_reg(chip, V3020_MONTH_DAY);
+       dt->tm_mday     = BCD2BIN(tmp);
+       tmp = v3020_get_reg(chip, V3020_MONTH);
+       dt->tm_mon      = BCD2BIN(tmp);
+       tmp = v3020_get_reg(chip, V3020_WEEK_DAY);
+       dt->tm_wday     = BCD2BIN(tmp);
+       tmp = v3020_get_reg(chip, V3020_YEAR);
+       dt->tm_year = BCD2BIN(tmp)+100;
+
+#ifdef DEBUG
+       printk("\n%s : Read RTC values\n",__FUNCTION__);
+       printk("tm_hour: %i\n",dt->tm_hour);
+       printk("tm_min : %i\n",dt->tm_min);
+       printk("tm_sec : %i\n",dt->tm_sec);
+       printk("tm_year: %i\n",dt->tm_year);
+       printk("tm_mon : %i\n",dt->tm_mon);
+       printk("tm_mday: %i\n",dt->tm_mday);
+       printk("tm_wday: %i\n",dt->tm_wday);
+#endif
+
+       return 0;
+}
+
+
+static int v3020_set_time(struct device *dev, struct rtc_time *dt)
+{
+       struct v3020 *chip = dev_get_drvdata(dev);
+
+#ifdef DEBUG
+       printk("\n%s : Setting RTC values\n",__FUNCTION__);
+       printk("tm_sec : %i\n",dt->tm_sec);
+       printk("tm_min : %i\n",dt->tm_min);
+       printk("tm_hour: %i\n",dt->tm_hour);
+       printk("tm_mday: %i\n",dt->tm_mday);
+       printk("tm_wday: %i\n",dt->tm_wday);
+       printk("tm_year: %i\n",dt->tm_year);
+#endif
+
+       /* Write all the values to ram... */
+       v3020_set_reg(chip, V3020_SECONDS,      BIN2BCD(dt->tm_sec));
+       v3020_set_reg(chip, V3020_MINUTES,      BIN2BCD(dt->tm_min));
+       v3020_set_reg(chip, V3020_HOURS,        BIN2BCD(dt->tm_hour));
+       v3020_set_reg(chip, V3020_MONTH_DAY,    BIN2BCD(dt->tm_mday));
+       v3020_set_reg(chip, V3020_MONTH,        BIN2BCD(dt->tm_mon));
+       v3020_set_reg(chip, V3020_WEEK_DAY,     BIN2BCD(dt->tm_wday));
+       v3020_set_reg(chip, V3020_YEAR,         BIN2BCD(dt->tm_year % 100));
+
+       /* ...and set the clock. */
+       v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0);
+
+       /* Compulab used this delay here. I dont know why,
+        * the datasheet does not specify a delay. */
+       /*mdelay(5);*/
+
+       return 0;
+}
+
+static struct rtc_class_ops v3020_rtc_ops = {
+       .read_time      = v3020_read_time,
+       .set_time       = v3020_set_time,
+};
+
+static int rtc_probe(struct platform_device *pdev)
+{
+       struct v3020_platform_data *pdata = pdev->dev.platform_data;
+       struct v3020 *chip;
+       struct rtc_device *rtc;
+       int retval = -EBUSY;
+       int i;
+       int temp;
+
+       if (pdev->num_resources != 1)
+               return -EBUSY;
+
+       if (pdev->resource[0].flags != IORESOURCE_MEM)
+               return -EBUSY;
+
+       if (pdev == NULL)
+               return -EBUSY;
+
+       chip = kzalloc(sizeof *chip, GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->leftshift = pdata->leftshift;
+       chip->ioaddress = ioremap(pdev->resource[0].start, 1);
+       if (chip->ioaddress == NULL)
+               goto err_chip;
+
+       /* Make sure the v3020 expects a communication cycle
+        * by reading 8 times */
+       for (i = 0; i < 8; i++)
+               temp = readl(chip->ioaddress);
+
+       /* Test chip by doing a write/read sequence
+        * to the chip ram */
+       v3020_set_reg(chip, V3020_SECONDS, 0x33);
+       if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) {
+               retval = -ENODEV;
+               goto err_io;
+       }
+
+       /* Make sure frequency measurment mode, test modes, and lock
+        * are all disabled */
+       v3020_set_reg(chip, V3020_STATUS_0, 0x0);
+
+       dev_info(&pdev->dev, "Chip available at physical address 0x%p,"
+               "data connected to D%d\n",
+               (void*)pdev->resource[0].start,
+               chip->leftshift);
+
+       platform_set_drvdata(pdev, chip);
+
+       rtc = rtc_device_register("v3020",
+                               &pdev->dev, &v3020_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               retval = PTR_ERR(rtc);
+               goto err_io;
+       }
+       chip->rtc = rtc;
+
+       return 0;
+
+err_io:
+       iounmap(chip->ioaddress);
+err_chip:
+       kfree(chip);
+
+       return retval;
+}
+
+static int rtc_remove(struct platform_device *dev)
+{
+       struct v3020 *chip = platform_get_drvdata(dev);
+       struct rtc_device *rtc = chip->rtc;
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+
+       iounmap(chip->ioaddress);
+       kfree(chip);
+
+       return 0;
+}
+
+static struct platform_driver rtc_device_driver = {
+       .probe  = rtc_probe,
+       .remove = rtc_remove,
+       .driver = {
+               .name   = "v3020",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static __init int v3020_init(void)
+{
+       return platform_driver_register(&rtc_device_driver);
+}
+
+static __exit void v3020_exit(void)
+{
+       platform_driver_unregister(&rtc_device_driver);
+}
+
+module_init(v3020_init);
+module_exit(v3020_exit);
+
+MODULE_DESCRIPTION("V3020 RTC");
+MODULE_AUTHOR("Raphael Assenat");
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
new file mode 100644 (file)
index 0000000..28bfb8f
--- /dev/null
@@ -0,0 +1,942 @@
+/*
+ * HighPoint RR3xxx controller driver for Linux
+ * Copyright (C) 2006 HighPoint Technologies, 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; 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.
+ *
+ * Please report bugs/comments/suggestions to linux@highpoint-tech.com
+ *
+ * For more information, visit http://www.highpoint-tech.com
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/hdreg.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_host.h>
+
+#include "hptiop.h"
+
+MODULE_AUTHOR("HighPoint Technologies, Inc.");
+MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver");
+
+static char driver_name[] = "hptiop";
+static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver";
+static const char driver_ver[] = "v1.0 (060426)";
+
+static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag);
+static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag);
+static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);
+
+static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop)
+{
+       readl(&iop->outbound_intstatus);
+}
+
+static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec)
+{
+       u32 req = 0;
+       int i;
+
+       for (i = 0; i < millisec; i++) {
+               req = readl(&iop->inbound_queue);
+               if (req != IOPMU_QUEUE_EMPTY)
+                       break;
+               msleep(1);
+       }
+
+       if (req != IOPMU_QUEUE_EMPTY) {
+               writel(req, &iop->outbound_queue);
+               hptiop_pci_posting_flush(iop);
+               return 0;
+       }
+
+       return -1;
+}
+
+static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag)
+{
+       if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT)
+               return hptiop_host_request_callback(hba,
+                               tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
+       else
+               return hptiop_iop_request_callback(hba, tag);
+}
+
+static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba)
+{
+       u32 req;
+
+       while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) {
+
+               if (req & IOPMU_QUEUE_MASK_HOST_BITS)
+                       hptiop_request_callback(hba, req);
+               else {
+                       struct hpt_iop_request_header __iomem * p;
+
+                       p = (struct hpt_iop_request_header __iomem *)
+                               ((char __iomem *)hba->iop + req);
+
+                       if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) {
+                               if (readl(&p->context))
+                                       hptiop_request_callback(hba, req);
+                               else
+                                       writel(1, &p->context);
+                       }
+                       else
+                               hptiop_request_callback(hba, req);
+               }
+       }
+}
+
+static int __iop_intr(struct hptiop_hba *hba)
+{
+       struct hpt_iopmu __iomem *iop = hba->iop;
+       u32 status;
+       int ret = 0;
+
+       status = readl(&iop->outbound_intstatus);
+
+       if (status & IOPMU_OUTBOUND_INT_MSG0) {
+               u32 msg = readl(&iop->outbound_msgaddr0);
+               dprintk("received outbound msg %x\n", msg);
+               writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus);
+               hptiop_message_callback(hba, msg);
+               ret = 1;
+       }
+
+       if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
+               hptiop_drain_outbound_queue(hba);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static int iop_send_sync_request(struct hptiop_hba *hba,
+                                       void __iomem *_req, u32 millisec)
+{
+       struct hpt_iop_request_header __iomem *req = _req;
+       u32 i;
+
+       writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST,
+                       &req->flags);
+
+       writel(0, &req->context);
+
+       writel((unsigned long)req - (unsigned long)hba->iop,
+                       &hba->iop->inbound_queue);
+
+       hptiop_pci_posting_flush(hba->iop);
+
+       for (i = 0; i < millisec; i++) {
+               __iop_intr(hba);
+               if (readl(&req->context))
+                       return 0;
+               msleep(1);
+       }
+
+       return -1;
+}
+
+static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
+{
+       u32 i;
+
+       hba->msg_done = 0;
+
+       writel(msg, &hba->iop->inbound_msgaddr0);
+
+       hptiop_pci_posting_flush(hba->iop);
+
+       for (i = 0; i < millisec; i++) {
+               spin_lock_irq(hba->host->host_lock);
+               __iop_intr(hba);
+               spin_unlock_irq(hba->host->host_lock);
+               if (hba->msg_done)
+                       break;
+               msleep(1);
+       }
+
+       return hba->msg_done? 0 : -1;
+}
+
+static int iop_get_config(struct hptiop_hba *hba,
+                               struct hpt_iop_request_get_config *config)
+{
+       u32 req32;
+       struct hpt_iop_request_get_config __iomem *req;
+
+       req32 = readl(&hba->iop->inbound_queue);
+       if (req32 == IOPMU_QUEUE_EMPTY)
+               return -1;
+
+       req = (struct hpt_iop_request_get_config __iomem *)
+                       ((unsigned long)hba->iop + req32);
+
+       writel(0, &req->header.flags);
+       writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type);
+       writel(sizeof(struct hpt_iop_request_get_config), &req->header.size);
+       writel(IOP_RESULT_PENDING, &req->header.result);
+
+       if (iop_send_sync_request(hba, req, 20000)) {
+               dprintk("Get config send cmd failed\n");
+               return -1;
+       }
+
+       memcpy_fromio(config, req, sizeof(*config));
+       writel(req32, &hba->iop->outbound_queue);
+       return 0;
+}
+
+static int iop_set_config(struct hptiop_hba *hba,
+                               struct hpt_iop_request_set_config *config)
+{
+       u32 req32;
+       struct hpt_iop_request_set_config __iomem *req;
+
+       req32 = readl(&hba->iop->inbound_queue);
+       if (req32 == IOPMU_QUEUE_EMPTY)
+               return -1;
+
+       req = (struct hpt_iop_request_set_config __iomem *)
+                       ((unsigned long)hba->iop + req32);
+
+       memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header),
+               (u8 *)config + sizeof(struct hpt_iop_request_header),
+               sizeof(struct hpt_iop_request_set_config) -
+                       sizeof(struct hpt_iop_request_header));
+
+       writel(0, &req->header.flags);
+       writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type);
+       writel(sizeof(struct hpt_iop_request_set_config), &req->header.size);
+       writel(IOP_RESULT_PENDING, &req->header.result);
+
+       if (iop_send_sync_request(hba, req, 20000)) {
+               dprintk("Set config send cmd failed\n");
+               return -1;
+       }
+
+       writel(req32, &hba->iop->outbound_queue);
+       return 0;
+}
+
+static int hptiop_initialize_iop(struct hptiop_hba *hba)
+{
+       struct hpt_iopmu __iomem *iop = hba->iop;
+
+       /* enable interrupts */
+       writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),
+                       &iop->outbound_intmask);
+
+       hba->initialized = 1;
+
+       /* start background tasks */
+       if (iop_send_sync_msg(hba,
+                       IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
+               printk(KERN_ERR "scsi%d: fail to start background task\n",
+                       hba->host->host_no);
+               return -1;
+       }
+       return 0;
+}
+
+static int hptiop_map_pci_bar(struct hptiop_hba *hba)
+{
+       u32 mem_base_phy, length;
+       void __iomem *mem_base_virt;
+       struct pci_dev *pcidev = hba->pcidev;
+
+       if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
+               printk(KERN_ERR "scsi%d: pci resource invalid\n",
+                               hba->host->host_no);
+               return -1;
+       }
+
+       mem_base_phy = pci_resource_start(pcidev, 0);
+       length = pci_resource_len(pcidev, 0);
+       mem_base_virt = ioremap(mem_base_phy, length);
+
+       if (!mem_base_virt) {
+               printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n",
+                               hba->host->host_no);
+               return -1;
+       }
+
+       hba->iop = mem_base_virt;
+       dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop);
+       return 0;
+}
+
+static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)
+{
+       dprintk("iop message 0x%x\n", msg);
+
+       if (!hba->initialized)
+               return;
+
+       if (msg == IOPMU_INBOUND_MSG0_RESET) {
+               atomic_set(&hba->resetting, 0);
+               wake_up(&hba->reset_wq);
+       }
+       else if (msg <= IOPMU_INBOUND_MSG0_MAX)
+               hba->msg_done = 1;
+}
+
+static inline struct hptiop_request *get_req(struct hptiop_hba *hba)
+{
+       struct hptiop_request *ret;
+
+       dprintk("get_req : req=%p\n", hba->req_list);
+
+       ret = hba->req_list;
+       if (ret)
+               hba->req_list = ret->next;
+
+       return ret;
+}
+
+static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req)
+{
+       dprintk("free_req(%d, %p)\n", req->index, req);
+       req->next = hba->req_list;
+       hba->req_list = req;
+}
+
+static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag)
+{
+       struct hpt_iop_request_scsi_command *req;
+       struct scsi_cmnd *scp;
+
+       req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt;
+       dprintk("hptiop_host_request_callback: req=%p, type=%d, "
+                       "result=%d, context=0x%x tag=%d\n",
+                       req, req->header.type, req->header.result,
+                       req->header.context, tag);
+
+       BUG_ON(!req->header.result);
+       BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND));
+
+       scp = hba->reqs[tag].scp;
+
+       if (HPT_SCP(scp)->mapped) {
+               if (scp->use_sg)
+                       pci_unmap_sg(hba->pcidev,
+                               (struct scatterlist *)scp->request_buffer,
+                               scp->use_sg,
+                               scp->sc_data_direction
+                       );
+               else
+                       pci_unmap_single(hba->pcidev,
+                               HPT_SCP(scp)->dma_handle,
+                               scp->request_bufflen,
+                               scp->sc_data_direction
+                       );
+       }
+
+       switch (le32_to_cpu(req->header.result)) {
+       case IOP_RESULT_SUCCESS:
+               scp->result = (DID_OK<<16);
+               break;
+       case IOP_RESULT_BAD_TARGET:
+               scp->result = (DID_BAD_TARGET<<16);
+               break;
+       case IOP_RESULT_BUSY:
+               scp->result = (DID_BUS_BUSY<<16);
+               break;
+       case IOP_RESULT_RESET:
+               scp->result = (DID_RESET<<16);
+               break;
+       case IOP_RESULT_FAIL:
+               scp->result = (DID_ERROR<<16);
+               break;
+       case IOP_RESULT_INVALID_REQUEST:
+               scp->result = (DID_ABORT<<16);
+               break;
+       case IOP_RESULT_MODE_SENSE_CHECK_CONDITION:
+               scp->result = SAM_STAT_CHECK_CONDITION;
+               memset(&scp->sense_buffer,
+                               0, sizeof(scp->sense_buffer));
+               memcpy(&scp->sense_buffer,
+                       &req->sg_list, le32_to_cpu(req->dataxfer_length));
+               break;
+
+       default:
+               scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) |
+                                       (DID_ABORT<<16);
+               break;
+       }
+
+       dprintk("scsi_done(%p)\n", scp);
+       scp->scsi_done(scp);
+       free_req(hba, &hba->reqs[tag]);
+}
+
+void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag)
+{
+       struct hpt_iop_request_header __iomem *req;
+       struct hpt_iop_request_ioctl_command __iomem *p;
+       struct hpt_ioctl_k *arg;
+
+       req = (struct hpt_iop_request_header __iomem *)
+                       ((unsigned long)hba->iop + tag);
+       dprintk("hptiop_iop_request_callback: req=%p, type=%d, "
+                       "result=%d, context=0x%x tag=%d\n",
+                       req, readl(&req->type), readl(&req->result),
+                       readl(&req->context), tag);
+
+       BUG_ON(!readl(&req->result));
+       BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND);
+
+       p = (struct hpt_iop_request_ioctl_command __iomem *)req;
+       arg = (struct hpt_ioctl_k *)(unsigned long)
+               (readl(&req->context) |
+                       ((u64)readl(&req->context_hi32)<<32));
+
+       if (readl(&req->result) == IOP_RESULT_SUCCESS) {
+               arg->result = HPT_IOCTL_RESULT_OK;
+
+               if (arg->outbuf_size)
+                       memcpy_fromio(arg->outbuf,
+                               &p->buf[(readl(&p->inbuf_size) + 3)& ~3],
+                               arg->outbuf_size);
+
+               if (arg->bytes_returned)
+                       *arg->bytes_returned = arg->outbuf_size;
+       }
+       else
+               arg->result = HPT_IOCTL_RESULT_FAILED;
+
+       arg->done(arg);
+       writel(tag, &hba->iop->outbound_queue);
+}
+
+static irqreturn_t hptiop_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct hptiop_hba  *hba = dev_id;
+       int  handled;
+       unsigned long flags;
+
+       spin_lock_irqsave(hba->host->host_lock, flags);
+       handled = __iop_intr(hba);
+       spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+       return handled;
+}
+
+static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg)
+{
+       struct Scsi_Host *host = scp->device->host;
+       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+       struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer;
+
+       /*
+        * though we'll not get non-use_sg fields anymore,
+        * keep use_sg checking anyway
+        */
+       if (scp->use_sg) {
+               int idx;
+
+               HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev,
+                               sglist, scp->use_sg,
+                               scp->sc_data_direction);
+               HPT_SCP(scp)->mapped = 1;
+               BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
+
+               for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) {
+                       psg[idx].pci_address =
+                               cpu_to_le64(sg_dma_address(&sglist[idx]));
+                       psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx]));
+                       psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
+                               cpu_to_le32(1) : 0;
+               }
+
+               return HPT_SCP(scp)->sgcnt;
+       } else {
+               HPT_SCP(scp)->dma_handle = pci_map_single(
+                               hba->pcidev,
+                               scp->request_buffer,
+                               scp->request_bufflen,
+                               scp->sc_data_direction
+                       );
+               HPT_SCP(scp)->mapped = 1;
+               psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle);
+               psg->size = cpu_to_le32(scp->request_bufflen);
+               psg->eot = cpu_to_le32(1);
+               return 1;
+       }
+}
+
+static int hptiop_queuecommand(struct scsi_cmnd *scp,
+                               void (*done)(struct scsi_cmnd *))
+{
+       struct Scsi_Host *host = scp->device->host;
+       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+       struct hpt_iop_request_scsi_command *req;
+       int sg_count = 0;
+       struct hptiop_request *_req;
+
+       BUG_ON(!done);
+       scp->scsi_done = done;
+
+       _req = get_req(hba);
+       if (_req == NULL) {
+               dprintk("hptiop_queuecmd : no free req\n");
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       _req->scp = scp;
+
+       dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) "
+                       "req_index=%d, req=%p\n",
+                       scp,
+                       host->host_no, scp->device->channel,
+                       scp->device->id, scp->device->lun,
+                       *((u32 *)&scp->cmnd),
+                       *((u32 *)&scp->cmnd + 1),
+                       *((u32 *)&scp->cmnd + 2),
+                       _req->index, _req->req_virt);
+
+       scp->result = 0;
+
+       if (scp->device->channel || scp->device->lun ||
+                       scp->device->id > hba->max_devices) {
+               scp->result = DID_BAD_TARGET << 16;
+               free_req(hba, _req);
+               goto cmd_done;
+       }
+
+       req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
+
+       /* build S/G table */
+       if (scp->request_bufflen)
+               sg_count = hptiop_buildsgl(scp, req->sg_list);
+       else
+               HPT_SCP(scp)->mapped = 0;
+
+       req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
+       req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND);
+       req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+       req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
+                                                       (u32)_req->index);
+       req->header.context_hi32 = 0;
+       req->dataxfer_length = cpu_to_le32(scp->request_bufflen);
+       req->channel = scp->device->channel;
+       req->target = scp->device->id;
+       req->lun = scp->device->lun;
+       req->header.size = cpu_to_le32(
+                               sizeof(struct hpt_iop_request_scsi_command)
+                                - sizeof(struct hpt_iopsg)
+                                + sg_count * sizeof(struct hpt_iopsg));
+
+       memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
+
+       writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy,
+                       &hba->iop->inbound_queue);
+
+       return 0;
+
+cmd_done:
+       dprintk("scsi_done(scp=%p)\n", scp);
+       scp->scsi_done(scp);
+       return 0;
+}
+
+static const char *hptiop_info(struct Scsi_Host *host)
+{
+       return driver_name_long;
+}
+
+static int hptiop_reset_hba(struct hptiop_hba *hba)
+{
+       if (atomic_xchg(&hba->resetting, 1) == 0) {
+               atomic_inc(&hba->reset_count);
+               writel(IOPMU_INBOUND_MSG0_RESET,
+                               &hba->iop->inbound_msgaddr0);
+               hptiop_pci_posting_flush(hba->iop);
+       }
+
+       wait_event_timeout(hba->reset_wq,
+                       atomic_read(&hba->resetting) == 0, 60 * HZ);
+
+       if (atomic_read(&hba->resetting)) {
+               /* IOP is in unkown state, abort reset */
+               printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no);
+               return -1;
+       }
+
+       if (iop_send_sync_msg(hba,
+               IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
+               dprintk("scsi%d: fail to start background task\n",
+                               hba->host->host_no);
+       }
+
+       return 0;
+}
+
+static int hptiop_reset(struct scsi_cmnd *scp)
+{
+       struct Scsi_Host * host = scp->device->host;
+       struct hptiop_hba * hba = (struct hptiop_hba *)host->hostdata;
+
+       printk(KERN_WARNING "hptiop_reset(%d/%d/%d) scp=%p\n",
+                       scp->device->host->host_no, scp->device->channel,
+                       scp->device->id, scp);
+
+       return hptiop_reset_hba(hba)? FAILED : SUCCESS;
+}
+
+static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
+                                               int queue_depth)
+{
+       if(queue_depth > 256)
+               queue_depth = 256;
+       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+       return queue_depth;
+}
+
+static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
+}
+
+static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
+{
+       struct Scsi_Host *host = class_to_shost(class_dev);
+       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+
+       return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
+                               hba->firmware_version >> 24,
+                               (hba->firmware_version >> 16) & 0xff,
+                               (hba->firmware_version >> 8) & 0xff,
+                               hba->firmware_version & 0xff);
+}
+
+static struct class_device_attribute hptiop_attr_version = {
+       .attr = {
+               .name = "driver-version",
+               .mode = S_IRUGO,
+       },
+       .show = hptiop_show_version,
+};
+
+static struct class_device_attribute hptiop_attr_fw_version = {
+       .attr = {
+               .name = "firmware-version",
+               .mode = S_IRUGO,
+       },
+       .show = hptiop_show_fw_version,
+};
+
+static struct class_device_attribute *hptiop_attrs[] = {
+       &hptiop_attr_version,
+       &hptiop_attr_fw_version,
+       NULL
+};
+
+static struct scsi_host_template driver_template = {
+       .module                     = THIS_MODULE,
+       .name                       = driver_name,
+       .queuecommand               = hptiop_queuecommand,
+       .eh_device_reset_handler    = hptiop_reset,
+       .eh_bus_reset_handler       = hptiop_reset,
+       .info                       = hptiop_info,
+       .unchecked_isa_dma          = 0,
+       .emulated                   = 0,
+       .use_clustering             = ENABLE_CLUSTERING,
+       .proc_name                  = driver_name,
+       .shost_attrs                = hptiop_attrs,
+       .this_id                    = -1,
+       .change_queue_depth         = hptiop_adjust_disk_queue_depth,
+};
+
+static int __devinit hptiop_probe(struct pci_dev *pcidev,
+                                       const struct pci_device_id *id)
+{
+       struct Scsi_Host *host = NULL;
+       struct hptiop_hba *hba;
+       struct hpt_iop_request_get_config iop_config;
+       struct hpt_iop_request_set_config set_config;
+       dma_addr_t start_phy;
+       void *start_virt;
+       u32 offset, i, req_size;
+
+       dprintk("hptiop_probe(%p)\n", pcidev);
+
+       if (pci_enable_device(pcidev)) {
+               printk(KERN_ERR "hptiop: fail to enable pci device\n");
+               return -ENODEV;
+       }
+
+       printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d\n",
+               pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7,
+               pcidev->irq);
+
+       pci_set_master(pcidev);
+
+       /* Enable 64bit DMA if possible */
+       if (pci_set_dma_mask(pcidev, DMA_64BIT_MASK)) {
+               if (pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
+                       printk(KERN_ERR "hptiop: fail to set dma_mask\n");
+                       goto disable_pci_device;
+               }
+       }
+
+       if (pci_request_regions(pcidev, driver_name)) {
+               printk(KERN_ERR "hptiop: pci_request_regions failed\n");
+               goto disable_pci_device;
+       }
+
+       host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba));
+       if (!host) {
+               printk(KERN_ERR "hptiop: fail to alloc scsi host\n");
+               goto free_pci_regions;
+       }
+
+       hba = (struct hptiop_hba *)host->hostdata;
+
+       hba->pcidev = pcidev;
+       hba->host = host;
+       hba->initialized = 0;
+
+       atomic_set(&hba->resetting, 0);
+       atomic_set(&hba->reset_count, 0);
+
+       init_waitqueue_head(&hba->reset_wq);
+       init_waitqueue_head(&hba->ioctl_wq);
+
+       host->max_lun = 1;
+       host->max_channel = 0;
+       host->io_port = 0;
+       host->n_io_port = 0;
+       host->irq = pcidev->irq;
+
+       if (hptiop_map_pci_bar(hba))
+               goto free_scsi_host;
+
+       if (iop_wait_ready(hba->iop, 20000)) {
+               printk(KERN_ERR "scsi%d: firmware not ready\n",
+                               hba->host->host_no);
+               goto unmap_pci_bar;
+       }
+
+       if (iop_get_config(hba, &iop_config)) {
+               printk(KERN_ERR "scsi%d: get config failed\n",
+                               hba->host->host_no);
+               goto unmap_pci_bar;
+       }
+
+       hba->max_requests = min(le32_to_cpu(iop_config.max_requests),
+                               HPTIOP_MAX_REQUESTS);
+       hba->max_devices = le32_to_cpu(iop_config.max_devices);
+       hba->max_request_size = le32_to_cpu(iop_config.request_size);
+       hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);
+       hba->firmware_version = le32_to_cpu(iop_config.firmware_version);
+       hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
+
+       host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9;
+       host->max_id = le32_to_cpu(iop_config.max_devices);
+       host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count);
+       host->can_queue = le32_to_cpu(iop_config.max_requests);
+       host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
+       host->max_cmd_len = 16;
+
+       set_config.vbus_id = cpu_to_le32(host->host_no);
+       set_config.iop_id = cpu_to_le32(host->host_no);
+
+       if (iop_set_config(hba, &set_config)) {
+               printk(KERN_ERR "scsi%d: set config failed\n",
+                               hba->host->host_no);
+               goto unmap_pci_bar;
+       }
+
+       pci_set_drvdata(pcidev, host);
+
+       if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED,
+                                       driver_name, hba)) {
+               printk(KERN_ERR "scsi%d: request irq %d failed\n",
+                                       hba->host->host_no, pcidev->irq);
+               goto unmap_pci_bar;
+       }
+
+       /* Allocate request mem */
+       req_size = sizeof(struct hpt_iop_request_scsi_command)
+               + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1);
+       if ((req_size& 0x1f) != 0)
+               req_size = (req_size + 0x1f) & ~0x1f;
+
+       dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests);
+
+       hba->req_size = req_size;
+       start_virt = dma_alloc_coherent(&pcidev->dev,
+                               hba->req_size*hba->max_requests + 0x20,
+                               &start_phy, GFP_KERNEL);
+
+       if (!start_virt) {
+               printk(KERN_ERR "scsi%d: fail to alloc request mem\n",
+                                       hba->host->host_no);
+               goto free_request_irq;
+       }
+
+       hba->dma_coherent = start_virt;
+       hba->dma_coherent_handle = start_phy;
+
+       if ((start_phy & 0x1f) != 0)
+       {
+               offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
+               start_phy += offset;
+               start_virt += offset;
+       }
+
+       hba->req_list = start_virt;
+       for (i = 0; i < hba->max_requests; i++) {
+               hba->reqs[i].next = NULL;
+               hba->reqs[i].req_virt = start_virt;
+               hba->reqs[i].req_shifted_phy = start_phy >> 5;
+               hba->reqs[i].index = i;
+               free_req(hba, &hba->reqs[i]);
+               start_virt = (char *)start_virt + hba->req_size;
+               start_phy = start_phy + hba->req_size;
+       }
+
+       /* Enable Interrupt and start background task */
+       if (hptiop_initialize_iop(hba))
+               goto free_request_mem;
+
+       if (scsi_add_host(host, &pcidev->dev)) {
+               printk(KERN_ERR "scsi%d: scsi_add_host failed\n",
+                                       hba->host->host_no);
+               goto free_request_mem;
+       }
+
+
+       scsi_scan_host(host);
+
+       dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no);
+       return 0;
+
+free_request_mem:
+       dma_free_coherent(&hba->pcidev->dev,
+                       hba->req_size*hba->max_requests + 0x20,
+                       hba->dma_coherent, hba->dma_coherent_handle);
+
+free_request_irq:
+       free_irq(hba->pcidev->irq, hba);
+
+unmap_pci_bar:
+       iounmap(hba->iop);
+
+free_pci_regions:
+       pci_release_regions(pcidev) ;
+
+free_scsi_host:
+       scsi_host_put(host);
+
+disable_pci_device:
+       pci_disable_device(pcidev);
+
+       dprintk("scsi%d: hptiop_probe fail\n", host->host_no);
+       return -ENODEV;
+}
+
+static void hptiop_shutdown(struct pci_dev *pcidev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pcidev);
+       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+       struct hpt_iopmu __iomem *iop = hba->iop;
+       u32    int_mask;
+
+       dprintk("hptiop_shutdown(%p)\n", hba);
+
+       /* stop the iop */
+       if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
+               printk(KERN_ERR "scsi%d: shutdown the iop timeout\n",
+                                       hba->host->host_no);
+
+       /* disable all outbound interrupts */
+       int_mask = readl(&iop->outbound_intmask);
+       writel(int_mask |
+               IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE,
+               &iop->outbound_intmask);
+       hptiop_pci_posting_flush(iop);
+}
+
+static void hptiop_remove(struct pci_dev *pcidev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pcidev);
+       struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+
+       dprintk("scsi%d: hptiop_remove\n", hba->host->host_no);
+
+       scsi_remove_host(host);
+
+       hptiop_shutdown(pcidev);
+
+       free_irq(hba->pcidev->irq, hba);
+
+       dma_free_coherent(&hba->pcidev->dev,
+                       hba->req_size * hba->max_requests + 0x20,
+                       hba->dma_coherent,
+                       hba->dma_coherent_handle);
+
+       iounmap(hba->iop);
+
+       pci_release_regions(hba->pcidev);
+       pci_set_drvdata(hba->pcidev, NULL);
+       pci_disable_device(hba->pcidev);
+
+       scsi_host_put(host);
+}
+
+static struct pci_device_id hptiop_id_table[] = {
+       { PCI_DEVICE(0x1103, 0x3220) },
+       { PCI_DEVICE(0x1103, 0x3320) },
+       {},
+};
+
+MODULE_DEVICE_TABLE(pci, hptiop_id_table);
+
+static struct pci_driver hptiop_pci_driver = {
+       .name       = driver_name,
+       .id_table   = hptiop_id_table,
+       .probe      = hptiop_probe,
+       .remove     = hptiop_remove,
+       .shutdown   = hptiop_shutdown,
+};
+
+static int __init hptiop_module_init(void)
+{
+       printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver);
+       return pci_register_driver(&hptiop_pci_driver);
+}
+
+static void __exit hptiop_module_exit(void)
+{
+       pci_unregister_driver(&hptiop_pci_driver);
+}
+
+
+module_init(hptiop_module_init);
+module_exit(hptiop_module_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h
new file mode 100644 (file)
index 0000000..f04f7e8
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * HighPoint RR3xxx controller driver for Linux
+ * Copyright (C) 2006 HighPoint Technologies, 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; 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.
+ *
+ * Please report bugs/comments/suggestions to linux@highpoint-tech.com
+ *
+ * For more information, visit http://www.highpoint-tech.com
+ */
+#ifndef _HPTIOP_H_
+#define _HPTIOP_H_
+
+/*
+ * logical device type.
+ * Identify array (logical device) and physical device.
+ */
+#define LDT_ARRAY   1
+#define LDT_DEVICE  2
+
+/*
+ * Array types
+ */
+#define AT_UNKNOWN  0
+#define AT_RAID0    1
+#define AT_RAID1    2
+#define AT_RAID5    3
+#define AT_RAID6    4
+#define AT_JBOD     7
+
+#define MAX_NAME_LENGTH     36
+#define MAX_ARRAYNAME_LEN   16
+
+#define MAX_ARRAY_MEMBERS_V1 8
+#define MAX_ARRAY_MEMBERS_V2 16
+
+/* keep definition for source code compatiblity */
+#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1
+
+/*
+ * array flags
+ */
+#define ARRAY_FLAG_DISABLED         0x00000001 /* The array is disabled */
+#define ARRAY_FLAG_NEEDBUILDING     0x00000002 /* need to be rebuilt */
+#define ARRAY_FLAG_REBUILDING       0x00000004 /* in rebuilding process */
+#define ARRAY_FLAG_BROKEN           0x00000008 /* broken but still working */
+#define ARRAY_FLAG_BOOTDISK         0x00000010 /* has a active partition */
+#define ARRAY_FLAG_BOOTMARK         0x00000040 /* array has boot mark set */
+#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */
+#define ARRAY_FLAG_VERIFYING        0x00000100 /* is being verified */
+#define ARRAY_FLAG_INITIALIZING     0x00000200 /* is being initialized */
+#define ARRAY_FLAG_TRANSFORMING     0x00000400 /* tranform in progress */
+#define ARRAY_FLAG_NEEDTRANSFORM    0x00000800 /* array need tranform */
+#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */
+#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */
+
+/*
+ * device flags
+ */
+#define DEVICE_FLAG_DISABLED        0x00000001 /* device is disabled */
+#define DEVICE_FLAG_UNINITIALIZED   0x00010000 /* device is not initialized */
+#define DEVICE_FLAG_LEGACY          0x00020000 /* lagacy drive */
+#define DEVICE_FLAG_IS_SPARE        0x80000000 /* is a spare disk */
+
+/*
+ * ioctl codes
+ */
+#define HPT_CTL_CODE(x) (x+0xFF00)
+#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00)
+
+#define HPT_IOCTL_GET_CONTROLLER_INFO       HPT_CTL_CODE(2)
+#define HPT_IOCTL_GET_CHANNEL_INFO          HPT_CTL_CODE(3)
+#define HPT_IOCTL_GET_LOGICAL_DEVICES       HPT_CTL_CODE(4)
+#define HPT_IOCTL_GET_DRIVER_CAPABILITIES   HPT_CTL_CODE(19)
+#define HPT_IOCTL_GET_DEVICE_INFO_V3        HPT_CTL_CODE(46)
+#define HPT_IOCTL_GET_CONTROLLER_INFO_V2    HPT_CTL_CODE(47)
+
+/*
+ * Controller information.
+ */
+struct hpt_controller_info {
+       u8      chip_type;                    /* chip type */
+       u8      interrupt_level;              /* IRQ level */
+       u8      num_buses;                    /* bus count */
+       u8      chip_flags;
+
+       u8      product_id[MAX_NAME_LENGTH];/* product name */
+       u8      vendor_id[MAX_NAME_LENGTH]; /* vendor name */
+}
+__attribute__((packed));
+
+/*
+ * Channel information.
+ */
+struct hpt_channel_info {
+       __le32  io_port;         /* IDE Base Port Address */
+       __le32  control_port;    /* IDE Control Port Address */
+       __le32  devices[2];      /* device connected to this channel */
+}
+__attribute__((packed));
+
+/*
+ * Array information.
+ */
+struct hpt_array_info_v3 {
+       u8      name[MAX_ARRAYNAME_LEN]; /* array name */
+       u8      description[64];         /* array description */
+       u8      create_manager[16];      /* who created it */
+       __le32  create_time;             /* when created it */
+
+       u8      array_type;              /* array type */
+       u8      block_size_shift;        /* stripe size */
+       u8      ndisk;                   /* Number of ID in Members[] */
+       u8      reserved;
+
+       __le32  flags;                   /* working flags, see ARRAY_FLAG_XXX */
+       __le32  members[MAX_ARRAY_MEMBERS_V2];  /* member array/disks */
+
+       __le32  rebuilding_progress;
+       __le64  rebuilt_sectors; /* rebuilding point (LBA) for single member */
+
+       __le32  transform_source;
+       __le32  transform_target;    /* destination device ID */
+       __le32  transforming_progress;
+       __le32  signature;              /* persistent identification*/
+       __le16  critical_members;       /* bit mask of critical members */
+       __le16  reserve2;
+       __le32  reserve;
+}
+__attribute__((packed));
+
+/*
+ * physical device information.
+ */
+#define MAX_PARENTS_PER_DISK    8
+
+struct hpt_device_info_v2 {
+       u8   ctlr_id;             /* controller id */
+       u8   path_id;             /* bus */
+       u8   target_id;           /* id */
+       u8   device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */
+                                 /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */
+       u8   device_type;         /* device type */
+       u8   usable_mode;         /* highest usable mode */
+
+#ifdef __BIG_ENDIAN_BITFIELD
+       u8   NCQ_enabled: 1;
+       u8   NCQ_supported: 1;
+       u8   TCQ_enabled: 1;
+       u8   TCQ_supported: 1;
+       u8   write_cache_enabled: 1;
+       u8   write_cache_supported: 1;
+       u8   read_ahead_enabled: 1;
+       u8   read_ahead_supported: 1;
+       u8   reserved6: 6;
+       u8   spin_up_mode: 2;
+#else
+       u8   read_ahead_supported: 1;
+       u8   read_ahead_enabled: 1;
+       u8   write_cache_supported: 1;
+       u8   write_cache_enabled: 1;
+       u8   TCQ_supported: 1;
+       u8   TCQ_enabled: 1;
+       u8   NCQ_supported: 1;
+       u8   NCQ_enabled: 1;
+       u8   spin_up_mode: 2;
+       u8   reserved6: 6;
+#endif
+
+       __le32  flags;         /* working flags, see DEVICE_FLAG_XXX */
+       u8      ident[150];    /* (partitial) Identify Data of this device */
+
+       __le64  total_free;
+       __le64  max_free;
+       __le64  bad_sectors;
+       __le32  parent_arrays[MAX_PARENTS_PER_DISK];
+}
+__attribute__((packed));
+
+/*
+ * Logical device information.
+ */
+#define INVALID_TARGET_ID   0xFF
+#define INVALID_BUS_ID      0xFF
+
+struct hpt_logical_device_info_v3 {
+       u8       type;                   /* LDT_ARRAY or LDT_DEVICE */
+       u8       cache_policy;           /* refer to CACHE_POLICY_xxx */
+       u8       vbus_id;                /* vbus sequence in vbus_list */
+       u8       target_id;              /* OS target id. 0xFF is invalid */
+                                        /* OS name: DISK $VBusId_$TargetId */
+       __le64   capacity;               /* array capacity */
+       __le32   parent_array;           /* don't use this field for physical
+                                           device. use ParentArrays field in
+                                           hpt_device_info_v2 */
+       /* reserved statistic fields */
+       __le32   stat1;
+       __le32   stat2;
+       __le32   stat3;
+       __le32   stat4;
+
+       union {
+               struct hpt_array_info_v3 array;
+               struct hpt_device_info_v2 device;
+       } __attribute__((packed)) u;
+
+}
+__attribute__((packed));
+
+/*
+ * ioctl structure
+ */
+#define HPT_IOCTL_MAGIC   0xA1B2C3D4
+
+struct hpt_ioctl_u {
+       u32   magic;            /* used to check if it's a valid ioctl packet */
+       u32   ioctl_code;       /* operation control code */
+       void __user *inbuf;     /* input data buffer */
+       u32   inbuf_size;       /* size of input data buffer */
+       void __user *outbuf;    /* output data buffer */
+       u32   outbuf_size;      /* size of output data buffer */
+       void __user *bytes_returned;   /* count of bytes returned */
+}
+__attribute__((packed));
+
+
+struct hpt_iopmu
+{
+       __le32 resrved0[4];
+       __le32 inbound_msgaddr0;
+       __le32 inbound_msgaddr1;
+       __le32 outbound_msgaddr0;
+       __le32 outbound_msgaddr1;
+       __le32 inbound_doorbell;
+       __le32 inbound_intstatus;
+       __le32 inbound_intmask;
+       __le32 outbound_doorbell;
+       __le32 outbound_intstatus;
+       __le32 outbound_intmask;
+       __le32 reserved1[2];
+       __le32 inbound_queue;
+       __le32 outbound_queue;
+};
+
+#define IOPMU_QUEUE_EMPTY            0xffffffff
+#define IOPMU_QUEUE_MASK_HOST_BITS   0xf0000000
+#define IOPMU_QUEUE_ADDR_HOST_BIT    0x80000000
+
+#define IOPMU_OUTBOUND_INT_MSG0      1
+#define IOPMU_OUTBOUND_INT_MSG1      2
+#define IOPMU_OUTBOUND_INT_DOORBELL  4
+#define IOPMU_OUTBOUND_INT_POSTQUEUE 8
+#define IOPMU_OUTBOUND_INT_PCI       0x10
+
+#define IOPMU_INBOUND_INT_MSG0       1
+#define IOPMU_INBOUND_INT_MSG1       2
+#define IOPMU_INBOUND_INT_DOORBELL   4
+#define IOPMU_INBOUND_INT_ERROR      8
+#define IOPMU_INBOUND_INT_POSTQUEUE  0x10
+
+enum hpt_iopmu_message {
+       /* host-to-iop messages */
+       IOPMU_INBOUND_MSG0_NOP = 0,
+       IOPMU_INBOUND_MSG0_RESET,
+       IOPMU_INBOUND_MSG0_FLUSH,
+       IOPMU_INBOUND_MSG0_SHUTDOWN,
+       IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
+       IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
+       IOPMU_INBOUND_MSG0_MAX = 0xff,
+       /* iop-to-host messages */
+       IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
+       IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff,
+       IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200,
+       IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff,
+       IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300,
+       IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff,
+};
+
+struct hpt_iop_request_header
+{
+       __le32 size;
+       __le32 type;
+       __le32 flags;
+       __le32 result;
+       __le32 context; /* host context */
+       __le32 context_hi32;
+};
+
+#define IOP_REQUEST_FLAG_SYNC_REQUEST 1
+#define IOP_REQUEST_FLAG_BIST_REQUEST 2
+#define IOP_REQUEST_FLAG_REMAPPED     4
+#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8
+
+enum hpt_iop_request_type {
+       IOP_REQUEST_TYPE_GET_CONFIG = 0,
+       IOP_REQUEST_TYPE_SET_CONFIG,
+       IOP_REQUEST_TYPE_BLOCK_COMMAND,
+       IOP_REQUEST_TYPE_SCSI_COMMAND,
+       IOP_REQUEST_TYPE_IOCTL_COMMAND,
+       IOP_REQUEST_TYPE_MAX
+};
+
+enum hpt_iop_result_type {
+       IOP_RESULT_PENDING = 0,
+       IOP_RESULT_SUCCESS,
+       IOP_RESULT_FAIL,
+       IOP_RESULT_BUSY,
+       IOP_RESULT_RESET,
+       IOP_RESULT_INVALID_REQUEST,
+       IOP_RESULT_BAD_TARGET,
+       IOP_RESULT_MODE_SENSE_CHECK_CONDITION,
+};
+
+struct hpt_iop_request_get_config
+{
+       struct hpt_iop_request_header header;
+       __le32 interface_version;
+       __le32 firmware_version;
+       __le32 max_requests;
+       __le32 request_size;
+       __le32 max_sg_count;
+       __le32 data_transfer_length;
+       __le32 alignment_mask;
+       __le32 max_devices;
+       __le32 sdram_size;
+};
+
+struct hpt_iop_request_set_config
+{
+       struct hpt_iop_request_header header;
+       __le32 iop_id;
+       __le32 vbus_id;
+       __le32 reserve[6];
+};
+
+struct hpt_iopsg
+{
+       __le32 size;
+       __le32 eot; /* non-zero: end of table */
+       __le64 pci_address;
+};
+
+struct hpt_iop_request_block_command
+{
+       struct hpt_iop_request_header header;
+       u8     channel;
+       u8     target;
+       u8     lun;
+       u8     pad1;
+       __le16 command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */
+       __le16 sectors;
+       __le64 lba;
+       struct hpt_iopsg sg_list[1];
+};
+
+#define IOP_BLOCK_COMMAND_READ     1
+#define IOP_BLOCK_COMMAND_WRITE    2
+#define IOP_BLOCK_COMMAND_VERIFY   3
+#define IOP_BLOCK_COMMAND_FLUSH    4
+#define IOP_BLOCK_COMMAND_SHUTDOWN 5
+
+struct hpt_iop_request_scsi_command
+{
+       struct hpt_iop_request_header header;
+       u8     channel;
+       u8     target;
+       u8     lun;
+       u8     pad1;
+       u8     cdb[16];
+       __le32 dataxfer_length;
+       struct hpt_iopsg sg_list[1];
+};
+
+struct hpt_iop_request_ioctl_command
+{
+       struct hpt_iop_request_header header;
+       __le32 ioctl_code;
+       __le32 inbuf_size;
+       __le32 outbuf_size;
+       __le32 bytes_returned;
+       u8     buf[1];
+       /* out data should be put at buf[(inbuf_size+3)&~3] */
+};
+
+#define HPTIOP_MAX_REQUESTS  256u
+
+struct hptiop_request {
+       struct hptiop_request * next;
+       void *                  req_virt;
+       u32                     req_shifted_phy;
+       struct scsi_cmnd *      scp;
+       int                     index;
+};
+
+struct hpt_scsi_pointer {
+       int mapped;
+       int sgcnt;
+       dma_addr_t dma_handle;
+};
+
+#define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp)
+
+struct hptiop_hba {
+       struct hpt_iopmu __iomem * iop;
+       struct Scsi_Host * host;
+       struct pci_dev * pcidev;
+
+       struct list_head link;
+
+       /* IOP config info */
+       u32     firmware_version;
+       u32     sdram_size;
+       u32     max_devices;
+       u32     max_requests;
+       u32     max_request_size;
+       u32     max_sg_descriptors;
+
+       u32     req_size; /* host-allocated request buffer size */
+       int     initialized;
+       int     msg_done;
+
+       struct hptiop_request * req_list;
+       struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];
+
+       /* used to free allocated dma area */
+       void *      dma_coherent;
+       dma_addr_t  dma_coherent_handle;
+
+       atomic_t    reset_count;
+       atomic_t    resetting;
+
+       wait_queue_head_t reset_wq;
+       wait_queue_head_t ioctl_wq;
+};
+
+struct hpt_ioctl_k
+{
+       struct hptiop_hba * hba;
+       u32    ioctl_code;
+       u32    inbuf_size;
+       u32    outbuf_size;
+       void * inbuf;
+       void * outbuf;
+       u32  * bytes_returned;
+       void (*done)(struct hpt_ioctl_k *);
+       int    result; /* HPT_IOCTL_RESULT_ */
+};
+
+#define HPT_IOCTL_RESULT_OK         0
+#define HPT_IOCTL_RESULT_FAILED     (-1)
+
+#if 0
+#define dprintk(fmt, args...) do { printk(fmt, ##args); } while(0)
+#else
+#define dprintk(fmt, args...)
+#endif
+
+#endif
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
new file mode 100644 (file)
index 0000000..2c34af9
--- /dev/null
@@ -0,0 +1,2245 @@
+/*
+ *  libata-eh.c - libata error handling
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2006 Tejun Heo <htejun@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, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ *  USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *  Hardware documentation available from http://www.t13.org/ and
+ *  http://www.sata-io.org/
+ *
+ */
+
+#include <linux/kernel.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include "scsi_transport_api.h"
+
+#include <linux/libata.h>
+
+#include "libata.h"
+
+static void __ata_port_freeze(struct ata_port *ap);
+static void ata_eh_finish(struct ata_port *ap);
+static void ata_eh_handle_port_suspend(struct ata_port *ap);
+static void ata_eh_handle_port_resume(struct ata_port *ap);
+
+static void ata_ering_record(struct ata_ering *ering, int is_io,
+                            unsigned int err_mask)
+{
+       struct ata_ering_entry *ent;
+
+       WARN_ON(!err_mask);
+
+       ering->cursor++;
+       ering->cursor %= ATA_ERING_SIZE;
+
+       ent = &ering->ring[ering->cursor];
+       ent->is_io = is_io;
+       ent->err_mask = err_mask;
+       ent->timestamp = get_jiffies_64();
+}
+
+static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
+{
+       struct ata_ering_entry *ent = &ering->ring[ering->cursor];
+       if (!ent->err_mask)
+               return NULL;
+       return ent;
+}
+
+static int ata_ering_map(struct ata_ering *ering,
+                        int (*map_fn)(struct ata_ering_entry *, void *),
+                        void *arg)
+{
+       int idx, rc = 0;
+       struct ata_ering_entry *ent;
+
+       idx = ering->cursor;
+       do {
+               ent = &ering->ring[idx];
+               if (!ent->err_mask)
+                       break;
+               rc = map_fn(ent, arg);
+               if (rc)
+                       break;
+               idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
+       } while (idx != ering->cursor);
+
+       return rc;
+}
+
+static unsigned int ata_eh_dev_action(struct ata_device *dev)
+{
+       struct ata_eh_context *ehc = &dev->ap->eh_context;
+
+       return ehc->i.action | ehc->i.dev_action[dev->devno];
+}
+
+static void ata_eh_clear_action(struct ata_device *dev,
+                               struct ata_eh_info *ehi, unsigned int action)
+{
+       int i;
+
+       if (!dev) {
+               ehi->action &= ~action;
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       ehi->dev_action[i] &= ~action;
+       } else {
+               /* doesn't make sense for port-wide EH actions */
+               WARN_ON(!(action & ATA_EH_PERDEV_MASK));
+
+               /* break ehi->action into ehi->dev_action */
+               if (ehi->action & action) {
+                       for (i = 0; i < ATA_MAX_DEVICES; i++)
+                               ehi->dev_action[i] |= ehi->action & action;
+                       ehi->action &= ~action;
+               }
+
+               /* turn off the specified per-dev action */
+               ehi->dev_action[dev->devno] &= ~action;
+       }
+}
+
+/**
+ *     ata_scsi_timed_out - SCSI layer time out callback
+ *     @cmd: timed out SCSI command
+ *
+ *     Handles SCSI layer timeout.  We race with normal completion of
+ *     the qc for @cmd.  If the qc is already gone, we lose and let
+ *     the scsi command finish (EH_HANDLED).  Otherwise, the qc has
+ *     timed out and EH should be invoked.  Prevent ata_qc_complete()
+ *     from finishing it by setting EH_SCHEDULED and return
+ *     EH_NOT_HANDLED.
+ *
+ *     TODO: kill this function once old EH is gone.
+ *
+ *     LOCKING:
+ *     Called from timer context
+ *
+ *     RETURNS:
+ *     EH_HANDLED or EH_NOT_HANDLED
+ */
+enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct ata_port *ap = ata_shost_to_port(host);
+       unsigned long flags;
+       struct ata_queued_cmd *qc;
+       enum scsi_eh_timer_return ret;
+
+       DPRINTK("ENTER\n");
+
+       if (ap->ops->error_handler) {
+               ret = EH_NOT_HANDLED;
+               goto out;
+       }
+
+       ret = EH_HANDLED;
+       spin_lock_irqsave(ap->lock, flags);
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       if (qc) {
+               WARN_ON(qc->scsicmd != cmd);
+               qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               ret = EH_NOT_HANDLED;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+
+ out:
+       DPRINTK("EXIT, ret=%d\n", ret);
+       return ret;
+}
+
+/**
+ *     ata_scsi_error - SCSI layer error handler callback
+ *     @host: SCSI host on which error occurred
+ *
+ *     Handles SCSI-layer-thrown error events.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+void ata_scsi_error(struct Scsi_Host *host)
+{
+       struct ata_port *ap = ata_shost_to_port(host);
+       int i, repeat_cnt = ATA_EH_MAX_REPEAT;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       /* synchronize with port task */
+       ata_port_flush_task(ap);
+
+       /* synchronize with host_set lock and sort out timeouts */
+
+       /* For new EH, all qcs are finished in one of three ways -
+        * normal completion, error completion, and SCSI timeout.
+        * Both cmpletions can race against SCSI timeout.  When normal
+        * completion wins, the qc never reaches EH.  When error
+        * completion wins, the qc has ATA_QCFLAG_FAILED set.
+        *
+        * When SCSI timeout wins, things are a bit more complex.
+        * Normal or error completion can occur after the timeout but
+        * before this point.  In such cases, both types of
+        * completions are honored.  A scmd is determined to have
+        * timed out iff its associated qc is active and not failed.
+        */
+       if (ap->ops->error_handler) {
+               struct scsi_cmnd *scmd, *tmp;
+               int nr_timedout = 0;
+
+               spin_lock_irqsave(ap->lock, flags);
+
+               list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
+                       struct ata_queued_cmd *qc;
+
+                       for (i = 0; i < ATA_MAX_QUEUE; i++) {
+                               qc = __ata_qc_from_tag(ap, i);
+                               if (qc->flags & ATA_QCFLAG_ACTIVE &&
+                                   qc->scsicmd == scmd)
+                                       break;
+                       }
+
+                       if (i < ATA_MAX_QUEUE) {
+                               /* the scmd has an associated qc */
+                               if (!(qc->flags & ATA_QCFLAG_FAILED)) {
+                                       /* which hasn't failed yet, timeout */
+                                       qc->err_mask |= AC_ERR_TIMEOUT;
+                                       qc->flags |= ATA_QCFLAG_FAILED;
+                                       nr_timedout++;
+                               }
+                       } else {
+                               /* Normal completion occurred after
+                                * SCSI timeout but before this point.
+                                * Successfully complete it.
+                                */
+                               scmd->retries = scmd->allowed;
+                               scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+                       }
+               }
+
+               /* If we have timed out qcs.  They belong to EH from
+                * this point but the state of the controller is
+                * unknown.  Freeze the port to make sure the IRQ
+                * handler doesn't diddle with those qcs.  This must
+                * be done atomically w.r.t. setting QCFLAG_FAILED.
+                */
+               if (nr_timedout)
+                       __ata_port_freeze(ap);
+
+               spin_unlock_irqrestore(ap->lock, flags);
+       } else
+               spin_unlock_wait(ap->lock);
+
+ repeat:
+       /* invoke error handler */
+       if (ap->ops->error_handler) {
+               /* process port resume request */
+               ata_eh_handle_port_resume(ap);
+
+               /* fetch & clear EH info */
+               spin_lock_irqsave(ap->lock, flags);
+
+               memset(&ap->eh_context, 0, sizeof(ap->eh_context));
+               ap->eh_context.i = ap->eh_info;
+               memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+
+               ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
+               ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+
+               spin_unlock_irqrestore(ap->lock, flags);
+
+               /* invoke EH, skip if unloading or suspended */
+               if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
+                       ap->ops->error_handler(ap);
+               else
+                       ata_eh_finish(ap);
+
+               /* process port suspend request */
+               ata_eh_handle_port_suspend(ap);
+
+               /* Exception might have happend after ->error_handler
+                * recovered the port but before this point.  Repeat
+                * EH in such case.
+                */
+               spin_lock_irqsave(ap->lock, flags);
+
+               if (ap->pflags & ATA_PFLAG_EH_PENDING) {
+                       if (--repeat_cnt) {
+                               ata_port_printk(ap, KERN_INFO,
+                                       "EH pending after completion, "
+                                       "repeating EH (cnt=%d)\n", repeat_cnt);
+                               spin_unlock_irqrestore(ap->lock, flags);
+                               goto repeat;
+                       }
+                       ata_port_printk(ap, KERN_ERR, "EH pending after %d "
+                                       "tries, giving up\n", ATA_EH_MAX_REPEAT);
+               }
+
+               /* this run is complete, make sure EH info is clear */
+               memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+
+               /* Clear host_eh_scheduled while holding ap->lock such
+                * that if exception occurs after this point but
+                * before EH completion, SCSI midlayer will
+                * re-initiate EH.
+                */
+               host->host_eh_scheduled = 0;
+
+               spin_unlock_irqrestore(ap->lock, flags);
+       } else {
+               WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+               ap->ops->eng_timeout(ap);
+       }
+
+       /* finish or retry handled scmd's and clean up */
+       WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
+
+       scsi_eh_flush_done_q(&ap->eh_done_q);
+
+       /* clean up */
+       spin_lock_irqsave(ap->lock, flags);
+
+       if (ap->pflags & ATA_PFLAG_LOADING)
+               ap->pflags &= ~ATA_PFLAG_LOADING;
+       else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
+               queue_work(ata_aux_wq, &ap->hotplug_task);
+
+       if (ap->pflags & ATA_PFLAG_RECOVERED)
+               ata_port_printk(ap, KERN_INFO, "EH complete\n");
+
+       ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
+
+       /* tell wait_eh that we're done */
+       ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS;
+       wake_up_all(&ap->eh_wait_q);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_port_wait_eh - Wait for the currently pending EH to complete
+ *     @ap: Port to wait EH for
+ *
+ *     Wait until the currently pending EH is complete.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_port_wait_eh(struct ata_port *ap)
+{
+       unsigned long flags;
+       DEFINE_WAIT(wait);
+
+ retry:
+       spin_lock_irqsave(ap->lock, flags);
+
+       while (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) {
+               prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
+               spin_unlock_irqrestore(ap->lock, flags);
+               schedule();
+               spin_lock_irqsave(ap->lock, flags);
+       }
+       finish_wait(&ap->eh_wait_q, &wait);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       /* make sure SCSI EH is complete */
+       if (scsi_host_in_recovery(ap->host)) {
+               msleep(10);
+               goto retry;
+       }
+}
+
+/**
+ *     ata_qc_timeout - Handle timeout of queued command
+ *     @qc: Command that timed out
+ *
+ *     Some part of the kernel (currently, only the SCSI layer)
+ *     has noticed that the active command on port @ap has not
+ *     completed after a specified length of time.  Handle this
+ *     condition by disabling DMA (if necessary) and completing
+ *     transactions, with error if necessary.
+ *
+ *     This also handles the case of the "lost interrupt", where
+ *     for some reason (possibly hardware bug, possibly driver bug)
+ *     an interrupt was not delivered to the driver, even though the
+ *     transaction completed successfully.
+ *
+ *     TODO: kill this function once old EH is gone.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ */
+static void ata_qc_timeout(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       u8 host_stat = 0, drv_stat;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       ap->hsm_task_state = HSM_ST_IDLE;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       switch (qc->tf.protocol) {
+
+       case ATA_PROT_DMA:
+       case ATA_PROT_ATAPI_DMA:
+               host_stat = ap->ops->bmdma_status(ap);
+
+               /* before we do anything else, clear DMA-Start bit */
+               ap->ops->bmdma_stop(qc);
+
+               /* fall through */
+
+       default:
+               ata_altstatus(ap);
+               drv_stat = ata_chk_status(ap);
+
+               /* ack bmdma irq events */
+               ap->ops->irq_clear(ap);
+
+               ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
+                              "stat 0x%x host_stat 0x%x\n",
+                              qc->tf.command, drv_stat, host_stat);
+
+               /* complete taskfile transaction */
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               break;
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       ata_eh_qc_complete(qc);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eng_timeout - Handle timeout of queued command
+ *     @ap: Port on which timed-out command is active
+ *
+ *     Some part of the kernel (currently, only the SCSI layer)
+ *     has noticed that the active command on port @ap has not
+ *     completed after a specified length of time.  Handle this
+ *     condition by disabling DMA (if necessary) and completing
+ *     transactions, with error if necessary.
+ *
+ *     This also handles the case of the "lost interrupt", where
+ *     for some reason (possibly hardware bug, possibly driver bug)
+ *     an interrupt was not delivered to the driver, even though the
+ *     transaction completed successfully.
+ *
+ *     TODO: kill this function once old EH is gone.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ */
+void ata_eng_timeout(struct ata_port *ap)
+{
+       DPRINTK("ENTER\n");
+
+       ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_qc_schedule_eh - schedule qc for error handling
+ *     @qc: command to schedule error handling for
+ *
+ *     Schedule error handling for @qc.  EH will kick in as soon as
+ *     other commands are drained.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       WARN_ON(!ap->ops->error_handler);
+
+       qc->flags |= ATA_QCFLAG_FAILED;
+       qc->ap->pflags |= ATA_PFLAG_EH_PENDING;
+
+       /* The following will fail if timeout has already expired.
+        * ata_scsi_error() takes care of such scmds on EH entry.
+        * Note that ATA_QCFLAG_FAILED is unconditionally set after
+        * this function completes.
+        */
+       scsi_req_abort_cmd(qc->scsicmd);
+}
+
+/**
+ *     ata_port_schedule_eh - schedule error handling without a qc
+ *     @ap: ATA port to schedule EH for
+ *
+ *     Schedule error handling for @ap.  EH will kick in as soon as
+ *     all commands are drained.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+void ata_port_schedule_eh(struct ata_port *ap)
+{
+       WARN_ON(!ap->ops->error_handler);
+
+       ap->pflags |= ATA_PFLAG_EH_PENDING;
+       scsi_schedule_eh(ap->host);
+
+       DPRINTK("port EH scheduled\n");
+}
+
+/**
+ *     ata_port_abort - abort all qc's on the port
+ *     @ap: ATA port to abort qc's for
+ *
+ *     Abort all active qc's of @ap and schedule EH.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Number of aborted qc's.
+ */
+int ata_port_abort(struct ata_port *ap)
+{
+       int tag, nr_aborted = 0;
+
+       WARN_ON(!ap->ops->error_handler);
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
+
+               if (qc) {
+                       qc->flags |= ATA_QCFLAG_FAILED;
+                       ata_qc_complete(qc);
+                       nr_aborted++;
+               }
+       }
+
+       if (!nr_aborted)
+               ata_port_schedule_eh(ap);
+
+       return nr_aborted;
+}
+
+/**
+ *     __ata_port_freeze - freeze port
+ *     @ap: ATA port to freeze
+ *
+ *     This function is called when HSM violation or some other
+ *     condition disrupts normal operation of the port.  Frozen port
+ *     is not allowed to perform any operation until the port is
+ *     thawed, which usually follows a successful reset.
+ *
+ *     ap->ops->freeze() callback can be used for freezing the port
+ *     hardware-wise (e.g. mask interrupt and stop DMA engine).  If a
+ *     port cannot be frozen hardware-wise, the interrupt handler
+ *     must ack and clear interrupts unconditionally while the port
+ *     is frozen.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+static void __ata_port_freeze(struct ata_port *ap)
+{
+       WARN_ON(!ap->ops->error_handler);
+
+       if (ap->ops->freeze)
+               ap->ops->freeze(ap);
+
+       ap->pflags |= ATA_PFLAG_FROZEN;
+
+       DPRINTK("ata%u port frozen\n", ap->id);
+}
+
+/**
+ *     ata_port_freeze - abort & freeze port
+ *     @ap: ATA port to freeze
+ *
+ *     Abort and freeze @ap.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Number of aborted commands.
+ */
+int ata_port_freeze(struct ata_port *ap)
+{
+       int nr_aborted;
+
+       WARN_ON(!ap->ops->error_handler);
+
+       nr_aborted = ata_port_abort(ap);
+       __ata_port_freeze(ap);
+
+       return nr_aborted;
+}
+
+/**
+ *     ata_eh_freeze_port - EH helper to freeze port
+ *     @ap: ATA port to freeze
+ *
+ *     Freeze @ap.
+ *
+ *     LOCKING:
+ *     None.
+ */
+void ata_eh_freeze_port(struct ata_port *ap)
+{
+       unsigned long flags;
+
+       if (!ap->ops->error_handler)
+               return;
+
+       spin_lock_irqsave(ap->lock, flags);
+       __ata_port_freeze(ap);
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_port_thaw_port - EH helper to thaw port
+ *     @ap: ATA port to thaw
+ *
+ *     Thaw frozen port @ap.
+ *
+ *     LOCKING:
+ *     None.
+ */
+void ata_eh_thaw_port(struct ata_port *ap)
+{
+       unsigned long flags;
+
+       if (!ap->ops->error_handler)
+               return;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       ap->pflags &= ~ATA_PFLAG_FROZEN;
+
+       if (ap->ops->thaw)
+               ap->ops->thaw(ap);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       DPRINTK("ata%u port thawed\n", ap->id);
+}
+
+static void ata_eh_scsidone(struct scsi_cmnd *scmd)
+{
+       /* nada */
+}
+
+static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       unsigned long flags;
+
+       spin_lock_irqsave(ap->lock, flags);
+       qc->scsidone = ata_eh_scsidone;
+       __ata_qc_complete(qc);
+       WARN_ON(ata_tag_valid(qc->tag));
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+}
+
+/**
+ *     ata_eh_qc_complete - Complete an active ATA command from EH
+ *     @qc: Command to complete
+ *
+ *     Indicate to the mid and upper layers that an ATA command has
+ *     completed.  To be used from EH.
+ */
+void ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       scmd->retries = scmd->allowed;
+       __ata_eh_qc_complete(qc);
+}
+
+/**
+ *     ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
+ *     @qc: Command to retry
+ *
+ *     Indicate to the mid and upper layers that an ATA command
+ *     should be retried.  To be used from EH.
+ *
+ *     SCSI midlayer limits the number of retries to scmd->allowed.
+ *     scmd->retries is decremented for commands which get retried
+ *     due to unrelated failures (qc->err_mask is zero).
+ */
+void ata_eh_qc_retry(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       if (!qc->err_mask && scmd->retries)
+               scmd->retries--;
+       __ata_eh_qc_complete(qc);
+}
+
+/**
+ *     ata_eh_detach_dev - detach ATA device
+ *     @dev: ATA device to detach
+ *
+ *     Detach @dev.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_detach_dev(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->ap;
+       unsigned long flags;
+
+       ata_dev_disable(dev);
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       dev->flags &= ~ATA_DFLAG_DETACH;
+
+       if (ata_scsi_offline_dev(dev)) {
+               dev->flags |= ATA_DFLAG_DETACHED;
+               ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+       }
+
+       /* clear per-dev EH actions */
+       ata_eh_clear_action(dev, &ap->eh_info, ATA_EH_PERDEV_MASK);
+       ata_eh_clear_action(dev, &ap->eh_context.i, ATA_EH_PERDEV_MASK);
+
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_eh_about_to_do - about to perform eh_action
+ *     @ap: target ATA port
+ *     @dev: target ATA dev for per-dev action (can be NULL)
+ *     @action: action about to be performed
+ *
+ *     Called just before performing EH actions to clear related bits
+ *     in @ap->eh_info such that eh actions are not unnecessarily
+ *     repeated.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
+                              unsigned int action)
+{
+       unsigned long flags;
+       struct ata_eh_info *ehi = &ap->eh_info;
+       struct ata_eh_context *ehc = &ap->eh_context;
+
+       spin_lock_irqsave(ap->lock, flags);
+
+       /* Reset is represented by combination of actions and EHI
+        * flags.  Suck in all related bits before clearing eh_info to
+        * avoid losing requested action.
+        */
+       if (action & ATA_EH_RESET_MASK) {
+               ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+               ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
+
+               /* make sure all reset actions are cleared & clear EHI flags */
+               action |= ATA_EH_RESET_MASK;
+               ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+       }
+
+       ata_eh_clear_action(dev, ehi, action);
+
+       if (!(ehc->i.flags & ATA_EHI_QUIET))
+               ap->pflags |= ATA_PFLAG_RECOVERED;
+
+       spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *     ata_eh_done - EH action complete
+ *     @ap: target ATA port
+ *     @dev: target ATA dev for per-dev action (can be NULL)
+ *     @action: action just completed
+ *
+ *     Called right after performing EH actions to clear related bits
+ *     in @ap->eh_context.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
+                       unsigned int action)
+{
+       /* if reset is complete, clear all reset actions & reset modifier */
+       if (action & ATA_EH_RESET_MASK) {
+               action |= ATA_EH_RESET_MASK;
+               ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+       }
+
+       ata_eh_clear_action(dev, &ap->eh_context.i, action);
+}
+
+/**
+ *     ata_err_string - convert err_mask to descriptive string
+ *     @err_mask: error mask to convert to string
+ *
+ *     Convert @err_mask to descriptive string.  Errors are
+ *     prioritized according to severity and only the most severe
+ *     error is reported.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Descriptive string for @err_mask
+ */
+static const char * ata_err_string(unsigned int err_mask)
+{
+       if (err_mask & AC_ERR_HOST_BUS)
+               return "host bus error";
+       if (err_mask & AC_ERR_ATA_BUS)
+               return "ATA bus error";
+       if (err_mask & AC_ERR_TIMEOUT)
+               return "timeout";
+       if (err_mask & AC_ERR_HSM)
+               return "HSM violation";
+       if (err_mask & AC_ERR_SYSTEM)
+               return "internal error";
+       if (err_mask & AC_ERR_MEDIA)
+               return "media error";
+       if (err_mask & AC_ERR_INVALID)
+               return "invalid argument";
+       if (err_mask & AC_ERR_DEV)
+               return "device error";
+       return "unknown error";
+}
+
+/**
+ *     ata_read_log_page - read a specific log page
+ *     @dev: target device
+ *     @page: page to read
+ *     @buf: buffer to store read page
+ *     @sectors: number of sectors to read
+ *
+ *     Read log page using READ_LOG_EXT command.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_read_log_page(struct ata_device *dev,
+                                     u8 page, void *buf, unsigned int sectors)
+{
+       struct ata_taskfile tf;
+       unsigned int err_mask;
+
+       DPRINTK("read log page - page %d\n", page);
+
+       ata_tf_init(dev, &tf);
+       tf.command = ATA_CMD_READ_LOG_EXT;
+       tf.lbal = page;
+       tf.nsect = sectors;
+       tf.hob_nsect = sectors >> 8;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_PIO;
+
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+                                    buf, sectors * ATA_SECT_SIZE);
+
+       DPRINTK("EXIT, err_mask=%x\n", err_mask);
+       return err_mask;
+}
+
+/**
+ *     ata_eh_read_log_10h - Read log page 10h for NCQ error details
+ *     @dev: Device to read log page 10h from
+ *     @tag: Resulting tag of the failed command
+ *     @tf: Resulting taskfile registers of the failed command
+ *
+ *     Read log page 10h to obtain NCQ error details and clear error
+ *     condition.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+static int ata_eh_read_log_10h(struct ata_device *dev,
+                              int *tag, struct ata_taskfile *tf)
+{
+       u8 *buf = dev->ap->sector_buf;
+       unsigned int err_mask;
+       u8 csum;
+       int i;
+
+       err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
+       if (err_mask)
+               return -EIO;
+
+       csum = 0;
+       for (i = 0; i < ATA_SECT_SIZE; i++)
+               csum += buf[i];
+       if (csum)
+               ata_dev_printk(dev, KERN_WARNING,
+                              "invalid checksum 0x%x on log page 10h\n", csum);
+
+       if (buf[0] & 0x80)
+               return -ENOENT;
+
+       *tag = buf[0] & 0x1f;
+
+       tf->command = buf[2];
+       tf->feature = buf[3];
+       tf->lbal = buf[4];
+       tf->lbam = buf[5];
+       tf->lbah = buf[6];
+       tf->device = buf[7];
+       tf->hob_lbal = buf[8];
+       tf->hob_lbam = buf[9];
+       tf->hob_lbah = buf[10];
+       tf->nsect = buf[12];
+       tf->hob_nsect = buf[13];
+
+       return 0;
+}
+
+/**
+ *     atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
+ *     @dev: device to perform REQUEST_SENSE to
+ *     @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
+ *
+ *     Perform ATAPI REQUEST_SENSE after the device reported CHECK
+ *     SENSE.  This function is EH helper.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask on failure
+ */
+static unsigned int atapi_eh_request_sense(struct ata_device *dev,
+                                          unsigned char *sense_buf)
+{
+       struct ata_port *ap = dev->ap;
+       struct ata_taskfile tf;
+       u8 cdb[ATAPI_CDB_LEN];
+
+       DPRINTK("ATAPI request sense\n");
+
+       ata_tf_init(dev, &tf);
+
+       /* FIXME: is this needed? */
+       memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
+
+       /* XXX: why tf_read here? */
+       ap->ops->tf_read(ap, &tf);
+
+       /* fill these in, for the case where they are -not- overwritten */
+       sense_buf[0] = 0x70;
+       sense_buf[2] = tf.feature >> 4;
+
+       memset(cdb, 0, ATAPI_CDB_LEN);
+       cdb[0] = REQUEST_SENSE;
+       cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.command = ATA_CMD_PACKET;
+
+       /* is it pointless to prefer PIO for "safety reasons"? */
+       if (ap->flags & ATA_FLAG_PIO_DMA) {
+               tf.protocol = ATA_PROT_ATAPI_DMA;
+               tf.feature |= ATAPI_PKT_DMA;
+       } else {
+               tf.protocol = ATA_PROT_ATAPI;
+               tf.lbam = (8 * 1024) & 0xff;
+               tf.lbah = (8 * 1024) >> 8;
+       }
+
+       return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
+                                sense_buf, SCSI_SENSE_BUFFERSIZE);
+}
+
+/**
+ *     ata_eh_analyze_serror - analyze SError for a failed port
+ *     @ap: ATA port to analyze SError for
+ *
+ *     Analyze SError if available and further determine cause of
+ *     failure.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_analyze_serror(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       u32 serror = ehc->i.serror;
+       unsigned int err_mask = 0, action = 0;
+
+       if (serror & SERR_PERSISTENT) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_HARDRESET;
+       }
+       if (serror &
+           (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_SOFTRESET;
+       }
+       if (serror & SERR_PROTOCOL) {
+               err_mask |= AC_ERR_HSM;
+               action |= ATA_EH_SOFTRESET;
+       }
+       if (serror & SERR_INTERNAL) {
+               err_mask |= AC_ERR_SYSTEM;
+               action |= ATA_EH_SOFTRESET;
+       }
+       if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG))
+               ata_ehi_hotplugged(&ehc->i);
+
+       ehc->i.err_mask |= err_mask;
+       ehc->i.action |= action;
+}
+
+/**
+ *     ata_eh_analyze_ncq_error - analyze NCQ error
+ *     @ap: ATA port to analyze NCQ error for
+ *
+ *     Read log page 10h, determine the offending qc and acquire
+ *     error status TF.  For NCQ device errors, all LLDDs have to do
+ *     is setting AC_ERR_DEV in ehi->err_mask.  This function takes
+ *     care of the rest.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_analyze_ncq_error(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev = ap->device;
+       struct ata_queued_cmd *qc;
+       struct ata_taskfile tf;
+       int tag, rc;
+
+       /* if frozen, we can't do much */
+       if (ap->pflags & ATA_PFLAG_FROZEN)
+               return;
+
+       /* is it NCQ device error? */
+       if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
+               return;
+
+       /* has LLDD analyzed already? */
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               if (qc->err_mask)
+                       return;
+       }
+
+       /* okay, this error is ours */
+       rc = ata_eh_read_log_10h(dev, &tag, &tf);
+       if (rc) {
+               ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
+                               "(errno=%d)\n", rc);
+               return;
+       }
+
+       if (!(ap->sactive & (1 << tag))) {
+               ata_port_printk(ap, KERN_ERR, "log page 10h reported "
+                               "inactive tag %d\n", tag);
+               return;
+       }
+
+       /* we've got the perpetrator, condemn it */
+       qc = __ata_qc_from_tag(ap, tag);
+       memcpy(&qc->result_tf, &tf, sizeof(tf));
+       qc->err_mask |= AC_ERR_DEV;
+       ehc->i.err_mask &= ~AC_ERR_DEV;
+}
+
+/**
+ *     ata_eh_analyze_tf - analyze taskfile of a failed qc
+ *     @qc: qc to analyze
+ *     @tf: Taskfile registers to analyze
+ *
+ *     Analyze taskfile of @qc and further determine cause of
+ *     failure.  This function also requests ATAPI sense data if
+ *     avaliable.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     Determined recovery action
+ */
+static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+                                     const struct ata_taskfile *tf)
+{
+       unsigned int tmp, action = 0;
+       u8 stat = tf->command, err = tf->feature;
+
+       if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
+               qc->err_mask |= AC_ERR_HSM;
+               return ATA_EH_SOFTRESET;
+       }
+
+       if (!(qc->err_mask & AC_ERR_DEV))
+               return 0;
+
+       switch (qc->dev->class) {
+       case ATA_DEV_ATA:
+               if (err & ATA_ICRC)
+                       qc->err_mask |= AC_ERR_ATA_BUS;
+               if (err & ATA_UNC)
+                       qc->err_mask |= AC_ERR_MEDIA;
+               if (err & ATA_IDNF)
+                       qc->err_mask |= AC_ERR_INVALID;
+               break;
+
+       case ATA_DEV_ATAPI:
+               tmp = atapi_eh_request_sense(qc->dev,
+                                            qc->scsicmd->sense_buffer);
+               if (!tmp) {
+                       /* ATA_QCFLAG_SENSE_VALID is used to tell
+                        * atapi_qc_complete() that sense data is
+                        * already valid.
+                        *
+                        * TODO: interpret sense data and set
+                        * appropriate err_mask.
+                        */
+                       qc->flags |= ATA_QCFLAG_SENSE_VALID;
+               } else
+                       qc->err_mask |= tmp;
+       }
+
+       if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
+               action |= ATA_EH_SOFTRESET;
+
+       return action;
+}
+
+static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
+{
+       if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
+               return 1;
+
+       if (ent->is_io) {
+               if (ent->err_mask & AC_ERR_HSM)
+                       return 1;
+               if ((ent->err_mask &
+                    (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
+                       return 2;
+       }
+
+       return 0;
+}
+
+struct speed_down_needed_arg {
+       u64 since;
+       int nr_errors[3];
+};
+
+static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+       struct speed_down_needed_arg *arg = void_arg;
+
+       if (ent->timestamp < arg->since)
+               return -1;
+
+       arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
+       return 0;
+}
+
+/**
+ *     ata_eh_speed_down_needed - Determine wheter speed down is necessary
+ *     @dev: Device of interest
+ *
+ *     This function examines error ring of @dev and determines
+ *     whether speed down is necessary.  Speed down is necessary if
+ *     there have been more than 3 of Cat-1 errors or 10 of Cat-2
+ *     errors during last 15 minutes.
+ *
+ *     Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
+ *     violation for known supported commands.
+ *
+ *     Cat-2 errors are unclassified DEV error for known supported
+ *     command.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     1 if speed down is necessary, 0 otherwise
+ */
+static int ata_eh_speed_down_needed(struct ata_device *dev)
+{
+       const u64 interval = 15LLU * 60 * HZ;
+       static const int err_limits[3] = { -1, 3, 10 };
+       struct speed_down_needed_arg arg;
+       struct ata_ering_entry *ent;
+       int err_cat;
+       u64 j64;
+
+       ent = ata_ering_top(&dev->ering);
+       if (!ent)
+               return 0;
+
+       err_cat = ata_eh_categorize_ering_entry(ent);
+       if (err_cat == 0)
+               return 0;
+
+       memset(&arg, 0, sizeof(arg));
+
+       j64 = get_jiffies_64();
+       if (j64 >= interval)
+               arg.since = j64 - interval;
+       else
+               arg.since = 0;
+
+       ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
+
+       return arg.nr_errors[err_cat] > err_limits[err_cat];
+}
+
+/**
+ *     ata_eh_speed_down - record error and speed down if necessary
+ *     @dev: Failed device
+ *     @is_io: Did the device fail during normal IO?
+ *     @err_mask: err_mask of the error
+ *
+ *     Record error and examine error history to determine whether
+ *     adjusting transmission speed is necessary.  It also sets
+ *     transmission limits appropriately if such adjustment is
+ *     necessary.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_eh_speed_down(struct ata_device *dev, int is_io,
+                            unsigned int err_mask)
+{
+       if (!err_mask)
+               return 0;
+
+       /* record error and determine whether speed down is necessary */
+       ata_ering_record(&dev->ering, is_io, err_mask);
+
+       if (!ata_eh_speed_down_needed(dev))
+               return 0;
+
+       /* speed down SATA link speed if possible */
+       if (sata_down_spd_limit(dev->ap) == 0)
+               return ATA_EH_HARDRESET;
+
+       /* lower transfer mode */
+       if (ata_down_xfermask_limit(dev, 0) == 0)
+               return ATA_EH_SOFTRESET;
+
+       ata_dev_printk(dev, KERN_ERR,
+                      "speed down requested but no transfer mode left\n");
+       return 0;
+}
+
+/**
+ *     ata_eh_autopsy - analyze error and determine recovery action
+ *     @ap: ATA port to perform autopsy on
+ *
+ *     Analyze why @ap failed and determine which recovery action is
+ *     needed.  This function also sets more detailed AC_ERR_* values
+ *     and fills sense data for ATAPI CHECK SENSE.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_autopsy(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       unsigned int all_err_mask = 0;
+       int tag, is_io = 0;
+       u32 serror;
+       int rc;
+
+       DPRINTK("ENTER\n");
+
+       if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
+               return;
+
+       /* obtain and analyze SError */
+       rc = sata_scr_read(ap, SCR_ERROR, &serror);
+       if (rc == 0) {
+               ehc->i.serror |= serror;
+               ata_eh_analyze_serror(ap);
+       } else if (rc != -EOPNOTSUPP)
+               ehc->i.action |= ATA_EH_HARDRESET;
+
+       /* analyze NCQ failure */
+       ata_eh_analyze_ncq_error(ap);
+
+       /* any real error trumps AC_ERR_OTHER */
+       if (ehc->i.err_mask & ~AC_ERR_OTHER)
+               ehc->i.err_mask &= ~AC_ERR_OTHER;
+
+       all_err_mask |= ehc->i.err_mask;
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               /* inherit upper level err_mask */
+               qc->err_mask |= ehc->i.err_mask;
+
+               /* analyze TF */
+               ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf);
+
+               /* DEV errors are probably spurious in case of ATA_BUS error */
+               if (qc->err_mask & AC_ERR_ATA_BUS)
+                       qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
+                                         AC_ERR_INVALID);
+
+               /* any real error trumps unknown error */
+               if (qc->err_mask & ~AC_ERR_OTHER)
+                       qc->err_mask &= ~AC_ERR_OTHER;
+
+               /* SENSE_VALID trumps dev/unknown error and revalidation */
+               if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+                       qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
+                       ehc->i.action &= ~ATA_EH_REVALIDATE;
+               }
+
+               /* accumulate error info */
+               ehc->i.dev = qc->dev;
+               all_err_mask |= qc->err_mask;
+               if (qc->flags & ATA_QCFLAG_IO)
+                       is_io = 1;
+       }
+
+       /* enforce default EH actions */
+       if (ap->pflags & ATA_PFLAG_FROZEN ||
+           all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+               ehc->i.action |= ATA_EH_SOFTRESET;
+       else if (all_err_mask)
+               ehc->i.action |= ATA_EH_REVALIDATE;
+
+       /* if we have offending qcs and the associated failed device */
+       if (ehc->i.dev) {
+               /* speed down */
+               ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
+                                                  all_err_mask);
+
+               /* perform per-dev EH action only on the offending device */
+               ehc->i.dev_action[ehc->i.dev->devno] |=
+                       ehc->i.action & ATA_EH_PERDEV_MASK;
+               ehc->i.action &= ~ATA_EH_PERDEV_MASK;
+       }
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eh_report - report error handling to user
+ *     @ap: ATA port EH is going on
+ *
+ *     Report EH to user.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_report(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       const char *frozen, *desc;
+       int tag, nr_failed = 0;
+
+       desc = NULL;
+       if (ehc->i.desc[0] != '\0')
+               desc = ehc->i.desc;
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+               if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
+                       continue;
+
+               nr_failed++;
+       }
+
+       if (!nr_failed && !ehc->i.err_mask)
+               return;
+
+       frozen = "";
+       if (ap->pflags & ATA_PFLAG_FROZEN)
+               frozen = " frozen";
+
+       if (ehc->i.dev) {
+               ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
+                              "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+                              ehc->i.err_mask, ap->sactive, ehc->i.serror,
+                              ehc->i.action, frozen);
+               if (desc)
+                       ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
+       } else {
+               ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
+                               "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+                               ehc->i.err_mask, ap->sactive, ehc->i.serror,
+                               ehc->i.action, frozen);
+               if (desc)
+                       ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
+       }
+
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
+                       continue;
+
+               ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
+                              "Emask 0x%x stat 0x%x err 0x%x (%s)\n",
+                              qc->tag, qc->tf.command, qc->err_mask,
+                              qc->result_tf.command, qc->result_tf.feature,
+                              ata_err_string(qc->err_mask));
+       }
+}
+
+static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
+                       unsigned int *classes)
+{
+       int i, rc;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               classes[i] = ATA_DEV_UNKNOWN;
+
+       rc = reset(ap, classes);
+       if (rc)
+               return rc;
+
+       /* If any class isn't ATA_DEV_UNKNOWN, consider classification
+        * is complete and convert all ATA_DEV_UNKNOWN to
+        * ATA_DEV_NONE.
+        */
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (classes[i] != ATA_DEV_UNKNOWN)
+                       break;
+
+       if (i < ATA_MAX_DEVICES)
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       if (classes[i] == ATA_DEV_UNKNOWN)
+                               classes[i] = ATA_DEV_NONE;
+
+       return 0;
+}
+
+static int ata_eh_followup_srst_needed(int rc, int classify,
+                                      const unsigned int *classes)
+{
+       if (rc == -EAGAIN)
+               return 1;
+       if (rc != 0)
+               return 0;
+       if (classify && classes[0] == ATA_DEV_UNKNOWN)
+               return 1;
+       return 0;
+}
+
+static int ata_eh_reset(struct ata_port *ap, int classify,
+                       ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+                       ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       unsigned int *classes = ehc->classes;
+       int tries = ATA_EH_RESET_TRIES;
+       int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
+       unsigned int action;
+       ata_reset_fn_t reset;
+       int i, did_followup_srst, rc;
+
+       /* about to reset */
+       ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+
+       /* Determine which reset to use and record in ehc->i.action.
+        * prereset() may examine and modify it.
+        */
+       action = ehc->i.action;
+       ehc->i.action &= ~ATA_EH_RESET_MASK;
+       if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
+                                        !(action & ATA_EH_HARDRESET))))
+               ehc->i.action |= ATA_EH_SOFTRESET;
+       else
+               ehc->i.action |= ATA_EH_HARDRESET;
+
+       if (prereset) {
+               rc = prereset(ap);
+               if (rc) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "prereset failed (errno=%d)\n", rc);
+                       return rc;
+               }
+       }
+
+       /* prereset() might have modified ehc->i.action */
+       if (ehc->i.action & ATA_EH_HARDRESET)
+               reset = hardreset;
+       else if (ehc->i.action & ATA_EH_SOFTRESET)
+               reset = softreset;
+       else {
+               /* prereset told us not to reset, bang classes and return */
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       classes[i] = ATA_DEV_NONE;
+               return 0;
+       }
+
+       /* did prereset() screw up?  if so, fix up to avoid oopsing */
+       if (!reset) {
+               ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
+                               "invalid reset type\n");
+               if (softreset)
+                       reset = softreset;
+               else
+                       reset = hardreset;
+       }
+
+ retry:
+       /* shut up during boot probing */
+       if (verbose)
+               ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
+                               reset == softreset ? "soft" : "hard");
+
+       /* mark that this EH session started with reset */
+       ehc->i.flags |= ATA_EHI_DID_RESET;
+
+       rc = ata_do_reset(ap, reset, classes);
+
+       did_followup_srst = 0;
+       if (reset == hardreset &&
+           ata_eh_followup_srst_needed(rc, classify, classes)) {
+               /* okay, let's do follow-up softreset */
+               did_followup_srst = 1;
+               reset = softreset;
+
+               if (!reset) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "follow-up softreset required "
+                                       "but no softreset avaliable\n");
+                       return -EINVAL;
+               }
+
+               ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
+               rc = ata_do_reset(ap, reset, classes);
+
+               if (rc == 0 && classify &&
+                   classes[0] == ATA_DEV_UNKNOWN) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "classification failed\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (rc && --tries) {
+               const char *type;
+
+               if (reset == softreset) {
+                       if (did_followup_srst)
+                               type = "follow-up soft";
+                       else
+                               type = "soft";
+               } else
+                       type = "hard";
+
+               ata_port_printk(ap, KERN_WARNING,
+                               "%sreset failed, retrying in 5 secs\n", type);
+               ssleep(5);
+
+               if (reset == hardreset)
+                       sata_down_spd_limit(ap);
+               if (hardreset)
+                       reset = hardreset;
+               goto retry;
+       }
+
+       if (rc == 0) {
+               /* After the reset, the device state is PIO 0 and the
+                * controller state is undefined.  Record the mode.
+                */
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       ap->device[i].pio_mode = XFER_PIO_0;
+
+               if (postreset)
+                       postreset(ap, classes);
+
+               /* reset successful, schedule revalidation */
+               ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+               ehc->i.action |= ATA_EH_REVALIDATE;
+       }
+
+       return rc;
+}
+
+static int ata_eh_revalidate_and_attach(struct ata_port *ap,
+                                       struct ata_device **r_failed_dev)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev;
+       unsigned long flags;
+       int i, rc = 0;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int action;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
+                       if (ata_port_offline(ap)) {
+                               rc = -EIO;
+                               break;
+                       }
+
+                       ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
+                       rc = ata_dev_revalidate(dev,
+                                       ehc->i.flags & ATA_EHI_DID_RESET);
+                       if (rc)
+                               break;
+
+                       ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
+
+                       /* schedule the scsi_rescan_device() here */
+                       queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
+               } else if (dev->class == ATA_DEV_UNKNOWN &&
+                          ehc->tries[dev->devno] &&
+                          ata_class_enabled(ehc->classes[dev->devno])) {
+                       dev->class = ehc->classes[dev->devno];
+
+                       rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+                       if (rc == 0)
+                               rc = ata_dev_configure(dev, 1);
+
+                       if (rc) {
+                               dev->class = ATA_DEV_UNKNOWN;
+                               break;
+                       }
+
+                       spin_lock_irqsave(ap->lock, flags);
+                       ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+                       spin_unlock_irqrestore(ap->lock, flags);
+               }
+       }
+
+       if (rc)
+               *r_failed_dev = dev;
+
+       DPRINTK("EXIT\n");
+       return rc;
+}
+
+/**
+ *     ata_eh_suspend - handle suspend EH action
+ *     @ap: target host port
+ *     @r_failed_dev: result parameter to indicate failing device
+ *
+ *     Handle suspend EH action.  Disk devices are spinned down and
+ *     other types of devices are just marked suspended.  Once
+ *     suspended, no EH action to the device is allowed until it is
+ *     resumed.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       struct ata_device *dev;
+       int i, rc = 0;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned long flags;
+               unsigned int action, err_mask;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND))
+                       continue;
+
+               WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED);
+
+               ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND);
+
+               if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
+                       /* flush cache */
+                       rc = ata_flush_cache(dev);
+                       if (rc)
+                               break;
+
+                       /* spin down */
+                       err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
+                       if (err_mask) {
+                               ata_dev_printk(dev, KERN_ERR, "failed to "
+                                              "spin down (err_mask=0x%x)\n",
+                                              err_mask);
+                               rc = -EIO;
+                               break;
+                       }
+               }
+
+               spin_lock_irqsave(ap->lock, flags);
+               dev->flags |= ATA_DFLAG_SUSPENDED;
+               spin_unlock_irqrestore(ap->lock, flags);
+
+               ata_eh_done(ap, dev, ATA_EH_SUSPEND);
+       }
+
+       if (rc)
+               *r_failed_dev = dev;
+
+       DPRINTK("EXIT\n");
+       return 0;
+}
+
+/**
+ *     ata_eh_prep_resume - prep for resume EH action
+ *     @ap: target host port
+ *
+ *     Clear SUSPENDED in preparation for scheduled resume actions.
+ *     This allows other parts of EH to access the devices being
+ *     resumed.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_prep_resume(struct ata_port *ap)
+{
+       struct ata_device *dev;
+       unsigned long flags;
+       int i;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int action;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
+                       continue;
+
+               spin_lock_irqsave(ap->lock, flags);
+               dev->flags &= ~ATA_DFLAG_SUSPENDED;
+               spin_unlock_irqrestore(ap->lock, flags);
+       }
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eh_resume - handle resume EH action
+ *     @ap: target host port
+ *     @r_failed_dev: result parameter to indicate failing device
+ *
+ *     Handle resume EH action.  Target devices are already reset and
+ *     revalidated.  Spinning up is the only operation left.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
+ */
+static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+       struct ata_device *dev;
+       int i, rc = 0;
+
+       DPRINTK("ENTER\n");
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               unsigned int action, err_mask;
+
+               dev = &ap->device[i];
+               action = ata_eh_dev_action(dev);
+
+               if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
+                       continue;
+
+               ata_eh_about_to_do(ap, dev, ATA_EH_RESUME);
+
+               if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
+                       err_mask = ata_do_simple_cmd(dev,
+                                                    ATA_CMD_IDLEIMMEDIATE);
+                       if (err_mask) {
+                               ata_dev_printk(dev, KERN_ERR, "failed to "
+                                              "spin up (err_mask=0x%x)\n",
+                                              err_mask);
+                               rc = -EIO;
+                               break;
+                       }
+               }
+
+               ata_eh_done(ap, dev, ATA_EH_RESUME);
+       }
+
+       if (rc)
+               *r_failed_dev = dev;
+
+       DPRINTK("EXIT\n");
+       return 0;
+}
+
+static int ata_port_nr_enabled(struct ata_port *ap)
+{
+       int i, cnt = 0;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (ata_dev_enabled(&ap->device[i]))
+                       cnt++;
+       return cnt;
+}
+
+static int ata_port_nr_vacant(struct ata_port *ap)
+{
+       int i, cnt = 0;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (ap->device[i].class == ATA_DEV_UNKNOWN)
+                       cnt++;
+       return cnt;
+}
+
+static int ata_eh_skip_recovery(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       int i;
+
+       /* skip if all possible devices are suspended */
+       for (i = 0; i < ata_port_max_devices(ap); i++) {
+               struct ata_device *dev = &ap->device[i];
+
+               if (!(dev->flags & ATA_DFLAG_SUSPENDED))
+                       break;
+       }
+
+       if (i == ata_port_max_devices(ap))
+               return 1;
+
+       /* thaw frozen port, resume link and recover failed devices */
+       if ((ap->pflags & ATA_PFLAG_FROZEN) ||
+           (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap))
+               return 0;
+
+       /* skip if class codes for all vacant slots are ATA_DEV_NONE */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               struct ata_device *dev = &ap->device[i];
+
+               if (dev->class == ATA_DEV_UNKNOWN &&
+                   ehc->classes[dev->devno] != ATA_DEV_NONE)
+                       return 0;
+       }
+
+       return 1;
+}
+
+/**
+ *     ata_eh_recover - recover host port after error
+ *     @ap: host port to recover
+ *     @prereset: prereset method (can be NULL)
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *
+ *     This is the alpha and omega, eum and yang, heart and soul of
+ *     libata exception handling.  On entry, actions required to
+ *     recover the port and hotplug requests are recorded in
+ *     eh_context.  This function executes all the operations with
+ *     appropriate retrials and fallbacks to resurrect failed
+ *     devices, detach goners and greet newcomers.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+                         ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+                         ata_postreset_fn_t postreset)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev;
+       int down_xfermask, i, rc;
+
+       DPRINTK("ENTER\n");
+
+       /* prep for recovery */
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+
+               /* process hotplug request */
+               if (dev->flags & ATA_DFLAG_DETACH)
+                       ata_eh_detach_dev(dev);
+
+               if (!ata_dev_enabled(dev) &&
+                   ((ehc->i.probe_mask & (1 << dev->devno)) &&
+                    !(ehc->did_probe_mask & (1 << dev->devno)))) {
+                       ata_eh_detach_dev(dev);
+                       ata_dev_init(dev);
+                       ehc->did_probe_mask |= (1 << dev->devno);
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+               }
+       }
+
+ retry:
+       down_xfermask = 0;
+       rc = 0;
+
+       /* if UNLOADING, finish immediately */
+       if (ap->pflags & ATA_PFLAG_UNLOADING)
+               goto out;
+
+       /* prep for resume */
+       ata_eh_prep_resume(ap);
+
+       /* skip EH if possible. */
+       if (ata_eh_skip_recovery(ap))
+               ehc->i.action = 0;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               ehc->classes[i] = ATA_DEV_UNKNOWN;
+
+       /* reset */
+       if (ehc->i.action & ATA_EH_RESET_MASK) {
+               ata_eh_freeze_port(ap);
+
+               rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset,
+                                 softreset, hardreset, postreset);
+               if (rc) {
+                       ata_port_printk(ap, KERN_ERR,
+                                       "reset failed, giving up\n");
+                       goto out;
+               }
+
+               ata_eh_thaw_port(ap);
+       }
+
+       /* revalidate existing devices and attach new ones */
+       rc = ata_eh_revalidate_and_attach(ap, &dev);
+       if (rc)
+               goto dev_fail;
+
+       /* resume devices */
+       rc = ata_eh_resume(ap, &dev);
+       if (rc)
+               goto dev_fail;
+
+       /* configure transfer mode if the port has been reset */
+       if (ehc->i.flags & ATA_EHI_DID_RESET) {
+               rc = ata_set_mode(ap, &dev);
+               if (rc) {
+                       down_xfermask = 1;
+                       goto dev_fail;
+               }
+       }
+
+       /* suspend devices */
+       rc = ata_eh_suspend(ap, &dev);
+       if (rc)
+               goto dev_fail;
+
+       goto out;
+
+ dev_fail:
+       switch (rc) {
+       case -ENODEV:
+               /* device missing, schedule probing */
+               ehc->i.probe_mask |= (1 << dev->devno);
+       case -EINVAL:
+               ehc->tries[dev->devno] = 0;
+               break;
+       case -EIO:
+               sata_down_spd_limit(ap);
+       default:
+               ehc->tries[dev->devno]--;
+               if (down_xfermask &&
+                   ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
+                       ehc->tries[dev->devno] = 0;
+       }
+
+       if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+               /* disable device if it has used up all its chances */
+               ata_dev_disable(dev);
+
+               /* detach if offline */
+               if (ata_port_offline(ap))
+                       ata_eh_detach_dev(dev);
+
+               /* probe if requested */
+               if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+                   !(ehc->did_probe_mask & (1 << dev->devno))) {
+                       ata_eh_detach_dev(dev);
+                       ata_dev_init(dev);
+
+                       ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+                       ehc->did_probe_mask |= (1 << dev->devno);
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+               }
+       } else {
+               /* soft didn't work?  be haaaaard */
+               if (ehc->i.flags & ATA_EHI_DID_RESET)
+                       ehc->i.action |= ATA_EH_HARDRESET;
+               else
+                       ehc->i.action |= ATA_EH_SOFTRESET;
+       }
+
+       if (ata_port_nr_enabled(ap)) {
+               ata_port_printk(ap, KERN_WARNING, "failed to recover some "
+                               "devices, retrying in 5 secs\n");
+               ssleep(5);
+       } else {
+               /* no device left, repeat fast */
+               msleep(500);
+       }
+
+       goto retry;
+
+ out:
+       if (rc) {
+               for (i = 0; i < ATA_MAX_DEVICES; i++)
+                       ata_dev_disable(&ap->device[i]);
+       }
+
+       DPRINTK("EXIT, rc=%d\n", rc);
+       return rc;
+}
+
+/**
+ *     ata_eh_finish - finish up EH
+ *     @ap: host port to finish EH for
+ *
+ *     Recovery is complete.  Clean up EH states and retry or finish
+ *     failed qcs.
+ *
+ *     LOCKING:
+ *     None.
+ */
+static void ata_eh_finish(struct ata_port *ap)
+{
+       int tag;
+
+       /* retry or finish qcs */
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               if (qc->err_mask) {
+                       /* FIXME: Once EH migration is complete,
+                        * generate sense data in this function,
+                        * considering both err_mask and tf.
+                        */
+                       if (qc->err_mask & AC_ERR_INVALID)
+                               ata_eh_qc_complete(qc);
+                       else
+                               ata_eh_qc_retry(qc);
+               } else {
+                       if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+                               ata_eh_qc_complete(qc);
+                       } else {
+                               /* feed zero TF to sense generation */
+                               memset(&qc->result_tf, 0, sizeof(qc->result_tf));
+                               ata_eh_qc_retry(qc);
+                       }
+               }
+       }
+}
+
+/**
+ *     ata_do_eh - do standard error handling
+ *     @ap: host port to handle error for
+ *     @prereset: prereset method (can be NULL)
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *
+ *     Perform standard error handling sequence.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+              ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+              ata_postreset_fn_t postreset)
+{
+       ata_eh_autopsy(ap);
+       ata_eh_report(ap);
+       ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
+       ata_eh_finish(ap);
+}
+
+/**
+ *     ata_eh_handle_port_suspend - perform port suspend operation
+ *     @ap: port to suspend
+ *
+ *     Suspend @ap.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_handle_port_suspend(struct ata_port *ap)
+{
+       unsigned long flags;
+       int rc = 0;
+
+       /* are we suspending? */
+       spin_lock_irqsave(ap->lock, flags);
+       if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
+           ap->pm_mesg.event == PM_EVENT_ON) {
+               spin_unlock_irqrestore(ap->lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
+
+       /* suspend */
+       ata_eh_freeze_port(ap);
+
+       if (ap->ops->port_suspend)
+               rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+
+       /* report result */
+       spin_lock_irqsave(ap->lock, flags);
+
+       ap->pflags &= ~ATA_PFLAG_PM_PENDING;
+       if (rc == 0)
+               ap->pflags |= ATA_PFLAG_SUSPENDED;
+       else
+               ata_port_schedule_eh(ap);
+
+       if (ap->pm_result) {
+               *ap->pm_result = rc;
+               ap->pm_result = NULL;
+       }
+
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       return;
+}
+
+/**
+ *     ata_eh_handle_port_resume - perform port resume operation
+ *     @ap: port to resume
+ *
+ *     Resume @ap.
+ *
+ *     This function also waits upto one second until all devices
+ *     hanging off this port requests resume EH action.  This is to
+ *     prevent invoking EH and thus reset multiple times on resume.
+ *
+ *     On DPM resume, where some of devices might not be resumed
+ *     together, this may delay port resume upto one second, but such
+ *     DPM resumes are rare and 1 sec delay isn't too bad.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_handle_port_resume(struct ata_port *ap)
+{
+       unsigned long timeout;
+       unsigned long flags;
+       int i, rc = 0;
+
+       /* are we resuming? */
+       spin_lock_irqsave(ap->lock, flags);
+       if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
+           ap->pm_mesg.event != PM_EVENT_ON) {
+               spin_unlock_irqrestore(ap->lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       /* spurious? */
+       if (!(ap->pflags & ATA_PFLAG_SUSPENDED))
+               goto done;
+
+       if (ap->ops->port_resume)
+               rc = ap->ops->port_resume(ap);
+
+       /* give devices time to request EH */
+       timeout = jiffies + HZ; /* 1s max */
+       while (1) {
+               for (i = 0; i < ATA_MAX_DEVICES; i++) {
+                       struct ata_device *dev = &ap->device[i];
+                       unsigned int action = ata_eh_dev_action(dev);
+
+                       if ((dev->flags & ATA_DFLAG_SUSPENDED) &&
+                           !(action & ATA_EH_RESUME))
+                               break;
+               }
+
+               if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout))
+                       break;
+               msleep(10);
+       }
+
+ done:
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
+       if (ap->pm_result) {
+               *ap->pm_result = rc;
+               ap->pm_result = NULL;
+       }
+       spin_unlock_irqrestore(ap->lock, flags);
+}
diff --git a/drivers/scsi/scsi_transport_api.h b/drivers/scsi/scsi_transport_api.h
new file mode 100644 (file)
index 0000000..934f0e6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _SCSI_TRANSPORT_API_H
+#define _SCSI_TRANSPORT_API_H
+
+void scsi_schedule_eh(struct Scsi_Host *shost);
+
+#endif /* _SCSI_TRANSPORT_API_H */
diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c
new file mode 100644 (file)
index 0000000..7502109
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+ * drivers/serial/netx-serial.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+
+/* We've been assigned a range on the "Low-density serial ports" major */
+#define SERIAL_NX_MAJOR        204
+#define MINOR_START    170
+
+#ifdef CONFIG_SERIAL_NETX_CONSOLE
+
+enum uart_regs {
+       UART_DR              = 0x00,
+       UART_SR              = 0x04,
+       UART_LINE_CR         = 0x08,
+       UART_BAUDDIV_MSB     = 0x0c,
+       UART_BAUDDIV_LSB     = 0x10,
+       UART_CR              = 0x14,
+       UART_FR              = 0x18,
+       UART_IIR             = 0x1c,
+       UART_ILPR            = 0x20,
+       UART_RTS_CR          = 0x24,
+       UART_RTS_LEAD        = 0x28,
+       UART_RTS_TRAIL       = 0x2c,
+       UART_DRV_ENABLE      = 0x30,
+       UART_BRM_CR          = 0x34,
+       UART_RXFIFO_IRQLEVEL = 0x38,
+       UART_TXFIFO_IRQLEVEL = 0x3c,
+};
+
+#define SR_FE (1<<0)
+#define SR_PE (1<<1)
+#define SR_BE (1<<2)
+#define SR_OE (1<<3)
+
+#define LINE_CR_BRK       (1<<0)
+#define LINE_CR_PEN       (1<<1)
+#define LINE_CR_EPS       (1<<2)
+#define LINE_CR_STP2      (1<<3)
+#define LINE_CR_FEN       (1<<4)
+#define LINE_CR_5BIT      (0<<5)
+#define LINE_CR_6BIT      (1<<5)
+#define LINE_CR_7BIT      (2<<5)
+#define LINE_CR_8BIT      (3<<5)
+#define LINE_CR_BITS_MASK (3<<5)
+
+#define CR_UART_EN (1<<0)
+#define CR_SIREN   (1<<1)
+#define CR_SIRLP   (1<<2)
+#define CR_MSIE    (1<<3)
+#define CR_RIE     (1<<4)
+#define CR_TIE     (1<<5)
+#define CR_RTIE    (1<<6)
+#define CR_LBE     (1<<7)
+
+#define FR_CTS  (1<<0)
+#define FR_DSR  (1<<1)
+#define FR_DCD  (1<<2)
+#define FR_BUSY (1<<3)
+#define FR_RXFE (1<<4)
+#define FR_TXFF (1<<5)
+#define FR_RXFF (1<<6)
+#define FR_TXFE (1<<7)
+
+#define IIR_MIS (1<<0)
+#define IIR_RIS (1<<1)
+#define IIR_TIS (1<<2)
+#define IIR_RTIS (1<<3)
+#define IIR_MASK 0xf
+
+#define RTS_CR_AUTO (1<<0)
+#define RTS_CR_RTS  (1<<1)
+#define RTS_CR_COUNT (1<<2)
+#define RTS_CR_MOD2  (1<<3)
+#define RTS_CR_RTS_POL (1<<4)
+#define RTS_CR_CTS_CTR (1<<5)
+#define RTS_CR_CTS_POL (1<<6)
+#define RTS_CR_STICK   (1<<7)
+
+#define UART_PORT_SIZE 0x40
+#define DRIVER_NAME "netx-uart"
+
+struct netx_port {
+       struct uart_port        port;
+};
+
+static void netx_stop_tx(struct uart_port *port)
+{
+       unsigned int val;
+       val = readl(port->membase + UART_CR);
+       writel(val & ~CR_TIE,  port->membase + UART_CR);
+}
+
+static void netx_stop_rx(struct uart_port *port)
+{
+       unsigned int val;
+       val = readl(port->membase + UART_CR);
+       writel(val & ~CR_RIE,  port->membase + UART_CR);
+}
+
+static void netx_enable_ms(struct uart_port *port)
+{
+       unsigned int val;
+       val = readl(port->membase + UART_CR);
+       writel(val | CR_MSIE, port->membase + UART_CR);
+}
+
+static inline void netx_transmit_buffer(struct uart_port *port)
+{
+       struct circ_buf *xmit = &port->info->xmit;
+
+       if (port->x_char) {
+               writel(port->x_char, port->membase + UART_DR);
+               port->icount.tx++;
+               port->x_char = 0;
+               return;
+       }
+
+       if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
+               netx_stop_tx(port);
+               return;
+       }
+
+       do {
+               /* send xmit->buf[xmit->tail]
+                * out the port here */
+               writel(xmit->buf[xmit->tail], port->membase + UART_DR);
+               xmit->tail = (xmit->tail + 1) &
+                        (UART_XMIT_SIZE - 1);
+               port->icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+       } while (!(readl(port->membase + UART_FR) & FR_TXFF));
+
+       if (uart_circ_empty(xmit))
+               netx_stop_tx(port);
+}
+
+static void netx_start_tx(struct uart_port *port)
+{
+       writel(
+           readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR);
+
+       if (!(readl(port->membase + UART_FR) & FR_TXFF))
+               netx_transmit_buffer(port);
+}
+
+static unsigned int netx_tx_empty(struct uart_port *port)
+{
+       return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT;
+}
+
+static void netx_txint(struct uart_port *port)
+{
+       struct circ_buf *xmit = &port->info->xmit;
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+               netx_stop_tx(port);
+               return;
+       }
+
+       netx_transmit_buffer(port);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+}
+
+static void netx_rxint(struct uart_port *port, struct pt_regs *regs)
+{
+       unsigned char rx, flg, status;
+       struct tty_struct *tty = port->info->tty;
+
+       while (!(readl(port->membase + UART_FR) & FR_RXFE)) {
+               rx = readl(port->membase + UART_DR);
+               flg = TTY_NORMAL;
+               port->icount.rx++;
+               status = readl(port->membase + UART_SR);
+               if (status & SR_BE) {
+                       writel(0, port->membase + UART_SR);
+                       if (uart_handle_break(port))
+                               continue;
+               }
+
+               if (unlikely(status & (SR_FE | SR_PE | SR_OE))) {
+
+                       if (status & SR_PE)
+                               port->icount.parity++;
+                       else if (status & SR_FE)
+                               port->icount.frame++;
+                       if (status & SR_OE)
+                               port->icount.overrun++;
+
+                       status &= port->read_status_mask;
+
+                       if (status & SR_BE)
+                               flg = TTY_BREAK;
+                       else if (status & SR_PE)
+                               flg = TTY_PARITY;
+                       else if (status & SR_FE)
+                               flg = TTY_FRAME;
+               }
+
+               if (uart_handle_sysrq_char(port, rx, regs))
+                       continue;
+
+               uart_insert_char(port, status, SR_OE, rx, flg);
+       }
+
+       tty_flip_buffer_push(tty);
+       return;
+}
+
+static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct uart_port *port = (struct uart_port *)dev_id;
+       unsigned long flags;
+       unsigned char status;
+
+       spin_lock_irqsave(&port->lock,flags);
+
+       status = readl(port->membase + UART_IIR) & IIR_MASK;
+       while (status) {
+               if (status & IIR_RIS)
+                       netx_rxint(port, regs);
+               if (status & IIR_TIS)
+                       netx_txint(port);
+               if (status & IIR_MIS) {
+                       if (readl(port->membase + UART_FR) & FR_CTS)
+                               uart_handle_cts_change(port, 1);
+                       else
+                               uart_handle_cts_change(port, 0);
+               }
+               writel(0, port->membase + UART_IIR);
+               status = readl(port->membase + UART_IIR) & IIR_MASK;
+       }
+
+       spin_unlock_irqrestore(&port->lock,flags);
+       return IRQ_HANDLED;
+}
+
+static unsigned int netx_get_mctrl(struct uart_port *port)
+{
+       unsigned int ret = TIOCM_DSR | TIOCM_CAR;
+
+       if (readl(port->membase + UART_FR) & FR_CTS)
+               ret |= TIOCM_CTS;
+
+       return ret;
+}
+
+static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       unsigned int val;
+
+       if (mctrl & TIOCM_RTS) {
+               val = readl(port->membase + UART_RTS_CR);
+               writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
+       }
+}
+
+static void netx_break_ctl(struct uart_port *port, int break_state)
+{
+       unsigned int line_cr;
+       spin_lock_irq(&port->lock);
+
+       line_cr = readl(port->membase + UART_LINE_CR);
+       if (break_state != 0)
+               line_cr |= LINE_CR_BRK;
+       else
+               line_cr &= ~LINE_CR_BRK;
+       writel(line_cr, port->membase + UART_LINE_CR);
+
+       spin_unlock_irq(&port->lock);
+}
+
+static int netx_startup(struct uart_port *port)
+{
+       int ret;
+
+       ret = request_irq(port->irq, netx_int, 0,
+                            DRIVER_NAME, port);
+       if (ret) {
+               dev_err(port->dev, "unable to grab irq%d\n",port->irq);
+               goto exit;
+       }
+
+       writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN,
+               port->membase + UART_LINE_CR);
+
+       writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN,
+               port->membase + UART_CR);
+
+exit:
+       return ret;
+}
+
+static void netx_shutdown(struct uart_port *port)
+{
+       writel(0, port->membase + UART_CR) ;
+
+       free_irq(port->irq, port);
+}
+
+static void
+netx_set_termios(struct uart_port *port, struct termios *termios,
+                  struct termios *old)
+{
+       unsigned int baud, quot;
+       unsigned char old_cr;
+       unsigned char line_cr = LINE_CR_FEN;
+       unsigned char rts_cr = 0;
+
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               line_cr |= LINE_CR_5BIT;
+               break;
+       case CS6:
+               line_cr |= LINE_CR_6BIT;
+               break;
+       case CS7:
+               line_cr |= LINE_CR_7BIT;
+               break;
+       case CS8:
+               line_cr |= LINE_CR_8BIT;
+               break;
+       }
+
+       if (termios->c_cflag & CSTOPB)
+               line_cr |= LINE_CR_STP2;
+
+       if (termios->c_cflag & PARENB) {
+               line_cr |= LINE_CR_PEN;
+               if (!(termios->c_cflag & PARODD))
+                       line_cr |= LINE_CR_EPS;
+       }
+
+       if (termios->c_cflag & CRTSCTS)
+               rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL;
+
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+       quot = baud * 4096;
+       quot /= 1000;
+       quot *= 256;
+       quot /= 100000;
+
+       spin_lock_irq(&port->lock);
+
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       old_cr = readl(port->membase + UART_CR);
+
+       /* disable interrupts */
+       writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE),
+               port->membase + UART_CR);
+
+       /* drain transmitter */
+       while (readl(port->membase + UART_FR) & FR_BUSY);
+
+       /* disable UART */
+       writel(old_cr & ~CR_UART_EN, port->membase + UART_CR);
+
+       /* modem status interrupts */
+       old_cr &= ~CR_MSIE;
+       if (UART_ENABLE_MS(port, termios->c_cflag))
+               old_cr |= CR_MSIE;
+
+       writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB);
+       writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB);
+       writel(line_cr, port->membase + UART_LINE_CR);
+
+       writel(rts_cr, port->membase + UART_RTS_CR);
+
+       /*
+        * Characters to ignore
+        */
+       port->ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               port->ignore_status_mask |= SR_PE;
+       if (termios->c_iflag & IGNBRK) {
+               port->ignore_status_mask |= SR_BE;
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       port->ignore_status_mask |= SR_PE;
+       }
+
+       port->read_status_mask = 0;
+       if (termios->c_iflag & (BRKINT | PARMRK))
+               port->read_status_mask |= SR_BE;
+       if (termios->c_iflag & INPCK)
+               port->read_status_mask |= SR_PE | SR_FE;
+
+       writel(old_cr, port->membase + UART_CR);
+
+       spin_unlock_irq(&port->lock);
+}
+
+static const char *netx_type(struct uart_port *port)
+{
+       return port->type == PORT_NETX ? "NETX" : NULL;
+}
+
+static void netx_release_port(struct uart_port *port)
+{
+       release_mem_region(port->mapbase, UART_PORT_SIZE);
+}
+
+static int netx_request_port(struct uart_port *port)
+{
+       return request_mem_region(port->mapbase, UART_PORT_SIZE,
+                       DRIVER_NAME) != NULL ? 0 : -EBUSY;
+}
+
+static void netx_config_port(struct uart_port *port, int flags)
+{
+       if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0)
+               port->type = PORT_NETX;
+}
+
+static int
+netx_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       int ret = 0;
+
+       if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX)
+               ret = -EINVAL;
+
+       return ret;
+}
+
+static struct uart_ops netx_pops = {
+       .tx_empty       = netx_tx_empty,
+       .set_mctrl      = netx_set_mctrl,
+       .get_mctrl      = netx_get_mctrl,
+       .stop_tx        = netx_stop_tx,
+       .start_tx       = netx_start_tx,
+       .stop_rx        = netx_stop_rx,
+       .enable_ms      = netx_enable_ms,
+       .break_ctl      = netx_break_ctl,
+       .startup        = netx_startup,
+       .shutdown       = netx_shutdown,
+       .set_termios    = netx_set_termios,
+       .type           = netx_type,
+       .release_port   = netx_release_port,
+       .request_port   = netx_request_port,
+       .config_port    = netx_config_port,
+       .verify_port    = netx_verify_port,
+};
+
+static struct netx_port netx_ports[] = {
+       {
+       .port = {
+               .type = PORT_NETX,
+               .iotype = UPIO_MEM,
+               .membase = (char __iomem *)io_p2v(NETX_PA_UART0),
+               .mapbase = NETX_PA_UART0,
+               .irq = NETX_IRQ_UART0,
+               .uartclk = 100000000,
+               .fifosize = 16,
+               .flags = UPF_BOOT_AUTOCONF,
+               .ops = &netx_pops,
+               .line = 0,
+       },
+       }, {
+       .port = {
+               .type = PORT_NETX,
+               .iotype = UPIO_MEM,
+               .membase = (char __iomem *)io_p2v(NETX_PA_UART1),
+               .mapbase = NETX_PA_UART1,
+               .irq = NETX_IRQ_UART1,
+               .uartclk = 100000000,
+               .fifosize = 16,
+               .flags = UPF_BOOT_AUTOCONF,
+               .ops = &netx_pops,
+               .line = 1,
+       },
+       }, {
+       .port = {
+               .type = PORT_NETX,
+               .iotype = UPIO_MEM,
+               .membase = (char __iomem *)io_p2v(NETX_PA_UART2),
+               .mapbase = NETX_PA_UART2,
+               .irq = NETX_IRQ_UART2,
+               .uartclk = 100000000,
+               .fifosize = 16,
+               .flags = UPF_BOOT_AUTOCONF,
+               .ops = &netx_pops,
+               .line = 2,
+       },
+       }
+};
+
+static void netx_console_putchar(struct uart_port *port, int ch)
+{
+       while (readl(port->membase + UART_FR) & FR_BUSY);
+       writel(ch, port->membase + UART_DR);
+}
+
+static void
+netx_console_write(struct console *co, const char *s, unsigned int count)
+{
+       struct uart_port *port = &netx_ports[co->index].port;
+       unsigned char cr_save;
+
+       cr_save = readl(port->membase + UART_CR);
+       writel(cr_save | CR_UART_EN, port->membase + UART_CR);
+
+       uart_console_write(port, s, count, netx_console_putchar);
+
+       while (readl(port->membase + UART_FR) & FR_BUSY);
+       writel(cr_save, port->membase + UART_CR);
+}
+
+static void __init
+netx_console_get_options(struct uart_port *port, int *baud,
+                       int *parity, int *bits, int *flow)
+{
+       unsigned char line_cr;
+
+       *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) |
+               readl(port->membase + UART_BAUDDIV_LSB);
+       *baud *= 1000;
+       *baud /= 4096;
+       *baud *= 1000;
+       *baud /= 256;
+       *baud *= 100;
+
+       line_cr = readl(port->membase + UART_LINE_CR);
+       *parity = 'n';
+       if (line_cr & LINE_CR_PEN) {
+               if (line_cr & LINE_CR_EPS)
+                       *parity = 'e';
+               else
+                       *parity = 'o';
+       }
+
+       switch (line_cr & LINE_CR_BITS_MASK) {
+       case LINE_CR_8BIT:
+               *bits = 8;
+               break;
+       case LINE_CR_7BIT:
+               *bits = 7;
+               break;
+       case LINE_CR_6BIT:
+               *bits = 6;
+               break;
+       case LINE_CR_5BIT:
+               *bits = 5;
+               break;
+       }
+
+       if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO)
+               *flow = 'r';
+}
+
+static int __init
+netx_console_setup(struct console *co, char *options)
+{
+       struct netx_port *sport;
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       /*
+        * Check whether an invalid uart number has been specified, and
+        * if so, search for the first available port that does have
+        * console support.
+        */
+       if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports))
+               co->index = 0;
+       sport = &netx_ports[co->index];
+
+       if (options) {
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       } else {
+               /* if the UART is enabled, assume it has been correctly setup
+                * by the bootloader and get the options
+                */
+               if (readl(sport->port.membase + UART_CR) & CR_UART_EN) {
+                       netx_console_get_options(&sport->port, &baud,
+                       &parity, &bits, &flow);
+               }
+
+       }
+
+       return uart_set_options(&sport->port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver netx_reg;
+static struct console netx_console = {
+       .name           = "ttyNX",
+       .write          = netx_console_write,
+       .device         = uart_console_device,
+       .setup          = netx_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &netx_reg,
+};
+
+static int __init netx_console_init(void)
+{
+       register_console(&netx_console);
+       return 0;
+}
+console_initcall(netx_console_init);
+
+#define NETX_CONSOLE   &netx_console
+#else
+#define NETX_CONSOLE   NULL
+#endif
+
+static struct uart_driver netx_reg = {
+       .owner          = THIS_MODULE,
+       .driver_name    = DRIVER_NAME,
+       .dev_name       = "ttyNX",
+       .major          = SERIAL_NX_MAJOR,
+       .minor          = MINOR_START,
+       .nr             = ARRAY_SIZE(netx_ports),
+       .cons           = NETX_CONSOLE,
+};
+
+static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct netx_port *sport = platform_get_drvdata(pdev);
+
+       if (sport)
+               uart_suspend_port(&netx_reg, &sport->port);
+
+       return 0;
+}
+
+static int serial_netx_resume(struct platform_device *pdev)
+{
+       struct netx_port *sport = platform_get_drvdata(pdev);
+
+       if (sport)
+               uart_resume_port(&netx_reg, &sport->port);
+
+       return 0;
+}
+
+static int serial_netx_probe(struct platform_device *pdev)
+{
+       struct uart_port *port = &netx_ports[pdev->id].port;
+
+       dev_info(&pdev->dev, "initialising\n");
+
+       port->dev = &pdev->dev;
+
+       writel(1, port->membase + UART_RXFIFO_IRQLEVEL);
+       uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port);
+       platform_set_drvdata(pdev, &netx_ports[pdev->id]);
+
+       return 0;
+}
+
+static int serial_netx_remove(struct platform_device *pdev)
+{
+       struct netx_port *sport = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       if (sport)
+               uart_remove_one_port(&netx_reg, &sport->port);
+
+       return 0;
+}
+
+static struct platform_driver serial_netx_driver = {
+       .probe          = serial_netx_probe,
+       .remove         = serial_netx_remove,
+
+       .suspend        = serial_netx_suspend,
+       .resume         = serial_netx_resume,
+
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init netx_serial_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "Serial: NetX driver\n");
+
+       ret = uart_register_driver(&netx_reg);
+       if (ret)
+               return ret;
+
+       ret = platform_driver_register(&serial_netx_driver);
+       if (ret != 0)
+               uart_unregister_driver(&netx_reg);
+
+       return 0;
+}
+
+static void __exit netx_serial_exit(void)
+{
+       platform_driver_unregister(&serial_netx_driver);
+       uart_unregister_driver(&netx_reg);
+}
+
+module_init(netx_serial_init);
+module_exit(netx_serial_exit);
+
+MODULE_AUTHOR("Sascha Hauer");
+MODULE_DESCRIPTION("NetX serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
new file mode 100644 (file)
index 0000000..247b5a4
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * drivers/usb/core/endpoint.c
+ *
+ * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman
+ * (C) Copyright 2002,2004 IBM Corp.
+ * (C) Copyright 2006 Novell Inc.
+ *
+ * Endpoint sysfs stuff
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include "usb.h"
+
+/* endpoint stuff */
+
+struct ep_device {
+       struct usb_endpoint_descriptor *desc;
+       struct usb_device *udev;
+       struct device dev;
+};
+#define to_ep_device(_dev) \
+       container_of(_dev, struct ep_device, dev)
+
+struct ep_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct usb_device *,
+                       struct usb_endpoint_descriptor *, char *);
+};
+#define to_ep_attribute(_attr) \
+       container_of(_attr, struct ep_attribute, attr)
+
+#define usb_ep_attr(field, format_string)                      \
+static ssize_t show_ep_##field(struct device *dev,             \
+                              struct device_attribute *attr,   \
+                              char *buf)                       \
+{                                                              \
+       struct ep_device *ep = to_ep_device(dev);               \
+       return sprintf(buf, format_string, ep->desc->field);    \
+}                                                              \
+static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL);
+
+usb_ep_attr(bLength, "%02x\n")
+usb_ep_attr(bEndpointAddress, "%02x\n")
+usb_ep_attr(bmAttributes, "%02x\n")
+usb_ep_attr(bInterval, "%02x\n")
+
+static ssize_t show_ep_wMaxPacketSize(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct ep_device *ep = to_ep_device(dev);
+       return sprintf(buf, "%04x\n",
+                       le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff);
+}
+static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL);
+
+static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct ep_device *ep = to_ep_device(dev);
+       char *type = "unknown";
+
+       switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               type = "Control";
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               type = "Isoc";
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               type = "Bulk";
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               type = "Interrupt";
+               break;
+       }
+       return sprintf(buf, "%s\n", type);
+}
+static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL);
+
+static ssize_t show_ep_interval(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct ep_device *ep = to_ep_device(dev);
+       char unit;
+       unsigned interval = 0;
+       unsigned in;
+
+       in = (ep->desc->bEndpointAddress & USB_DIR_IN);
+
+       switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               if (ep->udev->speed == USB_SPEED_HIGH)  /* uframes per NAK */
+                       interval = ep->desc->bInterval;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               interval = 1 << (ep->desc->bInterval - 1);
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+                       interval = ep->desc->bInterval;
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               if (ep->udev->speed == USB_SPEED_HIGH)
+                       interval = 1 << (ep->desc->bInterval - 1);
+               else
+                       interval = ep->desc->bInterval;
+               break;
+       }
+       interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
+       if (interval % 1000)
+               unit = 'u';
+       else {
+               unit = 'm';
+               interval /= 1000;
+       }
+
+       return sprintf(buf, "%d%cs\n", interval, unit);
+}
+static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL);
+
+static ssize_t show_ep_direction(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct ep_device *ep = to_ep_device(dev);
+       char *direction;
+
+       if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_CONTROL)
+               direction = "both";
+       else if (ep->desc->bEndpointAddress & USB_DIR_IN)
+               direction = "in";
+       else
+               direction = "out";
+       return sprintf(buf, "%s\n", direction);
+}
+static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL);
+
+static struct attribute *ep_dev_attrs[] = {
+       &dev_attr_bLength.attr,
+       &dev_attr_bEndpointAddress.attr,
+       &dev_attr_bmAttributes.attr,
+       &dev_attr_bInterval.attr,
+       &dev_attr_wMaxPacketSize.attr,
+       &dev_attr_interval.attr,
+       &dev_attr_type.attr,
+       &dev_attr_direction.attr,
+       NULL,
+};
+static struct attribute_group ep_dev_attr_grp = {
+       .attrs = ep_dev_attrs,
+};
+
+static struct endpoint_class {
+       struct kref kref;
+       struct class *class;
+} *ep_class;
+
+static int init_endpoint_class(void)
+{
+       int result = 0;
+
+       if (ep_class != NULL) {
+               kref_get(&ep_class->kref);
+               goto exit;
+       }
+
+       ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL);
+       if (!ep_class) {
+               result = -ENOMEM;
+               goto exit;
+       }
+
+       kref_init(&ep_class->kref);
+       ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
+       if (IS_ERR(ep_class->class)) {
+               result = IS_ERR(ep_class->class);
+               kfree(ep_class);
+               ep_class = NULL;
+               goto exit;
+       }
+
+exit:
+       return result;
+}
+
+static void release_endpoint_class(struct kref *kref)
+{
+       /* Ok, we cheat as we know we only have one ep_class */
+       class_destroy(ep_class->class);
+       kfree(ep_class);
+       ep_class = NULL;
+}
+
+static void destroy_endpoint_class(void)
+{
+       if (ep_class)
+               kref_put(&ep_class->kref, release_endpoint_class);
+}
+
+static void ep_device_release(struct device *dev)
+{
+       struct ep_device *ep_dev = to_ep_device(dev);
+
+       dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
+       kfree(ep_dev);
+}
+
+void usb_create_ep_files(struct device *parent,
+                        struct usb_host_endpoint *endpoint,
+                        struct usb_device *udev)
+{
+       char name[8];
+       struct ep_device *ep_dev;
+       int minor;
+       int retval;
+
+       retval = init_endpoint_class();
+       if (retval)
+               goto exit;
+
+       ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
+       if (!ep_dev) {
+               retval = -ENOMEM;
+               goto exit;
+       }
+
+       /* fun calculation to determine the minor of this endpoint */
+       minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1);
+
+       ep_dev->desc = &endpoint->desc;
+       ep_dev->udev = udev;
+       ep_dev->dev.devt = MKDEV(442, minor);   // FIXME fake number...
+       ep_dev->dev.class = ep_class->class;
+       ep_dev->dev.parent = parent;
+       ep_dev->dev.release = ep_device_release;
+       snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x",
+                udev->bus->busnum, udev->devnum,
+                endpoint->desc.bEndpointAddress);
+
+       retval = device_register(&ep_dev->dev);
+       if (retval)
+               goto error;
+       sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+
+       endpoint->ep_dev = ep_dev;
+
+       /* create the symlink to the old-style "ep_XX" directory */
+       sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+       sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name);
+
+exit:
+       return;
+error:
+       kfree(ep_dev);
+       return;
+}
+
+void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+{
+
+       if (endpoint->ep_dev) {
+               char name[8];
+
+               sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+               sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name);
+               sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
+               device_unregister(&endpoint->ep_dev->dev);
+               endpoint->ep_dev = NULL;
+       }
+       destroy_endpoint_class();
+}
+
+
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
new file mode 100644 (file)
index 0000000..6531c4d
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ *
+ * Bus Glue for ep93xx.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ * Based on fragments of previous driver by Russell King et al.
+ *
+ * Modified for LH7A404 from ohci-sa1111.c
+ *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
+ *
+ * Modified for pxa27x from ohci-lh7a404.c
+ *  by Nick Bane <nick@cecomputing.co.uk> 26-8-2004
+ *
+ * Modified for ep93xx from ohci-pxa27x.c
+ *  by Lennert Buytenhek <buytenh@wantstofly.org> 28-2-2006
+ *  Based on an earlier driver by Ray Lehtiniemi
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/signal.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+static struct clk *usb_host_clock;
+
+static void ep93xx_start_hc(struct device *dev)
+{
+       clk_enable(usb_host_clock);
+}
+
+static void ep93xx_stop_hc(struct device *dev)
+{
+       clk_disable(usb_host_clock);
+}
+
+static int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
+                        struct platform_device *pdev)
+{
+       int retval;
+       struct usb_hcd *hcd;
+
+       if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+               pr_debug("resource[1] is not IORESOURCE_IRQ");
+               return -ENOMEM;
+       }
+
+       hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx");
+       if (hcd == NULL)
+               return -ENOMEM;
+
+       hcd->rsrc_start = pdev->resource[0].start;
+       hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+               usb_put_hcd(hcd);
+               retval = -EBUSY;
+               goto err1;
+       }
+
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (hcd->regs == NULL) {
+               pr_debug("ioremap failed");
+               retval = -ENOMEM;
+               goto err2;
+       }
+
+       usb_host_clock = clk_get(&pdev->dev, "usb_host");
+       ep93xx_start_hc(&pdev->dev);
+
+       ohci_hcd_init(hcd_to_ohci(hcd));
+
+       retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+       if (retval == 0)
+               return retval;
+
+       ep93xx_stop_hc(&pdev->dev);
+       iounmap(hcd->regs);
+err2:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+       usb_put_hcd(hcd);
+
+       return retval;
+}
+
+static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,
+                       struct platform_device *pdev)
+{
+       usb_remove_hcd(hcd);
+       ep93xx_stop_hc(&pdev->dev);
+       clk_put(usb_host_clock);
+       iounmap(hcd->regs);
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+}
+
+static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
+
+       if ((ret = ohci_init(ohci)) < 0)
+               return ret;
+
+       if ((ret = ohci_run(ohci)) < 0) {
+               err("can't start %s", hcd->self.bus_name);
+               ohci_stop(hcd);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct hc_driver ohci_ep93xx_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "EP93xx OHCI",
+       .hcd_priv_size          = sizeof(struct ohci_hcd),
+       .irq                    = ohci_irq,
+       .flags                  = HCD_USB11 | HCD_MEMORY,
+       .start                  = ohci_ep93xx_start,
+       .stop                   = ohci_stop,
+       .urb_enqueue            = ohci_urb_enqueue,
+       .urb_dequeue            = ohci_urb_dequeue,
+       .endpoint_disable       = ohci_endpoint_disable,
+       .get_frame_number       = ohci_get_frame,
+       .hub_status_data        = ohci_hub_status_data,
+       .hub_control            = ohci_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend            = ohci_bus_suspend,
+       .bus_resume             = ohci_bus_resume,
+#endif
+       .start_port_reset       = ohci_start_port_reset,
+};
+
+extern int usb_disabled(void);
+
+static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = -ENODEV;
+       if (!usb_disabled())
+               ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev);
+
+       return ret;
+}
+
+static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_hcd_ep93xx_remove(hcd, pdev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct ochi_hcd *ohci = hcd_to_ohci(hcd);
+
+       if (time_before(jiffies, ohci->next_statechange))
+               msleep(5);
+       ohci->next_statechange = jiffies;
+
+       ep93xx_stop_hc(&pdev->dev);
+       hcd->state = HC_STATE_SUSPENDED;
+       pdev->dev.power.power_state = PMSG_SUSPEND;
+
+       return 0;
+}
+
+static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int status;
+
+       if (time_before(jiffies, ohci->next_statechange))
+               msleep(5);
+       ohci->next_statechange = jiffies;
+
+       ep93xx_start_hc(&pdev->dev);
+       pdev->dev.power.power_state = PMSG_ON;
+       usb_hcd_resume_root_hub(hcd);
+
+       return 0;
+}
+#endif
+
+
+static struct platform_driver ohci_hcd_ep93xx_driver = {
+       .probe          = ohci_hcd_ep93xx_drv_probe,
+       .remove         = ohci_hcd_ep93xx_drv_remove,
+#ifdef CONFIG_PM
+       .suspend        = ohci_hcd_ep93xx_drv_suspend,
+       .resume         = ohci_hcd_ep93xx_drv_resume,
+#endif
+       .driver         = {
+               .name   = "ep93xx-ohci",
+       },
+};
+
+static int __init ohci_hcd_ep93xx_init(void)
+{
+       return platform_driver_register(&ohci_hcd_ep93xx_driver);
+}
+
+static void __exit ohci_hcd_ep93xx_cleanup(void)
+{
+       platform_driver_unregister(&ohci_hcd_ep93xx_driver);
+}
+
+module_init(ohci_hcd_ep93xx_init);
+module_exit(ohci_hcd_ep93xx_cleanup);
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
new file mode 100644 (file)
index 0000000..fc6cc14
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Apple Cinema Display driver
+ *
+ * Copyright (C) 2006  Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * Thanks to Caskey L. Dickson for his work with acdctl.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/backlight.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+#define APPLE_VENDOR_ID                0x05AC
+
+#define USB_REQ_GET_REPORT     0x01
+#define USB_REQ_SET_REPORT     0x09
+
+#define ACD_USB_TIMEOUT                250
+
+#define ACD_USB_EDID           0x0302
+#define ACD_USB_BRIGHTNESS     0x0310
+
+#define ACD_BTN_NONE           0
+#define ACD_BTN_BRIGHT_UP      3
+#define ACD_BTN_BRIGHT_DOWN    4
+
+#define ACD_URB_BUFFER_LEN     2
+#define ACD_MSG_BUFFER_LEN     2
+
+#define APPLEDISPLAY_DEVICE(prod)                              \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |             \
+                      USB_DEVICE_ID_MATCH_INT_CLASS |          \
+                      USB_DEVICE_ID_MATCH_INT_PROTOCOL,        \
+       .idVendor = APPLE_VENDOR_ID,                            \
+       .idProduct = (prod),                                    \
+       .bInterfaceClass = USB_CLASS_HID,                       \
+       .bInterfaceProtocol = 0x00
+
+/* table of devices that work with this driver */
+static struct usb_device_id appledisplay_table [] = {
+       { APPLEDISPLAY_DEVICE(0x9218) },
+       { APPLEDISPLAY_DEVICE(0x9219) },
+       { APPLEDISPLAY_DEVICE(0x921d) },
+
+       /* Terminating entry */
+       { }
+};
+MODULE_DEVICE_TABLE(usb, appledisplay_table);
+
+/* Structure to hold all of our device specific stuff */
+struct appledisplay {
+       struct usb_device *udev;        /* usb device */
+       struct urb *urb;                /* usb request block */
+       struct backlight_device *bd;    /* backlight device */
+       char *urbdata;                  /* interrupt URB data buffer */
+       char *msgdata;                  /* control message data buffer */
+
+       struct work_struct work;
+       int button_pressed;
+       spinlock_t lock;
+};
+
+static atomic_t count_displays = ATOMIC_INIT(0);
+static struct workqueue_struct *wq;
+
+static void appledisplay_complete(struct urb *urb, struct pt_regs *regs)
+{
+       struct appledisplay *pdata = urb->context;
+       unsigned long flags;
+       int retval;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -EOVERFLOW:
+               printk(KERN_ERR "appletouch: OVERFLOW with data "
+                       "length %d, actual length is %d\n",
+                       ACD_URB_BUFFER_LEN, pdata->urb->actual_length);
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* This urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d",
+                       __FUNCTION__, urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d",
+                       __FUNCTION__, urb->status);
+               goto exit;
+       }
+
+       spin_lock_irqsave(&pdata->lock, flags);
+
+       switch(pdata->urbdata[1]) {
+       case ACD_BTN_BRIGHT_UP:
+       case ACD_BTN_BRIGHT_DOWN:
+               pdata->button_pressed = 1;
+               queue_work(wq, &pdata->work);
+               break;
+       case ACD_BTN_NONE:
+       default:
+               pdata->button_pressed = 0;
+               break;
+       }
+
+       spin_unlock_irqrestore(&pdata->lock, flags);
+
+exit:
+       retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
+       if (retval) {
+               err("%s - usb_submit_urb failed with result %d",
+                       __FUNCTION__, retval);
+       }
+}
+
+static int appledisplay_bl_update_status(struct backlight_device *bd)
+{
+       struct appledisplay *pdata = class_get_devdata(&bd->class_dev);
+       int retval;
+
+       pdata->msgdata[0] = 0x10;
+       pdata->msgdata[1] = bd->props->brightness;
+
+       retval = usb_control_msg(
+               pdata->udev,
+               usb_sndctrlpipe(pdata->udev, 0),
+               USB_REQ_SET_REPORT,
+               USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               ACD_USB_BRIGHTNESS,
+               0,
+               pdata->msgdata, 2,
+               ACD_USB_TIMEOUT);
+
+       return retval;
+}
+
+static int appledisplay_bl_get_brightness(struct backlight_device *bd)
+{
+       struct appledisplay *pdata = class_get_devdata(&bd->class_dev);
+       int retval;
+
+       retval = usb_control_msg(
+               pdata->udev,
+               usb_rcvctrlpipe(pdata->udev, 0),
+               USB_REQ_GET_REPORT,
+               USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               ACD_USB_BRIGHTNESS,
+               0,
+               pdata->msgdata, 2,
+               ACD_USB_TIMEOUT);
+
+       if (retval < 0)
+               return retval;
+       else
+               return pdata->msgdata[1];
+}
+
+static struct backlight_properties appledisplay_bl_data = {
+       .owner          = THIS_MODULE,
+       .get_brightness = appledisplay_bl_get_brightness,
+       .update_status  = appledisplay_bl_update_status,
+       .max_brightness = 0xFF
+};
+
+static void appledisplay_work(void *private)
+{
+       struct appledisplay *pdata = private;
+       int retval;
+
+       up(&pdata->bd->sem);
+       retval = appledisplay_bl_get_brightness(pdata->bd);
+       if (retval >= 0)
+               pdata->bd->props->brightness = retval;
+       down(&pdata->bd->sem);
+
+       /* Poll again in about 125ms if there's still a button pressed */
+       if (pdata->button_pressed)
+               schedule_delayed_work(&pdata->work, HZ / 8);
+}
+
+static int appledisplay_probe(struct usb_interface *iface,
+       const struct usb_device_id *id)
+{
+       struct appledisplay *pdata;
+       struct usb_device *udev = interface_to_usbdev(iface);
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int int_in_endpointAddr = 0;
+       int i, retval = -ENOMEM, brightness;
+       char bl_name[20];
+
+       /* set up the endpoint information */
+       /* use only the first interrupt-in endpoint */
+       iface_desc = iface->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (!int_in_endpointAddr &&
+                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
+                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+                    USB_ENDPOINT_XFER_INT)) {
+                       /* we found an interrupt in endpoint */
+                       int_in_endpointAddr = endpoint->bEndpointAddress;
+                       break;
+               }
+       }
+       if (!int_in_endpointAddr) {
+               err("Could not find int-in endpoint");
+               return -EIO;
+       }
+
+       /* allocate memory for our device state and initialize it */
+       pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL);
+       if (!pdata) {
+               retval = -ENOMEM;
+               err("Out of memory");
+               goto error;
+       }
+
+       pdata->udev = udev;
+
+       spin_lock_init(&pdata->lock);
+       INIT_WORK(&pdata->work, appledisplay_work, pdata);
+
+       /* Allocate buffer for control messages */
+       pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
+       if (!pdata->msgdata) {
+               retval = -ENOMEM;
+               err("appledisplay: Allocating buffer for control messages "
+                       "failed");
+               goto error;
+       }
+
+       /* Allocate interrupt URB */
+       pdata->urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!pdata->urb) {
+               retval = -ENOMEM;
+               err("appledisplay: Allocating URB failed");
+               goto error;
+       }
+
+       /* Allocate buffer for interrupt data */
+       pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN,
+               GFP_KERNEL, &pdata->urb->transfer_dma);
+       if (!pdata->urbdata) {
+               retval = -ENOMEM;
+               err("appledisplay: Allocating URB buffer failed");
+               goto error;
+       }
+
+       /* Configure interrupt URB */
+       usb_fill_int_urb(pdata->urb, udev,
+               usb_rcvintpipe(udev, int_in_endpointAddr),
+               pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete,
+               pdata, 1);
+       if (usb_submit_urb(pdata->urb, GFP_KERNEL)) {
+               retval = -EIO;
+               err("appledisplay: Submitting URB failed");
+               goto error;
+       }
+
+       /* Register backlight device */
+       snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
+               atomic_inc_return(&count_displays) - 1);
+       pdata->bd = backlight_device_register(bl_name, pdata,
+                                               &appledisplay_bl_data);
+       if (IS_ERR(pdata->bd)) {
+               err("appledisplay: Backlight registration failed");
+               goto error;
+       }
+
+       /* Try to get brightness */
+       up(&pdata->bd->sem);
+       brightness = appledisplay_bl_get_brightness(pdata->bd);
+       down(&pdata->bd->sem);
+
+       if (brightness < 0) {
+               retval = brightness;
+               err("appledisplay: Error while getting initial brightness: %d", retval);
+               goto error;
+       }
+
+       /* Set brightness in backlight device */
+       up(&pdata->bd->sem);
+       pdata->bd->props->brightness = brightness;
+       down(&pdata->bd->sem);
+
+       /* save our data pointer in the interface device */
+       usb_set_intfdata(iface, pdata);
+
+       printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n");
+
+       return 0;
+
+error:
+       if (pdata) {
+               if (pdata->urb) {
+                       usb_kill_urb(pdata->urb);
+                       if (pdata->urbdata)
+                               usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN,
+                                       pdata->urbdata, pdata->urb->transfer_dma);
+                       usb_free_urb(pdata->urb);
+               }
+               if (pdata->bd)
+                       backlight_device_unregister(pdata->bd);
+               kfree(pdata->msgdata);
+       }
+       usb_set_intfdata(iface, NULL);
+       kfree(pdata);
+       return retval;
+}
+
+static void appledisplay_disconnect(struct usb_interface *iface)
+{
+       struct appledisplay *pdata = usb_get_intfdata(iface);
+
+       if (pdata) {
+               usb_kill_urb(pdata->urb);
+               cancel_delayed_work(&pdata->work);
+               backlight_device_unregister(pdata->bd);
+               usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN,
+                       pdata->urbdata, pdata->urb->transfer_dma);
+               usb_free_urb(pdata->urb);
+               kfree(pdata->msgdata);
+               kfree(pdata);
+       }
+
+       printk(KERN_INFO "appledisplay: Apple Cinema Display disconnected\n");
+}
+
+static struct usb_driver appledisplay_driver = {
+       .name           = "appledisplay",
+       .probe          = appledisplay_probe,
+       .disconnect     = appledisplay_disconnect,
+       .id_table       = appledisplay_table,
+};
+
+static int __init appledisplay_init(void)
+{
+       wq = create_singlethread_workqueue("appledisplay");
+       if (!wq) {
+               err("Could not create work queue\n");
+               return -ENOMEM;
+       }
+
+       return usb_register(&appledisplay_driver);
+}
+
+static void __exit appledisplay_exit(void)
+{
+       flush_workqueue(wq);
+       destroy_workqueue(wq);
+       usb_deregister(&appledisplay_driver);
+}
+
+MODULE_AUTHOR("Michael Hanselmann");
+MODULE_DESCRIPTION("Apple Cinema Display driver");
+MODULE_LICENSE("GPL");
+
+module_init(appledisplay_init);
+module_exit(appledisplay_exit);
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
new file mode 100644 (file)
index 0000000..9c46746
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+* cypress_cy7c63.c
+*
+* Copyright (c) 2006 Oliver Bock (o.bock@fh-wolfenbuettel.de)
+*
+*      This driver is based on the Cypress USB Driver by Marcus Maul
+*      (cyport) and the 2.0 version of Greg Kroah-Hartman's
+*      USB Skeleton driver.
+*
+*      This is a generic driver for the Cypress CY7C63xxx family.
+*      For the time being it enables you to read from and write to
+*      the single I/O ports of the device.
+*
+*      Supported vendors:      AK Modul-Bus Computer GmbH
+*                              (Firmware "Port-Chip")
+*
+*      Supported devices:      CY7C63001A-PC
+*                              CY7C63001C-PXC
+*                              CY7C63001C-SXC
+*
+*      Supported functions:    Read/Write Ports
+*
+*
+*      This program is free software; you can redistribute it and/or
+*      modify it under the terms of the GNU General Public License as
+*      published by the Free Software Foundation, version 2.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+
+#define DRIVER_AUTHOR          "Oliver Bock (o.bock@fh-wolfenbuettel.de)"
+#define DRIVER_DESC            "Cypress CY7C63xxx USB driver"
+
+#define CYPRESS_VENDOR_ID      0xa2c
+#define CYPRESS_PRODUCT_ID     0x8
+
+#define CYPRESS_READ_PORT      0x4
+#define CYPRESS_WRITE_PORT     0x5
+
+#define CYPRESS_READ_RAM       0x2
+#define CYPRESS_WRITE_RAM      0x3
+#define CYPRESS_READ_ROM       0x1
+
+#define CYPRESS_READ_PORT_ID0  0
+#define CYPRESS_WRITE_PORT_ID0 0
+#define CYPRESS_READ_PORT_ID1  0x2
+#define CYPRESS_WRITE_PORT_ID1 1
+
+#define CYPRESS_MAX_REQSIZE    8
+
+
+/* table of devices that work with this driver */
+static struct usb_device_id cypress_table [] = {
+       { USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, cypress_table);
+
+/* structure to hold all of our device specific stuff */
+struct cypress {
+       struct usb_device *     udev;
+       unsigned char           port[2];
+};
+
+/* used to send usb control messages to device */
+static int vendor_command(struct cypress *dev, unsigned char request,
+                         unsigned char address, unsigned char data)
+{
+       int retval = 0;
+       unsigned int pipe;
+       unsigned char *iobuf;
+
+       /* allocate some memory for the i/o buffer*/
+       iobuf = kzalloc(CYPRESS_MAX_REQSIZE, GFP_KERNEL);
+       if (!iobuf) {
+               dev_err(&dev->udev->dev, "Out of memory!\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
+
+       /* prepare usb control message and send it upstream */
+       pipe = usb_rcvctrlpipe(dev->udev, 0);
+       retval = usb_control_msg(dev->udev, pipe, request,
+                                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                                address, data, iobuf, CYPRESS_MAX_REQSIZE,
+                                USB_CTRL_GET_TIMEOUT);
+
+       /* store returned data (more READs to be added) */
+       switch (request) {
+               case CYPRESS_READ_PORT:
+                       if (address == CYPRESS_READ_PORT_ID0) {
+                               dev->port[0] = iobuf[1];
+                               dev_dbg(&dev->udev->dev,
+                                       "READ_PORT0 returned: %d\n",
+                                       dev->port[0]);
+                       }
+                       else if (address == CYPRESS_READ_PORT_ID1) {
+                               dev->port[1] = iobuf[1];
+                               dev_dbg(&dev->udev->dev,
+                                       "READ_PORT1 returned: %d\n",
+                                       dev->port[1]);
+                       }
+                       break;
+       }
+
+       kfree(iobuf);
+error:
+       return retval;
+}
+
+/* write port value */
+static ssize_t write_port(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t count,
+                         int port_num, int write_id)
+{
+       int value = -1;
+       int result = 0;
+
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct cypress *cyp = usb_get_intfdata(intf);
+
+       dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", port_num);
+
+       /* validate input data */
+       if (sscanf(buf, "%d", &value) < 1) {
+               result = -EINVAL;
+               goto error;
+       }
+       if (value < 0 || value > 255) {
+               result = -EINVAL;
+               goto error;
+       }
+
+       result = vendor_command(cyp, CYPRESS_WRITE_PORT, write_id,
+                               (unsigned char)value);
+
+       dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
+error:
+       return result < 0 ? result : count;
+}
+
+/* attribute callback handler (write) */
+static ssize_t set_port0_handler(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       return write_port(dev, attr, buf, count, 0, CYPRESS_WRITE_PORT_ID0);
+}
+
+/* attribute callback handler (write) */
+static ssize_t set_port1_handler(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       return write_port(dev, attr, buf, count, 1, CYPRESS_WRITE_PORT_ID1);
+}
+
+/* read port value */
+static ssize_t read_port(struct device *dev, struct device_attribute *attr,
+                        char *buf, int port_num, int read_id)
+{
+       int result = 0;
+
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct cypress *cyp = usb_get_intfdata(intf);
+
+       dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", port_num);
+
+       result = vendor_command(cyp, CYPRESS_READ_PORT, read_id, 0);
+
+       dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
+
+       return sprintf(buf, "%d", cyp->port[port_num]);
+}
+
+/* attribute callback handler (read) */
+static ssize_t get_port0_handler(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0);
+}
+
+/* attribute callback handler (read) */
+static ssize_t get_port1_handler(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1);
+}
+
+static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO,
+                  get_port0_handler, set_port0_handler);
+
+static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO,
+                  get_port1_handler, set_port1_handler);
+
+
+static int cypress_probe(struct usb_interface *interface,
+                        const struct usb_device_id *id)
+{
+       struct cypress *dev = NULL;
+       int retval = -ENOMEM;
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory!\n");
+               goto error;
+       }
+
+       dev->udev = usb_get_dev(interface_to_usbdev(interface));
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       /* create device attribute files */
+       device_create_file(&interface->dev, &dev_attr_port0);
+       device_create_file(&interface->dev, &dev_attr_port1);
+
+       /* let the user know that the device is now attached */
+       dev_info(&interface->dev,
+                "Cypress CY7C63xxx device now attached\n");
+
+       retval = 0;
+error:
+       return retval;
+}
+
+static void cypress_disconnect(struct usb_interface *interface)
+{
+       struct cypress *dev;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       /* remove device attribute files */
+       device_remove_file(&interface->dev, &dev_attr_port0);
+       device_remove_file(&interface->dev, &dev_attr_port1);
+
+       usb_put_dev(dev->udev);
+
+       dev_info(&interface->dev,
+                "Cypress CY7C63xxx device now disconnected\n");
+
+       kfree(dev);
+}
+
+static struct usb_driver cypress_driver = {
+       .name = "cypress_cy7c63",
+       .probe = cypress_probe,
+       .disconnect = cypress_disconnect,
+       .id_table = cypress_table,
+};
+
+static int __init cypress_init(void)
+{
+       int result;
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&cypress_driver);
+       if (result) {
+               err("Function usb_register failed! Error number: %d\n", result);
+       }
+
+       return result;
+}
+
+static void __exit cypress_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&cypress_driver);
+}
+
+module_init(cypress_init);
+module_exit(cypress_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
new file mode 100644 (file)
index 0000000..d29638d
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Sierra Wireless CDMA Wireless Serial USB driver
+ *
+ * Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com>
+ * Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License version
+ *     2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+       { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
+       { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
+       { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
+       { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+       { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
+       { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
+       { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
+       /* Following devices are supported in the airprime.c driver */
+       /* { USB_DEVICE(0x1199, 0x0112) }, */   /* Sierra Wireless AirCard 580 */
+       /* { USB_DEVICE(0x0F3D, 0x0112) }, */   /* AirPrime/Sierra PC 5220 */
+       { }
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver sierra_driver = {
+       .name =         "sierra_wireless",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+};
+
+static struct usb_serial_driver sierra_device = {
+       .driver = {
+       .owner =                THIS_MODULE,
+       .name =                 "Sierra_Wireless",
+       },
+       .id_table =             id_table,
+       .num_interrupt_in =     NUM_DONT_CARE,
+       .num_bulk_in =          NUM_DONT_CARE,
+       .num_bulk_out =         NUM_DONT_CARE,
+       .num_ports =            3,
+};
+
+static int __init sierra_init(void)
+{
+       int retval;
+
+       retval = usb_serial_register(&sierra_device);
+       if (retval)
+               return retval;
+       retval = usb_register(&sierra_driver);
+       if (retval)
+               usb_serial_deregister(&sierra_device);
+       return retval;
+}
+
+static void __exit sierra_exit(void)
+{
+       usb_deregister(&sierra_driver);
+       usb_serial_deregister(&sierra_device);
+}
+
+module_init(sierra_init);
+module_exit(sierra_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
new file mode 100644 (file)
index 0000000..585eb7b
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Backlight code for ATI Radeon based graphic cards
+ *
+ * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
+ * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * This program is free software; you can 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 "radeonfb.h"
+#include <linux/backlight.h>
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#define MAX_RADEON_LEVEL 0xFF
+
+static struct backlight_properties radeon_bl_data;
+
+struct radeon_bl_privdata {
+       struct radeonfb_info *rinfo;
+       uint8_t negative;
+};
+
+static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
+               int level)
+{
+       struct fb_info *info = pdata->rinfo->info;
+       int rlevel;
+
+       mutex_lock(&info->bl_mutex);
+
+       /* Get and convert the value */
+       rlevel = pdata->rinfo->info->bl_curve[level] *
+                FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
+
+       mutex_unlock(&info->bl_mutex);
+
+       if (rlevel < 0)
+               rlevel = 0;
+       else if (rlevel > MAX_RADEON_LEVEL)
+               rlevel = MAX_RADEON_LEVEL;
+
+       if (pdata->negative)
+               rlevel = MAX_RADEON_LEVEL - rlevel;
+
+       return rlevel;
+}
+
+static int radeon_bl_update_status(struct backlight_device *bd)
+{
+       struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev);
+       struct radeonfb_info *rinfo = pdata->rinfo;
+       u32 lvds_gen_cntl, tmpPixclksCntl;
+       int level;
+
+       if (rinfo->mon1_type != MT_LCD)
+               return 0;
+
+       /* We turn off the LCD completely instead of just dimming the
+        * backlight. This provides some greater power saving and the display
+        * is useless without backlight anyway.
+        */
+        if (bd->props->power != FB_BLANK_UNBLANK ||
+           bd->props->fb_blank != FB_BLANK_UNBLANK)
+               level = 0;
+       else
+               level = bd->props->brightness;
+
+       del_timer_sync(&rinfo->lvds_timer);
+       radeon_engine_idle();
+
+       lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+       if (level > 0) {
+               lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
+               if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
+                       lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
+                       lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
+                       OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+                       lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+                       lvds_gen_cntl |=
+                               (radeon_bl_get_level_brightness(pdata, level) <<
+                                LVDS_BL_MOD_LEVEL_SHIFT);
+                       lvds_gen_cntl |= LVDS_ON;
+                       lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
+                       rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+                       mod_timer(&rinfo->lvds_timer,
+                                 jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+               } else {
+                       lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+                       lvds_gen_cntl |=
+                               (radeon_bl_get_level_brightness(pdata, level) <<
+                                LVDS_BL_MOD_LEVEL_SHIFT);
+                       OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+               }
+               rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+               rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
+                       & LVDS_STATE_MASK;
+       } else {
+               /* Asic bug, when turning off LVDS_ON, we have to make sure
+                  RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+               */
+               tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
+               if (rinfo->is_mobility || rinfo->is_IGP)
+                       OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+               lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
+               lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
+                                 LVDS_BL_MOD_LEVEL_SHIFT);
+               lvds_gen_cntl |= LVDS_DISPLAY_DIS;
+               OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+               udelay(100);
+               lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
+               OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+               lvds_gen_cntl &= ~(LVDS_DIGON);
+               rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+               mod_timer(&rinfo->lvds_timer,
+                         jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+               if (rinfo->is_mobility || rinfo->is_IGP)
+                       OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
+       }
+       rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+       rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
+
+       return 0;
+}
+
+static int radeon_bl_get_brightness(struct backlight_device *bd)
+{
+       return bd->props->brightness;
+}
+
+static struct backlight_properties radeon_bl_data = {
+       .owner          = THIS_MODULE,
+       .get_brightness = radeon_bl_get_brightness,
+       .update_status  = radeon_bl_update_status,
+       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void radeonfb_bl_init(struct radeonfb_info *rinfo)
+{
+       struct backlight_device *bd;
+       struct radeon_bl_privdata *pdata;
+       char name[12];
+
+       if (rinfo->mon1_type != MT_LCD)
+               return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       if (!pmac_has_backlight_type("ati") &&
+           !pmac_has_backlight_type("mnca"))
+               return;
+#endif
+
+       pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
+       if (!pdata) {
+               printk("radeonfb: Memory allocation failed\n");
+               goto error;
+       }
+
+       snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
+
+       bd = backlight_device_register(name, pdata, &radeon_bl_data);
+       if (IS_ERR(bd)) {
+               rinfo->info->bl_dev = NULL;
+               printk("radeonfb: Backlight registration failed\n");
+               goto error;
+       }
+
+       pdata->rinfo = rinfo;
+
+       /* Pardon me for that hack... maybe some day we can figure out in what
+        * direction backlight should work on a given panel?
+        */
+       pdata->negative =
+               (rinfo->family != CHIP_FAMILY_RV200 &&
+                rinfo->family != CHIP_FAMILY_RV250 &&
+                rinfo->family != CHIP_FAMILY_RV280 &&
+                rinfo->family != CHIP_FAMILY_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       pdata->negative = pdata->negative ||
+               machine_is_compatible("PowerBook4,3") ||
+               machine_is_compatible("PowerBook6,3") ||
+               machine_is_compatible("PowerBook6,5");
+#endif
+
+       mutex_lock(&rinfo->info->bl_mutex);
+       rinfo->info->bl_dev = bd;
+       fb_bl_default_curve(rinfo->info, 0,
+                63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
+               217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
+       mutex_unlock(&rinfo->info->bl_mutex);
+
+       down(&bd->sem);
+       bd->props->brightness = radeon_bl_data.max_brightness;
+       bd->props->power = FB_BLANK_UNBLANK;
+       bd->props->update_status(bd);
+       up(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_lock(&pmac_backlight_mutex);
+       if (!pmac_backlight)
+               pmac_backlight = bd;
+       mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+       printk("radeonfb: Backlight initialized (%s)\n", name);
+
+       return;
+
+error:
+       kfree(pdata);
+       return;
+}
+
+void radeonfb_bl_exit(struct radeonfb_info *rinfo)
+{
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_lock(&pmac_backlight_mutex);
+#endif
+
+       mutex_lock(&rinfo->info->bl_mutex);
+       if (rinfo->info->bl_dev) {
+               struct radeon_bl_privdata *pdata;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+               if (pmac_backlight == rinfo->info->bl_dev)
+                       pmac_backlight = NULL;
+#endif
+
+               pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
+               backlight_device_unregister(rinfo->info->bl_dev);
+               kfree(pdata);
+               rinfo->info->bl_dev = NULL;
+
+               printk("radeonfb: Backlight unloaded\n");
+       }
+       mutex_unlock(&rinfo->info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
diff --git a/drivers/video/fb_notify.c b/drivers/video/fb_notify.c
new file mode 100644 (file)
index 0000000..8c02038
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  linux/drivers/video/fb_notify.c
+ *
+ *  Copyright (C) 2006 Antonino Daplas <adaplas@pol.net>
+ *
+ *     2001 - Documented with DocBook
+ *     - Brad Douglas <brad@neruo.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+#include <linux/fb.h>
+#include <linux/notifier.h>
+
+static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
+
+/**
+ *     fb_register_client - register a client notifier
+ *     @nb: notifier block to callback on events
+ */
+int fb_register_client(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&fb_notifier_list, nb);
+}
+EXPORT_SYMBOL(fb_register_client);
+
+/**
+ *     fb_unregister_client - unregister a client notifier
+ *     @nb: notifier block to callback on events
+ */
+int fb_unregister_client(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
+}
+EXPORT_SYMBOL(fb_unregister_client);
+
+/**
+ * fb_notifier_call_chain - notify clients of fb_events
+ *
+ */
+int fb_notifier_call_chain(unsigned long val, void *v)
+{
+       return blocking_notifier_call_chain(&fb_notifier_list, val, v);
+}
+EXPORT_SYMBOL_GPL(fb_notifier_call_chain);
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
new file mode 100644 (file)
index 0000000..18ea4a5
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * 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(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;
+
+#ifndef __i386__
+       screen_info.imacpm_seg = 0;
+#endif
+
+       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");
diff --git a/drivers/video/mbx/Makefile b/drivers/video/mbx/Makefile
new file mode 100644 (file)
index 0000000..16c1165
--- /dev/null
@@ -0,0 +1,4 @@
+# Makefile for the 2700G controller driver.
+
+obj-$(CONFIG_FB_MBX)      += mbxfb.o
+obj-$(CONFIG_FB_MBX_DEBUG) += mbxfbdebugfs.o
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
new file mode 100644 (file)
index 0000000..84aab3a
--- /dev/null
@@ -0,0 +1,188 @@
+#include <linux/debugfs.h>
+
+#define BIG_BUFFER_SIZE        (1024)
+
+static char big_buffer[BIG_BUFFER_SIZE];
+
+struct mbxfb_debugfs_data {
+       struct dentry *dir;
+       struct dentry *sysconf;
+       struct dentry *clock;
+       struct dentry *display;
+       struct dentry *gsctl;
+};
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->u.generic_ip;
+       return 0;
+}
+
+static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       return count;
+}
+
+static ssize_t sysconf_read_file(struct file *file, char __user *userbuf,
+                                size_t count, loff_t *ppos)
+{
+       char * s = big_buffer;
+
+       s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG);
+       s += sprintf(s, "PFBASE = %08lx\n", PFBASE);
+       s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL);
+       s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG);
+       s += sprintf(s, "SYSRST = %08lx\n", SYSRST);
+
+       return  simple_read_from_buffer(userbuf, count, ppos,
+                                       big_buffer, s-big_buffer);
+}
+
+
+static ssize_t gsctl_read_file(struct file *file, char __user *userbuf,
+                              size_t count, loff_t *ppos)
+{
+       char * s = big_buffer;
+
+       s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL);
+       s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL);
+       s += sprintf(s, "GBBASE = %08lx\n", GBBASE);
+       s += sprintf(s, "VBBASE = %08lx\n", VBBASE);
+       s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL);
+       s += sprintf(s, "VCMSK = %08lx\n", VCMSK);
+       s += sprintf(s, "GSCADR = %08lx\n", GSCADR);
+       s += sprintf(s, "VSCADR = %08lx\n", VSCADR);
+       s += sprintf(s, "VUBASE = %08lx\n", VUBASE);
+       s += sprintf(s, "VVBASE = %08lx\n", VVBASE);
+       s += sprintf(s, "GSADR = %08lx\n", GSADR);
+       s += sprintf(s, "VSADR = %08lx\n", VSADR);
+       s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL);
+       s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE);
+       s += sprintf(s, "HCPOS = %08lx\n", HCPOS);
+       s += sprintf(s, "HCBADR = %08lx\n", HCBADR);
+       s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK);
+       s += sprintf(s, "GPLUT = %08lx\n", GPLUT);
+
+       return  simple_read_from_buffer(userbuf, count, ppos,
+                                       big_buffer, s-big_buffer);
+}
+
+static ssize_t display_read_file(struct file *file, char __user *userbuf,
+                                size_t count, loff_t *ppos)
+{
+       char * s = big_buffer;
+
+       s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL);
+       s += sprintf(s, "DHT01 = %08lx\n", DHT01);
+       s += sprintf(s, "DHT02 = %08lx\n", DHT02);
+       s += sprintf(s, "DHT03 = %08lx\n", DHT03);
+       s += sprintf(s, "DVT01 = %08lx\n", DVT01);
+       s += sprintf(s, "DVT02 = %08lx\n", DVT02);
+       s += sprintf(s, "DVT03 = %08lx\n", DVT03);
+       s += sprintf(s, "DBCOL = %08lx\n", DBCOL);
+       s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR);
+       s += sprintf(s, "DINTRS = %08lx\n", DINTRS);
+       s += sprintf(s, "DINTRE = %08lx\n", DINTRE);
+       s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT);
+       s += sprintf(s, "DSIG = %08lx\n", DSIG);
+       s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL);
+       s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL);
+       s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL);
+       s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL);
+       s += sprintf(s, "DLSTS = %08lx\n", DLSTS);
+       s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL);
+       s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM);
+       s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL);
+       s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL);
+       s += sprintf(s, "DHDET = %08lx\n", DHDET);
+       s += sprintf(s, "DVDET = %08lx\n", DVDET);
+       s += sprintf(s, "DODMSK = %08lx\n", DODMSK);
+       s += sprintf(s, "CSC01 = %08lx\n", CSC01);
+       s += sprintf(s, "CSC02 = %08lx\n", CSC02);
+       s += sprintf(s, "CSC03 = %08lx\n", CSC03);
+       s += sprintf(s, "CSC04 = %08lx\n", CSC04);
+       s += sprintf(s, "CSC05 = %08lx\n", CSC05);
+
+       return  simple_read_from_buffer(userbuf, count, ppos,
+                                       big_buffer, s-big_buffer);
+}
+
+static ssize_t clock_read_file(struct file *file, char __user *userbuf,
+                              size_t count, loff_t *ppos)
+{
+       char * s = big_buffer;
+
+       s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC);
+       s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC);
+       s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP);
+       s += sprintf(s, "COREPLL = %08lx\n", COREPLL);
+       s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL);
+       s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT);
+       s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK);
+       s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK);
+       s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK);
+       s += sprintf(s, "M24CLK = %08lx\n", M24CLK);
+       s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK);
+       s += sprintf(s, "SDCLK = %08lx\n", SDCLK);
+       s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV);
+
+       return  simple_read_from_buffer(userbuf, count, ppos,
+                                       big_buffer, s-big_buffer);
+}
+
+static struct file_operations sysconf_fops = {
+       .read = sysconf_read_file,
+       .write = write_file_dummy,
+       .open = open_file_generic,
+};
+
+static struct file_operations clock_fops = {
+       .read = clock_read_file,
+       .write = write_file_dummy,
+       .open = open_file_generic,
+};
+
+static struct file_operations display_fops = {
+       .read = display_read_file,
+       .write = write_file_dummy,
+       .open = open_file_generic,
+};
+
+static struct file_operations gsctl_fops = {
+       .read = gsctl_read_file,
+       .write = write_file_dummy,
+       .open = open_file_generic,
+};
+
+
+static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
+{
+       struct mbxfb_info *mfbi = fbi->par;
+       struct mbxfb_debugfs_data *dbg;
+
+       dbg = kzalloc(sizeof(struct mbxfb_debugfs_data), GFP_KERNEL);
+       mfbi->debugfs_data = dbg;
+
+       dbg->dir = debugfs_create_dir("mbxfb", NULL);
+       dbg->sysconf = debugfs_create_file("sysconf", 0444, dbg->dir,
+                                     fbi, &sysconf_fops);
+       dbg->clock = debugfs_create_file("clock", 0444, dbg->dir,
+                                   fbi, &clock_fops);
+       dbg->display = debugfs_create_file("display", 0444, dbg->dir,
+                                     fbi, &display_fops);
+       dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir,
+                                   fbi, &gsctl_fops);
+}
+
+static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi)
+{
+       struct mbxfb_info *mfbi = fbi->par;
+       struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data;
+
+       debugfs_remove(dbg->gsctl);
+       debugfs_remove(dbg->display);
+       debugfs_remove(dbg->clock);
+       debugfs_remove(dbg->sysconf);
+       debugfs_remove(dbg->dir);
+}
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
new file mode 100644 (file)
index 0000000..6849ab7
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ *  linux/drivers/video/mbx/mbxfb.c
+ *
+ *  Copyright (C) 2006 Compulab, Ltd.
+ *  Mike Rapoport <mike@compulab.co.il>
+ *
+ *   Based on pxafb.c
+ *
+ * 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.
+ *
+ *   Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <video/mbxfb.h>
+
+#include "regs.h"
+#include "reg_bits.h"
+
+static unsigned long virt_base_2700;
+
+#define MIN_XRES       16
+#define MIN_YRES       16
+#define MAX_XRES       2048
+#define MAX_YRES       2048
+
+#define MAX_PALETTES   16
+
+/* FIXME: take care of different chip revisions with different sizes
+   of ODFB */
+#define MEMORY_OFFSET  0x60000
+
+struct mbxfb_info {
+       struct device *dev;
+
+       struct resource *fb_res;
+       struct resource *fb_req;
+
+       struct resource *reg_res;
+       struct resource *reg_req;
+
+       void __iomem *fb_virt_addr;
+       unsigned long fb_phys_addr;
+
+       void __iomem *reg_virt_addr;
+       unsigned long reg_phys_addr;
+
+       int (*platform_probe) (struct fb_info * fb);
+       int (*platform_remove) (struct fb_info * fb);
+
+       u32 pseudo_palette[MAX_PALETTES];
+#ifdef CONFIG_FB_MBX_DEBUG
+       void *debugfs_data;
+#endif
+
+};
+
+static struct fb_var_screeninfo mbxfb_default __devinitdata = {
+       .xres = 640,
+       .yres = 480,
+       .xres_virtual = 640,
+       .yres_virtual = 480,
+       .bits_per_pixel = 16,
+       .red = {11, 5, 0},
+       .green = {5, 6, 0},
+       .blue = {0, 5, 0},
+       .activate = FB_ACTIVATE_TEST,
+       .height = -1,
+       .width = -1,
+       .pixclock = 40000,
+       .left_margin = 48,
+       .right_margin = 16,
+       .upper_margin = 33,
+       .lower_margin = 10,
+       .hsync_len = 96,
+       .vsync_len = 2,
+       .vmode = FB_VMODE_NONINTERLACED,
+       .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+};
+
+static struct fb_fix_screeninfo mbxfb_fix  __devinitdata = {
+       .id = "MBX",
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_TRUECOLOR,
+       .xpanstep = 0,
+       .ypanstep = 0,
+       .ywrapstep = 0,
+       .accel = FB_ACCEL_NONE,
+};
+
+struct pixclock_div {
+       u8 m;
+       u8 n;
+       u8 p;
+};
+
+static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps,
+                                      struct pixclock_div *div)
+{
+       u8 m, n, p;
+       unsigned int err = 0;
+       unsigned int min_err = ~0x0;
+       unsigned int clk;
+       unsigned int best_clk = 0;
+       unsigned int ref_clk = 13000;   /* FIXME: take from platform data */
+       unsigned int pixclock;
+
+       /* convert pixclock to KHz */
+       pixclock = PICOS2KHZ(pixclock_ps);
+
+       for (m = 1; m < 64; m++) {
+               for (n = 1; n < 8; n++) {
+                       for (p = 0; p < 8; p++) {
+                               clk = (ref_clk * m) / (n * (1 << p));
+                               err = (clk > pixclock) ? (clk - pixclock) :
+                                       (pixclock - clk);
+                               if (err < min_err) {
+                                       min_err = err;
+                                       best_clk = clk;
+                                       div->m = m;
+                                       div->n = n;
+                                       div->p = p;
+                               }
+                       }
+               }
+       }
+       return KHZ2PICOS(best_clk);
+}
+
+static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                          u_int trans, struct fb_info *info)
+{
+       u32 val, ret = 1;
+
+       if (regno < MAX_PALETTES) {
+               u32 *pal = info->pseudo_palette;
+
+               val = (red & 0xf800) | ((green & 0xfc00) >> 5) |
+                       ((blue & 0xf800) >> 11);
+               pal[regno] = val;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct pixclock_div div;
+
+       var->pixclock = mbxfb_get_pixclock(var->pixclock, &div);
+
+       if (var->xres < MIN_XRES)
+               var->xres = MIN_XRES;
+       if (var->yres < MIN_YRES)
+               var->yres = MIN_YRES;
+       if (var->xres > MAX_XRES)
+               return -EINVAL;
+       if (var->yres > MAX_YRES)
+               return -EINVAL;
+       var->xres_virtual = max(var->xres_virtual, var->xres);
+       var->yres_virtual = max(var->yres_virtual, var->yres);
+
+       switch (var->bits_per_pixel) {
+               /* 8 bits-per-pixel is not supported yet */
+       case 8:
+               return -EINVAL;
+       case 16:
+               var->green.length = (var->green.length == 5) ? 5 : 6;
+               var->red.length = 5;
+               var->blue.length = 5;
+               var->transp.length = 6 - var->green.length;
+               var->blue.offset = 0;
+               var->green.offset = 5;
+               var->red.offset = 5 + var->green.length;
+               var->transp.offset = (5 + var->red.offset) & 15;
+               break;
+       case 24:                /* RGB 888   */
+       case 32:                /* RGBA 8888 */
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.length = var->bits_per_pixel - 24;
+               var->transp.offset = (var->transp.length) ? 24 : 0;
+               break;
+       }
+       var->red.msb_right = 0;
+       var->green.msb_right = 0;
+       var->blue.msb_right = 0;
+       var->transp.msb_right = 0;
+
+       return 0;
+}
+
+static int mbxfb_set_par(struct fb_info *info)
+{
+       struct fb_var_screeninfo *var = &info->var;
+       struct pixclock_div div;
+       ushort hbps, ht, hfps, has;
+       ushort vbps, vt, vfps, vas;
+       u32 gsctrl = readl(GSCTRL);
+       u32 gsadr = readl(GSADR);
+
+       info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+       /* setup color mode */
+       gsctrl &= ~(FMsk(GSCTRL_GPIXFMT));
+       /* FIXME: add *WORKING* support for 8-bits per color */
+       if (info->var.bits_per_pixel == 8) {
+               return -EINVAL;
+       } else {
+               fb_dealloc_cmap(&info->cmap);
+               gsctrl &= ~GSCTRL_LUT_EN;
+
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               switch (info->var.bits_per_pixel) {
+               case 16:
+                       if (info->var.green.length == 5)
+                               gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
+                       else
+                               gsctrl |= GSCTRL_GPIXFMT_RGB565;
+                       break;
+               case 24:
+                       gsctrl |= GSCTRL_GPIXFMT_RGB888;
+                       break;
+               case 32:
+                       gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
+                       break;
+               }
+       }
+
+       /* setup resolution */
+       gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT));
+       gsctrl |= Gsctrl_Width(info->var.xres - 1) |
+               Gsctrl_Height(info->var.yres - 1);
+       writel(gsctrl, GSCTRL);
+       udelay(1000);
+
+       gsadr &= ~(FMsk(GSADR_SRCSTRIDE));
+       gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel /
+                                (8 * 16) - 1);
+       writel(gsadr, GSADR);
+       udelay(1000);
+
+       /* setup timings */
+       var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div);
+
+       writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) |
+               Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL);
+
+       hbps = var->hsync_len;
+       has = hbps + var->left_margin;
+       hfps = has + var->xres;
+       ht = hfps + var->right_margin;
+
+       vbps = var->vsync_len;
+       vas = vbps + var->upper_margin;
+       vfps = vas + var->yres;
+       vt = vfps + var->lower_margin;
+
+       writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01);
+       writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02);
+       writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03);
+       writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET);
+
+       writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01);
+       writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02);
+       writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03);
+       writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET);
+       writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL);
+
+       writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+
+       return 0;
+}
+
+static int mbxfb_blank(int blank, struct fb_info *info)
+{
+       switch (blank) {
+       case FB_BLANK_POWERDOWN:
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_NORMAL:
+               writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL);
+               udelay(1000);
+               writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK);
+               udelay(1000);
+               writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK);
+               udelay(1000);
+               break;
+       case FB_BLANK_UNBLANK:
+               writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+               udelay(1000);
+               writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK);
+               udelay(1000);
+               break;
+       }
+       return 0;
+}
+
+static struct fb_ops mbxfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = mbxfb_check_var,
+       .fb_set_par = mbxfb_set_par,
+       .fb_setcolreg = mbxfb_setcolreg,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+       .fb_blank = mbxfb_blank,
+};
+
+/*
+  Enable external SDRAM controller. Assume that all clocks are active
+  by now.
+*/
+static void __devinit setup_memc(struct fb_info *fbi)
+{
+       struct mbxfb_info *mfbi = fbi->par;
+       unsigned long tmp;
+       int i;
+
+       /* FIXME: use platfrom specific parameters */
+       /* setup SDRAM controller */
+       writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
+               LMCFG_LMA_TS),
+              LMCFG);
+       udelay(1000);
+
+       writel(LMPWR_MC_PWR_ACT, LMPWR);
+       udelay(1000);
+
+       /* setup SDRAM timings */
+       writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) |
+               Lmtim_Trc(9) | Lmtim_Tdpl(2)),
+              LMTIM);
+       udelay(1000);
+       /* setup SDRAM refresh rate */
+       writel(0xc2b, LMREFRESH);
+       udelay(1000);
+       /* setup SDRAM type parameters */
+       writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 |
+               LMTYPE_COLSZ_8),
+              LMTYPE);
+       udelay(1000);
+       /* enable memory controller */
+       writel(LMPWR_MC_PWR_ACT, LMPWR);
+       udelay(1000);
+
+       /* perform dummy reads */
+       for ( i = 0; i < 16; i++ ) {
+               tmp = readl(fbi->screen_base);
+       }
+}
+
+static void enable_clocks(struct fb_info *fbi)
+{
+       /* enable clocks */
+       writel(SYSCLKSRC_PLL_2, SYSCLKSRC);
+       udelay(1000);
+       writel(PIXCLKSRC_PLL_1, PIXCLKSRC);
+       udelay(1000);
+       writel(0x00000000, CLKSLEEP);
+       udelay(1000);
+       writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) |
+               CORE_PLL_EN),
+              COREPLL);
+       udelay(1000);
+       writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) |
+               DISP_PLL_EN),
+              DISPPLL);
+
+       writel(0x00000000, VOVRCLK);
+       udelay(1000);
+       writel(PIXCLK_EN, PIXCLK);
+       udelay(1000);
+       writel(MEMCLK_EN, MEMCLK);
+       udelay(1000);
+       writel(0x00000006, M24CLK);
+       udelay(1000);
+       writel(0x00000006, MBXCLK);
+       udelay(1000);
+       writel(SDCLK_EN, SDCLK);
+       udelay(1000);
+       writel(0x00000001, PIXCLKDIV);
+       udelay(1000);
+}
+
+static void __devinit setup_graphics(struct fb_info *fbi)
+{
+       unsigned long gsctrl;
+
+       gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres - 1) |
+               Gsctrl_Height(fbi->var.yres - 1);
+       switch (fbi->var.bits_per_pixel) {
+       case 16:
+               if (fbi->var.green.length == 5)
+                       gsctrl |= GSCTRL_GPIXFMT_ARGB1555;
+               else
+                       gsctrl |= GSCTRL_GPIXFMT_RGB565;
+               break;
+       case 24:
+               gsctrl |= GSCTRL_GPIXFMT_RGB888;
+               break;
+       case 32:
+               gsctrl |= GSCTRL_GPIXFMT_ARGB8888;
+               break;
+       }
+
+       writel(gsctrl, GSCTRL);
+       udelay(1000);
+       writel(0x00000000, GBBASE);
+       udelay(1000);
+       writel(0x00ffffff, GDRCTRL);
+       udelay(1000);
+       writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR);
+       udelay(1000);
+       writel(0x00000000, GPLUT);
+       udelay(1000);
+}
+
+static void __devinit setup_display(struct fb_info *fbi)
+{
+       unsigned long dsctrl = 0;
+
+       dsctrl = DSCTRL_BLNK_POL;
+       if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
+               dsctrl |= DSCTRL_HS_POL;
+       if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
+               dsctrl |= DSCTRL_VS_POL;
+       writel(dsctrl, DSCTRL);
+       udelay(1000);
+       writel(0xd0303010, DMCTRL);
+       udelay(1000);
+       writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+}
+
+static void __devinit enable_controller(struct fb_info *fbi)
+{
+       writel(SYSRST_RST, SYSRST);
+       udelay(1000);
+
+
+       enable_clocks(fbi);
+       setup_memc(fbi);
+       setup_graphics(fbi);
+       setup_display(fbi);
+}
+
+#ifdef CONFIG_PM
+/*
+ * Power management hooks.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
+ */
+static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
+{
+       /* make frame buffer memory enter self-refresh mode */
+       writel(LMPWR_MC_PWR_SRM, LMPWR);
+       while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
+               ; /* empty statement */
+
+       /* reset the device, since it's initial state is 'mostly sleeping' */
+       writel(SYSRST_RST, SYSRST);
+       return 0;
+}
+
+static int mbxfb_resume(struct platform_device *dev)
+{
+       struct fb_info *fbi = platform_get_drvdata(dev);
+
+       enable_clocks(fbi);
+/*     setup_graphics(fbi); */
+/*     setup_display(fbi); */
+
+       writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL);
+       return 0;
+}
+#else
+#define mbxfb_suspend  NULL
+#define mbxfb_resume   NULL
+#endif
+
+/* debugfs entries */
+#ifndef CONFIG_FB_MBX_DEBUG
+#define mbxfb_debugfs_init(x)  do {} while(0)
+#define mbxfb_debugfs_remove(x)        do {} while(0)
+#endif
+
+#define res_size(_r) (((_r)->end - (_r)->start) + 1)
+
+static int __devinit mbxfb_probe(struct platform_device *dev)
+{
+       int ret;
+       struct fb_info *fbi;
+       struct mbxfb_info *mfbi;
+       struct mbxfb_platform_data *pdata;
+
+       dev_dbg(dev, "mbxfb_probe\n");
+
+       fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev);
+       if (fbi == NULL) {
+               dev_err(&dev->dev, "framebuffer_alloc failed\n");
+               return -ENOMEM;
+       }
+
+       mfbi = fbi->par;
+       fbi->pseudo_palette = mfbi->pseudo_palette;
+       pdata = dev->dev.platform_data;
+       if (pdata->probe)
+               mfbi->platform_probe = pdata->probe;
+       if (pdata->remove)
+               mfbi->platform_remove = pdata->remove;
+
+       mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+
+       if (!mfbi->fb_res || !mfbi->reg_res) {
+               dev_err(&dev->dev, "no resources found\n");
+               ret = -ENODEV;
+               goto err1;
+       }
+
+       mfbi->fb_req = request_mem_region(mfbi->fb_res->start,
+                                         res_size(mfbi->fb_res), dev->name);
+       if (mfbi->fb_req == NULL) {
+               dev_err(&dev->dev, "failed to claim framebuffer memory\n");
+               ret = -EINVAL;
+               goto err1;
+       }
+       mfbi->fb_phys_addr = mfbi->fb_res->start;
+
+       mfbi->reg_req = request_mem_region(mfbi->reg_res->start,
+                                          res_size(mfbi->reg_res), dev->name);
+       if (mfbi->reg_req == NULL) {
+               dev_err(&dev->dev, "failed to claim Marathon registers\n");
+               ret = -EINVAL;
+               goto err2;
+       }
+       mfbi->reg_phys_addr = mfbi->reg_res->start;
+
+       mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr,
+                                             res_size(mfbi->reg_req));
+       if (!mfbi->reg_virt_addr) {
+               dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
+               ret = -EINVAL;
+               goto err3;
+       }
+       virt_base_2700 = (unsigned long)mfbi->reg_virt_addr;
+
+       mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
+                                            res_size(mfbi->fb_req));
+       if (!mfbi->reg_virt_addr) {
+               dev_err(&dev->dev, "failed to ioremap frame buffer\n");
+               ret = -EINVAL;
+               goto err4;
+       }
+
+       /* FIXME: get from platform */
+       fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
+       fbi->screen_size = 8 * 1024 * 1024;     /* 8 Megs */
+       fbi->fbops = &mbxfb_ops;
+
+       fbi->var = mbxfb_default;
+       fbi->fix = mbxfb_fix;
+       fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000;
+       fbi->fix.smem_len = 8 * 1024 * 1024;
+       fbi->fix.line_length = 640 * 2;
+
+       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+       if (ret < 0) {
+               dev_err(&dev->dev, "fb_alloc_cmap failed\n");
+               ret = -EINVAL;
+               goto err5;
+       }
+
+       platform_set_drvdata(dev, fbi);
+
+       printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node);
+
+       if (mfbi->platform_probe)
+               mfbi->platform_probe(fbi);
+
+       enable_controller(fbi);
+
+       mbxfb_debugfs_init(fbi);
+
+       ret = register_framebuffer(fbi);
+       if (ret < 0) {
+               dev_err(&dev->dev, "register_framebuffer failed\n");
+               ret = -EINVAL;
+               goto err6;
+       }
+
+       return 0;
+
+err6:
+       fb_dealloc_cmap(&fbi->cmap);
+err5:
+       iounmap(mfbi->fb_virt_addr);
+err4:
+       iounmap(mfbi->reg_virt_addr);
+err3:
+       release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
+err2:
+       release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res));
+err1:
+       framebuffer_release(fbi);
+
+       return ret;
+}
+
+static int __devexit mbxfb_remove(struct platform_device *dev)
+{
+       struct fb_info *fbi = platform_get_drvdata(dev);
+
+       writel(SYSRST_RST, SYSRST);
+       udelay(1000);
+
+       mbxfb_debugfs_remove(fbi);
+
+       if (fbi) {
+               struct mbxfb_info *mfbi = fbi->par;
+
+               unregister_framebuffer(fbi);
+               if (mfbi) {
+                       if (mfbi->platform_remove)
+                               mfbi->platform_remove(fbi);
+
+                       if (mfbi->fb_virt_addr)
+                               iounmap(mfbi->fb_virt_addr);
+                       if (mfbi->reg_virt_addr)
+                               iounmap(mfbi->reg_virt_addr);
+                       if (mfbi->reg_req)
+                               release_mem_region(mfbi->reg_req->start,
+                                                  res_size(mfbi->reg_req));
+                       if (mfbi->fb_req)
+                               release_mem_region(mfbi->fb_req->start,
+                                                  res_size(mfbi->fb_req));
+               }
+               framebuffer_release(fbi);
+       }
+
+       return 0;
+}
+
+static struct platform_driver mbxfb_driver = {
+       .probe = mbxfb_probe,
+       .remove = mbxfb_remove,
+       .suspend = mbxfb_suspend,
+       .resume = mbxfb_resume,
+       .driver = {
+               .name = "mbx-fb",
+       },
+};
+
+int __devinit mbxfb_init(void)
+{
+       return platform_driver_register(&mbxfb_driver);
+}
+
+static void __devexit mbxfb_exit(void)
+{
+       platform_driver_unregister(&mbxfb_driver);
+}
+
+module_init(mbxfb_init);
+module_exit(mbxfb_exit);
+
+MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
+MODULE_AUTHOR("Mike Rapoport, Compulab");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h
new file mode 100644 (file)
index 0000000..c226a8e
--- /dev/null
@@ -0,0 +1,418 @@
+#ifndef __REG_BITS_2700G_
+#define __REG_BITS_2700G_
+
+/* use defines from asm-arm/arch-pxa/bitfields.h for bit fields access */
+#define UData(Data)    ((unsigned long) (Data))
+#define Fld(Size, Shft)        (((Size) << 16) + (Shft))
+#define FSize(Field)   ((Field) >> 16)
+#define FShft(Field)   ((Field) & 0x0000FFFF)
+#define FMsk(Field)    (((UData (1) << FSize (Field)) - 1) << FShft (Field))
+#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1)
+#define F1stBit(Field) (UData (1) << FShft (Field))
+
+#define SYSRST_RST     (1 << 0)
+
+/* SYSCLKSRC - SYSCLK Source Control Register */
+#define SYSCLKSRC_SEL  Fld(2,0)
+#define SYSCLKSRC_REF  ((0x0) << FShft(SYSCLKSRC_SEL))
+#define SYSCLKSRC_PLL_1        ((0x1) << FShft(SYSCLKSRC_SEL))
+#define SYSCLKSRC_PLL_2        ((0x2) << FShft(SYSCLKSRC_SEL))
+
+/* PIXCLKSRC - PIXCLK Source Control Register */
+#define PIXCLKSRC_SEL  Fld(2,0)
+#define PIXCLKSRC_REF  ((0x0) << FShft(PIXCLKSRC_SEL))
+#define PIXCLKSRC_PLL_1        ((0x1) << FShft(PIXCLKSRC_SEL))
+#define PIXCLKSRC_PLL_2        ((0x2) << FShft(PIXCLKSRC_SEL))
+
+/* Clock Disable Register */
+#define CLKSLEEP_SLP   (1 << 0)
+
+/* Core PLL Control Register */
+#define CORE_PLL_M     Fld(6,7)
+#define Core_Pll_M(x)  ((x) << FShft(CORE_PLL_M))
+#define CORE_PLL_N     Fld(3,4)
+#define Core_Pll_N(x)  ((x) << FShft(CORE_PLL_N))
+#define CORE_PLL_P     Fld(3,1)
+#define Core_Pll_P(x)  ((x) << FShft(CORE_PLL_P))
+#define CORE_PLL_EN    (1 << 0)
+
+/* Display PLL Control Register */
+#define DISP_PLL_M     Fld(6,7)
+#define Disp_Pll_M(x)  ((x) << FShft(DISP_PLL_M))
+#define DISP_PLL_N     Fld(3,4)
+#define Disp_Pll_N(x)  ((x) << FShft(DISP_PLL_N))
+#define DISP_PLL_P     Fld(3,1)
+#define Disp_Pll_P(x)  ((x) << FShft(DISP_PLL_P))
+#define DISP_PLL_EN    (1 << 0)
+
+/* PLL status register */
+#define PLLSTAT_CORE_PLL_LOST_L        (1 << 3)
+#define PLLSTAT_CORE_PLL_LSTS  (1 << 2)
+#define PLLSTAT_DISP_PLL_LOST_L        (1 << 1)
+#define PLLSTAT_DISP_PLL_LSTS  (1 << 0)
+
+/* Video and scale clock control register */
+#define VOVRCLK_EN     (1 << 0)
+
+/* Pixel clock control register */
+#define PIXCLK_EN      (1 << 0)
+
+/* Memory clock control register */
+#define MEMCLK_EN      (1 << 0)
+
+/* MBX clock control register */
+#define MBXCLK_DIV     Fld(2,2)
+#define MBXCLK_DIV_1   ((0x0) << FShft(MBXCLK_DIV))
+#define MBXCLK_DIV_2   ((0x1) << FShft(MBXCLK_DIV))
+#define MBXCLK_DIV_3   ((0x2) << FShft(MBXCLK_DIV))
+#define MBXCLK_DIV_4   ((0x3) << FShft(MBXCLK_DIV))
+#define MBXCLK_EN      Fld(2,0)
+#define MBXCLK_EN_NONE ((0x0) << FShft(MBXCLK_EN))
+#define MBXCLK_EN_2D   ((0x1) << FShft(MBXCLK_EN))
+#define MBXCLK_EN_BOTH ((0x2) << FShft(MBXCLK_EN))
+
+/* M24 clock control register */
+#define M24CLK_DIV     Fld(2,1)
+#define M24CLK_DIV_1   ((0x0) << FShft(M24CLK_DIV))
+#define M24CLK_DIV_2   ((0x1) << FShft(M24CLK_DIV))
+#define M24CLK_DIV_3   ((0x2) << FShft(M24CLK_DIV))
+#define M24CLK_DIV_4   ((0x3) << FShft(M24CLK_DIV))
+#define M24CLK_EN      (1 << 0)
+
+/* SDRAM clock control register */
+#define SDCLK_EN       (1 << 0)
+
+/* PixClk Divisor Register */
+#define PIXCLKDIV_PD   Fld(9,0)
+#define Pixclkdiv_Pd(x)        ((x) << FShft(PIXCLKDIV_PD))
+
+/* LCD Config control register */
+#define LCDCFG_IN_FMT  Fld(3,28)
+#define Lcdcfg_In_Fmt(x)       ((x) << FShft(LCDCFG_IN_FMT))
+#define LCDCFG_LCD1DEN_POL     (1 << 27)
+#define LCDCFG_LCD1FCLK_POL    (1 << 26)
+#define LCDCFG_LCD1LCLK_POL    (1 << 25)
+#define LCDCFG_LCD1D_POL       (1 << 24)
+#define LCDCFG_LCD2DEN_POL     (1 << 23)
+#define LCDCFG_LCD2FCLK_POL    (1 << 22)
+#define LCDCFG_LCD2LCLK_POL    (1 << 21)
+#define LCDCFG_LCD2D_POL       (1 << 20)
+#define LCDCFG_LCD1_TS         (1 << 19)
+#define LCDCFG_LCD1D_DS                (1 << 18)
+#define LCDCFG_LCD1C_DS                (1 << 17)
+#define LCDCFG_LCD1_IS_IN      (1 << 16)
+#define LCDCFG_LCD2_TS         (1 << 3)
+#define LCDCFG_LCD2D_DS                (1 << 2)
+#define LCDCFG_LCD2C_DS                (1 << 1)
+#define LCDCFG_LCD2_IS_IN      (1 << 0)
+
+/* On-Die Frame Buffer Power Control Register */
+#define ODFBPWR_SLOW   (1 << 2)
+#define ODFBPWR_MODE   Fld(2,0)
+#define ODFBPWR_MODE_ACT       ((0x0) << FShft(ODFBPWR_MODE))
+#define ODFBPWR_MODE_ACT_LP    ((0x1) << FShft(ODFBPWR_MODE))
+#define ODFBPWR_MODE_SLEEP     ((0x2) << FShft(ODFBPWR_MODE))
+#define ODFBPWR_MODE_SHUTD     ((0x3) << FShft(ODFBPWR_MODE))
+
+/* On-Die Frame Buffer Power State Status Register */
+#define ODFBSTAT_ACT   (1 << 2)
+#define ODFBSTAT_SLP   (1 << 1)
+#define ODFBSTAT_SDN   (1 << 0)
+
+/* LMRST - Local Memory (SDRAM) Reset */
+#define LMRST_MC_RST   (1 << 0)
+
+/* LMCFG - Local Memory (SDRAM) Configuration Register */
+#define LMCFG_LMC_DS   (1 << 5)
+#define LMCFG_LMD_DS   (1 << 4)
+#define LMCFG_LMA_DS   (1 << 3)
+#define LMCFG_LMC_TS   (1 << 2)
+#define LMCFG_LMD_TS   (1 << 1)
+#define LMCFG_LMA_TS   (1 << 0)
+
+/* LMPWR - Local Memory (SDRAM) Power Control Register */
+#define LMPWR_MC_PWR_CNT       Fld(2,0)
+#define LMPWR_MC_PWR_ACT       ((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */
+#define LMPWR_MC_PWR_SRM       ((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */
+#define LMPWR_MC_PWR_DPD       ((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */
+
+/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */
+#define LMPWRSTAT_MC_PWR_CNT   Fld(2,0)
+#define LMPWRSTAT_MC_PWR_ACT   ((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */
+#define LMPWRSTAT_MC_PWR_SRM   ((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */
+#define LMPWRSTAT_MC_PWR_DPD   ((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */
+
+/* LMTYPE - Local Memory (SDRAM) Type Register */
+#define LMTYPE_CASLAT  Fld(3,10)
+#define LMTYPE_CASLAT_1        ((0x1) << FShft(LMTYPE_CASLAT))
+#define LMTYPE_CASLAT_2        ((0x2) << FShft(LMTYPE_CASLAT))
+#define LMTYPE_CASLAT_3        ((0x3) << FShft(LMTYPE_CASLAT))
+#define LMTYPE_BKSZ    Fld(2,8)
+#define LMTYPE_BKSZ_1  ((0x1) << FShft(LMTYPE_BKSZ))
+#define LMTYPE_BKSZ_2  ((0x2) << FShft(LMTYPE_BKSZ))
+#define LMTYPE_ROWSZ   Fld(4,4)
+#define LMTYPE_ROWSZ_11        ((0xb) << FShft(LMTYPE_ROWSZ))
+#define LMTYPE_ROWSZ_12        ((0xc) << FShft(LMTYPE_ROWSZ))
+#define LMTYPE_ROWSZ_13        ((0xd) << FShft(LMTYPE_ROWSZ))
+#define LMTYPE_COLSZ   Fld(4,0)
+#define LMTYPE_COLSZ_7 ((0x7) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_8 ((0x8) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_9 ((0x9) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_10        ((0xa) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_11        ((0xb) << FShft(LMTYPE_COLSZ))
+#define LMTYPE_COLSZ_12        ((0xc) << FShft(LMTYPE_COLSZ))
+
+/* LMTIM - Local Memory (SDRAM) Timing Register */
+#define LMTIM_TRAS     Fld(4,16)
+#define Lmtim_Tras(x)  ((x) << FShft(LMTIM_TRAS))
+#define LMTIM_TRP      Fld(4,12)
+#define Lmtim_Trp(x)   ((x) << FShft(LMTIM_TRP))
+#define LMTIM_TRCD     Fld(4,8)
+#define Lmtim_Trcd(x)  ((x) << FShft(LMTIM_TRCD))
+#define LMTIM_TRC      Fld(4,4)
+#define Lmtim_Trc(x)   ((x) << FShft(LMTIM_TRC))
+#define LMTIM_TDPL     Fld(4,0)
+#define Lmtim_Tdpl(x)  ((x) << FShft(LMTIM_TDPL))
+
+/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */
+#define LMREFRESH_TREF Fld(2,0)
+#define Lmrefresh_Tref(x)      ((x) << FShft(LMREFRESH_TREF))
+
+/* GSCTRL - Graphics surface control register */
+#define GSCTRL_LUT_EN  (1 << 31)
+#define GSCTRL_GPIXFMT Fld(4,27)
+#define GSCTRL_GPIXFMT_INDEXED ((0x0) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_ARGB4444        ((0x4) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_ARGB1555        ((0x5) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_RGB888  ((0x6) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_RGB565  ((0x7) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GPIXFMT_ARGB8888        ((0x8) << FShft(GSCTRL_GPIXFMT))
+#define GSCTRL_GAMMA_EN        (1 << 26)
+
+#define GSCTRL_GSWIDTH Fld(11,11)
+#define Gsctrl_Width(Pixel)    /* Display Width [1..2048 pix.]  */ \
+                        (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH))
+
+#define GSCTRL_GSHEIGHT Fld(11,0)
+#define Gsctrl_Height(Pixel)   /* Display Height [1..2048 pix.]  */ \
+                        (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT))
+
+/* GBBASE fileds */
+#define GBBASE_GLALPHA Fld(8,24)
+#define Gbbase_Glalpha(x)      ((x) << FShft(GBBASE_GLALPHA))
+
+#define GBBASE_COLKEY Fld(24,0)
+#define Gbbase_Colkey(x)       ((x) << FShft(GBBASE_COLKEY))
+
+/* GDRCTRL fields */
+#define GDRCTRL_PIXDBL (1 << 31)
+#define GDRCTRL_PIXHLV (1 << 30)
+#define GDRCTRL_LNDBL  (1 << 29)
+#define GDRCTRL_LNHLV  (1 << 28)
+#define GDRCTRL_COLKEYM        Fld(24,0)
+#define Gdrctrl_Colkeym(x)     ((x) << FShft(GDRCTRL_COLKEYM))
+
+/* GSCADR graphics stream control address register fields */
+#define GSCADR_STR_EN  (1 << 31)
+#define GSCADR_COLKEY_EN       (1 << 30)
+#define GSCADR_COLKEYSCR       (1 << 29)
+#define GSCADR_BLEND_M Fld(2,27)
+#define GSCADR_BLEND_NONE      ((0x0) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_INV       ((0x1) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_GLOB      ((0x2) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_PIX       ((0x3) << FShft(GSCADR_BLEND_M))
+#define GSCADR_BLEND_POS       Fld(2,24)
+#define GSCADR_BLEND_GFX       ((0x0) << FShft(GSCADR_BLEND_POS))
+#define GSCADR_BLEND_VID       ((0x1) << FShft(GSCADR_BLEND_POS))
+#define GSCADR_BLEND_CUR       ((0x2) << FShft(GSCADR_BLEND_POS))
+#define GSCADR_GBASE_ADR       Fld(23,0)
+#define Gscadr_Gbase_Adr(x)    ((x) << FShft(GSCADR_GBASE_ADR))
+
+/* GSADR graphics stride address register fields */
+#define GSADR_SRCSTRIDE        Fld(10,22)
+#define Gsadr_Srcstride(x)     ((x) << FShft(GSADR_SRCSTRIDE))
+#define GSADR_XSTART   Fld(11,11)
+#define Gsadr_Xstart(x)                ((x) << FShft(GSADR_XSTART))
+#define GSADR_YSTART   Fld(11,0)
+#define Gsadr_Ystart(y)                ((y) << FShft(GSADR_YSTART))
+
+/* GPLUT graphics palette register fields */
+#define GPLUT_LUTADR   Fld(8,24)
+#define Gplut_Lutadr(x)        ((x) << FShft(GPLUT_LUTADR))
+#define GPLUT_LUTDATA  Fld(24,0)
+#define Gplut_Lutdata(x)       ((x) << FShft(GPLUT_LUTDATA))
+
+/* HCCTRL - Hardware Cursor Register fields */
+#define HCCTRL_CUR_EN  (1 << 31)
+#define HCCTRL_COLKEY_EN       (1 << 29)
+#define HCCTRL_COLKEYSRC       (1 << 28)
+#define HCCTRL_BLEND_M Fld(2,26)
+#define HCCTRL_BLEND_NONE      ((0x0) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_BLEND_INV       ((0x1) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_BLEND_GLOB      ((0x2) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_BLEND_PIX       ((0x3) << FShft(HCCTRL_BLEND_M))
+#define HCCTRL_CPIXFMT Fld(3,23)
+#define HCCTRL_CPIXFMT_RGB332  ((0x3) << FShft(HCCTRL_CPIXFMT))
+#define HCCTRL_CPIXFMT_ARGB4444        ((0x4) << FShft(HCCTRL_CPIXFMT))
+#define HCCTRL_CPIXFMT_ARGB1555        ((0x5) << FShft(HCCTRL_CPIXFMT))
+#define HCCTRL_CBASE_ADR       Fld(23,0)
+#define Hcctrl_Cbase_Adr(x)    ((x) << FShft(HCCTRL_CBASE_ADR))
+
+/* HCSIZE Hardware Cursor Size Register fields */
+#define HCSIZE_BLEND_POS       Fld(2,29)
+#define HCSIZE_BLEND_GFX       ((0x0) << FShft(HCSIZE_BLEND_POS))
+#define HCSIZE_BLEND_VID       ((0x1) << FShft(HCSIZE_BLEND_POS))
+#define HCSIZE_BLEND_CUR       ((0x2) << FShft(HCSIZE_BLEND_POS))
+#define HCSIZE_CWIDTH  Fld(3,16)
+#define Hcsize_Cwidth(x)       ((x) << FShft(HCSIZE_CWIDTH))
+#define HCSIZE_CHEIGHT Fld(3,0)
+#define Hcsize_Cheight(x)      ((x) << FShft(HCSIZE_CHEIGHT))
+
+/* HCPOS Hardware Cursor Position Register fields */
+#define HCPOS_SWITCHSRC        (1 << 30)
+#define HCPOS_CURBLINK Fld(6,24)
+#define Hcpos_Curblink(x)      ((x) << FShft(HCPOS_CURBLINK))
+#define HCPOS_XSTART   Fld(12,12)
+#define Hcpos_Xstart(x)        ((x) << FShft(HCPOS_XSTART))
+#define HCPOS_YSTART   Fld(12,0)
+#define Hcpos_Ystart(y)        ((y) << FShft(HCPOS_YSTART))
+
+/* HCBADR Hardware Cursor Blend Address Register */
+#define HCBADR_GLALPHA Fld(8,24)
+#define Hcbadr_Glalpha(x)      ((x) << FShft(HCBADR_GLALPHA))
+#define HCBADR_COLKEY  Fld(24,0)
+#define Hcbadr_Colkey(x)       ((x) << FShft(HCBADR_COLKEY))
+
+/* HCCKMSK - Hardware Cursor Color Key Mask Register */
+#define HCCKMSK_COLKEY_M       Fld(24,0)
+#define Hcckmsk_Colkey_M(x)    ((x) << FShft(HCCKMSK_COLKEY_M))
+
+/* DSCTRL - Display sync control register */
+#define DSCTRL_SYNCGEN_EN      (1 << 31)
+#define DSCTRL_DPL_RST         (1 << 29)
+#define DSCTRL_PWRDN_M         (1 << 28)
+#define DSCTRL_UPDSYNCCNT      (1 << 26)
+#define DSCTRL_UPDINTCNT       (1 << 25)
+#define DSCTRL_UPDCNT          (1 << 24)
+#define DSCTRL_UPDWAIT Fld(4,16)
+#define Dsctrl_Updwait(x)      ((x) << FShft(DSCTRL_UPDWAIT))
+#define DSCTRL_CLKPOL          (1 << 11)
+#define DSCTRL_CSYNC_EN                (1 << 10)
+#define DSCTRL_VS_SLAVE                (1 << 7)
+#define DSCTRL_HS_SLAVE                (1 << 6)
+#define DSCTRL_BLNK_POL                (1 << 5)
+#define DSCTRL_BLNK_DIS                (1 << 4)
+#define DSCTRL_VS_POL          (1 << 3)
+#define DSCTRL_VS_DIS          (1 << 2)
+#define DSCTRL_HS_POL          (1 << 1)
+#define DSCTRL_HS_DIS          (1 << 0)
+
+/* DHT01 - Display horizontal timing register 01 */
+#define DHT01_HBPS     Fld(12,16)
+#define Dht01_Hbps(x)  ((x) << FShft(DHT01_HBPS))
+#define DHT01_HT       Fld(12,0)
+#define Dht01_Ht(x)    ((x) << FShft(DHT01_HT))
+
+/* DHT02 - Display horizontal timing register 02 */
+#define DHT02_HAS      Fld(12,16)
+#define Dht02_Has(x)   ((x) << FShft(DHT02_HAS))
+#define DHT02_HLBS     Fld(12,0)
+#define Dht02_Hlbs(x)  ((x) << FShft(DHT02_HLBS))
+
+/* DHT03 - Display horizontal timing register 03 */
+#define DHT03_HFPS     Fld(12,16)
+#define Dht03_Hfps(x)  ((x) << FShft(DHT03_HFPS))
+#define DHT03_HRBS     Fld(12,0)
+#define Dht03_Hrbs(x)  ((x) << FShft(DHT03_HRBS))
+
+/* DVT01 - Display vertical timing register 01 */
+#define DVT01_VBPS     Fld(12,16)
+#define Dvt01_Vbps(x)  ((x) << FShft(DVT01_VBPS))
+#define DVT01_VT       Fld(12,0)
+#define Dvt01_Vt(x)    ((x) << FShft(DVT01_VT))
+
+/* DVT02 - Display vertical timing register 02 */
+#define DVT02_VAS      Fld(12,16)
+#define Dvt02_Vas(x)   ((x) << FShft(DVT02_VAS))
+#define DVT02_VTBS     Fld(12,0)
+#define Dvt02_Vtbs(x)  ((x) << FShft(DVT02_VTBS))
+
+/* DVT03 - Display vertical timing register 03 */
+#define DVT03_VFPS     Fld(12,16)
+#define Dvt03_Vfps(x)  ((x) << FShft(DVT03_VFPS))
+#define DVT03_VBBS     Fld(12,0)
+#define Dvt03_Vbbs(x)  ((x) << FShft(DVT03_VBBS))
+
+/* DVECTRL - display vertical event control register */
+#define DVECTRL_VEVENT Fld(12,16)
+#define Dvectrl_Vevent(x)      ((x) << FShft(DVECTRL_VEVENT))
+#define DVECTRL_VFETCH Fld(12,0)
+#define Dvectrl_Vfetch(x)      ((x) << FShft(DVECTRL_VFETCH))
+
+/* DHDET - display horizontal DE timing register */
+#define DHDET_HDES     Fld(12,16)
+#define Dhdet_Hdes(x)  ((x) << FShft(DHDET_HDES))
+#define DHDET_HDEF     Fld(12,0)
+#define Dhdet_Hdef(x)  ((x) << FShft(DHDET_HDEF))
+
+/* DVDET - display vertical DE timing register */
+#define DVDET_VDES     Fld(12,16)
+#define Dvdet_Vdes(x)  ((x) << FShft(DVDET_VDES))
+#define DVDET_VDEF     Fld(12,0)
+#define Dvdet_Vdef(x)  ((x) << FShft(DVDET_VDEF))
+
+/* DODMSK - display output data mask register */
+#define DODMSK_MASK_LVL        (1 << 31)
+#define DODMSK_BLNK_LVL        (1 << 30)
+#define DODMSK_MASK_B  Fld(8,16)
+#define Dodmsk_Mask_B(x)       ((x) << FShft(DODMSK_MASK_B))
+#define DODMSK_MASK_G  Fld(8,8)
+#define Dodmsk_Mask_G(x)       ((x) << FShft(DODMSK_MASK_G))
+#define DODMSK_MASK_R  Fld(8,0)
+#define Dodmsk_Mask_R(x)       ((x) << FShft(DODMSK_MASK_R))
+
+/* DBCOL - display border color control register */
+#define DBCOL_BORDCOL  Fld(24,0)
+#define Dbcol_Bordcol(x)       ((x) << FShft(DBCOL_BORDCOL))
+
+/* DVLNUM - display vertical line number register */
+#define DVLNUM_VLINE   Fld(12,0)
+#define Dvlnum_Vline(x)        ((x) << FShft(DVLNUM_VLINE))
+
+/* DMCTRL - Display Memory Control Register */
+#define DMCTRL_MEM_REF Fld(2,30)
+#define DMCTRL_MEM_REF_ACT     ((0x0) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_MEM_REF_HB      ((0x1) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_MEM_REF_VB      ((0x2) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_MEM_REF_BOTH    ((0x3) << FShft(DMCTRL_MEM_REF))
+#define DMCTRL_UV_THRHLD       Fld(6,24)
+#define Dmctrl_Uv_Thrhld(x)    ((x) << FShft(DMCTRL_UV_THRHLD))
+#define DMCTRL_V_THRHLD                Fld(7,16)
+#define Dmctrl_V_Thrhld(x)     ((x) << FShft(DMCTRL_V_THRHLD))
+#define DMCTRL_D_THRHLD                Fld(7,8)
+#define Dmctrl_D_Thrhld(x)     ((x) << FShft(DMCTRL_D_THRHLD))
+#define DMCTRL_BURSTLEN        Fld(6,0)
+#define Dmctrl_Burstlen(x)     ((x) << FShft(DMCTRL_BURSTLEN))
+
+
+/* DLSTS - display load status register */
+#define DLSTS_RLD_ADONE        (1 << 23)
+/* #define DLSTS_RLD_ADOUT     Fld(23,0) */
+
+/* DLLCTRL - display list load control register */
+#define DLLCTRL_RLD_ADRLN      Fld(8,24)
+#define Dllctrl_Rld_Adrln(x)   ((x) << FShft(DLLCTRL_RLD_ADRLN))
+
+/* SPOCTRL - Scale Pitch/Order Control Register */
+#define SPOCTRL_H_SC_BP                (1 << 31)
+#define SPOCTRL_V_SC_BP                (1 << 30)
+#define SPOCTRL_HV_SC_OR       (1 << 29)
+#define SPOCTRL_VS_UR_C                (1 << 27)
+#define SPOCTRL_VORDER Fld(2,16)
+#define SPOCTRL_VORDER_1TAP    ((0x0) << FShft(SPOCTRL_VORDER))
+#define SPOCTRL_VORDER_2TAP    ((0x1) << FShft(SPOCTRL_VORDER))
+#define SPOCTRL_VORDER_4TAP    ((0x3) << FShft(SPOCTRL_VORDER))
+#define SPOCTRL_VPITCH Fld(16,0)
+#define Spoctrl_Vpitch(x)      ((x) << FShft(SPOCTRL_VPITCH))
+
+#endif /* __REG_BITS_2700G_ */
diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h
new file mode 100644 (file)
index 0000000..ad20be0
--- /dev/null
@@ -0,0 +1,195 @@
+#ifndef __REGS_2700G_
+#define __REGS_2700G_
+
+/* extern unsigned long virt_base_2700; */
+/* #define __REG_2700G(x)      (*(volatile unsigned long*)((x)+virt_base_2700)) */
+#define __REG_2700G(x) ((x)+virt_base_2700)
+
+/* System Configuration Registers (0x0000_0000  0x0000_0010) */
+#define SYSCFG         __REG_2700G(0x00000000)
+#define PFBASE         __REG_2700G(0x00000004)
+#define PFCEIL         __REG_2700G(0x00000008)
+#define POLLFLAG       __REG_2700G(0x0000000c)
+#define SYSRST         __REG_2700G(0x00000010)
+
+/* Interrupt Control Registers (0x0000_0014  0x0000_002F) */
+#define NINTPW         __REG_2700G(0x00000014)
+#define MINTENABLE     __REG_2700G(0x00000018)
+#define MINTSTAT       __REG_2700G(0x0000001c)
+#define SINTENABLE     __REG_2700G(0x00000020)
+#define SINTSTAT       __REG_2700G(0x00000024)
+#define SINTCLR                __REG_2700G(0x00000028)
+
+/* Clock Control Registers (0x0000_002C  0x0000_005F) */
+#define SYSCLKSRC      __REG_2700G(0x0000002c)
+#define PIXCLKSRC      __REG_2700G(0x00000030)
+#define CLKSLEEP       __REG_2700G(0x00000034)
+#define COREPLL                __REG_2700G(0x00000038)
+#define DISPPLL                __REG_2700G(0x0000003c)
+#define PLLSTAT                __REG_2700G(0x00000040)
+#define VOVRCLK                __REG_2700G(0x00000044)
+#define PIXCLK         __REG_2700G(0x00000048)
+#define MEMCLK         __REG_2700G(0x0000004c)
+#define M24CLK         __REG_2700G(0x00000054)
+#define MBXCLK         __REG_2700G(0x00000054)
+#define SDCLK          __REG_2700G(0x00000058)
+#define PIXCLKDIV      __REG_2700G(0x0000005c)
+
+/* LCD Port Control Register (0x0000_0060  0x0000_006F) */
+#define LCD_CONFIG     __REG_2700G(0x00000060)
+
+/* On-Die Frame Buffer Registers (0x0000_0064  0x0000_006B) */
+#define ODFBPWR                __REG_2700G(0x00000064)
+#define ODFBSTAT       __REG_2700G(0x00000068)
+
+/* GPIO Registers (0x0000_006C  0x0000_007F) */
+#define GPIOCGF                __REG_2700G(0x0000006c)
+#define GPIOHI         __REG_2700G(0x00000070)
+#define GPIOLO         __REG_2700G(0x00000074)
+#define GPIOSTAT       __REG_2700G(0x00000078)
+
+/* Pulse Width Modulator (PWM) Registers (0x0000_0200  0x0000_02FF) */
+#define PWMRST         __REG_2700G(0x00000200)
+#define PWMCFG         __REG_2700G(0x00000204)
+#define PWM0DIV                __REG_2700G(0x00000210)
+#define PWM0DUTY       __REG_2700G(0x00000214)
+#define PWM0PER                __REG_2700G(0x00000218)
+#define PWM1DIV                __REG_2700G(0x00000220)
+#define PWM1DUTY       __REG_2700G(0x00000224)
+#define PWM1PER                __REG_2700G(0x00000228)
+
+/* Identification (ID) Registers (0x0000_0300  0x0000_0FFF) */
+#define ID             __REG_2700G(0x00000FF0)
+
+/* Local Memory (SDRAM) Interface Registers (0x0000_1000  0x0000_1FFF) */
+#define LMRST          __REG_2700G(0x00001000)
+#define LMCFG          __REG_2700G(0x00001004)
+#define LMPWR          __REG_2700G(0x00001008)
+#define LMPWRSTAT      __REG_2700G(0x0000100c)
+#define LMCEMR         __REG_2700G(0x00001010)
+#define LMTYPE         __REG_2700G(0x00001014)
+#define LMTIM          __REG_2700G(0x00001018)
+#define LMREFRESH      __REG_2700G(0x0000101c)
+#define LMPROTMIN      __REG_2700G(0x00001020)
+#define LMPROTMAX      __REG_2700G(0x00001024)
+#define LMPROTCFG      __REG_2700G(0x00001028)
+#define LMPROTERR      __REG_2700G(0x0000102c)
+
+/* Plane Controller Registers (0x0000_2000  0x0000_2FFF) */
+#define GSCTRL         __REG_2700G(0x00002000)
+#define VSCTRL         __REG_2700G(0x00002004)
+#define GBBASE         __REG_2700G(0x00002020)
+#define VBBASE         __REG_2700G(0x00002024)
+#define GDRCTRL                __REG_2700G(0x00002040)
+#define VCMSK          __REG_2700G(0x00002044)
+#define GSCADR         __REG_2700G(0x00002060)
+#define VSCADR         __REG_2700G(0x00002064)
+#define VUBASE         __REG_2700G(0x00002084)
+#define VVBASE         __REG_2700G(0x000020a4)
+#define GSADR          __REG_2700G(0x000020c0)
+#define VSADR          __REG_2700G(0x000020c4)
+#define HCCTRL         __REG_2700G(0x00002100)
+#define HCSIZE         __REG_2700G(0x00002110)
+#define HCPOS          __REG_2700G(0x00002120)
+#define HCBADR         __REG_2700G(0x00002130)
+#define HCCKMSK                __REG_2700G(0x00002140)
+#define GPLUT          __REG_2700G(0x00002150)
+#define DSCTRL         __REG_2700G(0x00002154)
+#define DHT01          __REG_2700G(0x00002158)
+#define DHT02          __REG_2700G(0x0000215c)
+#define DHT03          __REG_2700G(0x00002160)
+#define DVT01          __REG_2700G(0x00002164)
+#define DVT02          __REG_2700G(0x00002168)
+#define DVT03          __REG_2700G(0x0000216c)
+#define DBCOL          __REG_2700G(0x00002170)
+#define BGCOLOR                __REG_2700G(0x00002174)
+#define DINTRS         __REG_2700G(0x00002178)
+#define DINTRE         __REG_2700G(0x0000217c)
+#define DINTRCNT       __REG_2700G(0x00002180)
+#define DSIG           __REG_2700G(0x00002184)
+#define DMCTRL         __REG_2700G(0x00002188)
+#define CLIPCTRL       __REG_2700G(0x0000218c)
+#define SPOCTRL                __REG_2700G(0x00002190)
+#define SVCTRL         __REG_2700G(0x00002194)
+
+/* 0x0000_2198 */
+/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */
+#define VSCOEFF0       __REG_2700G(0x00002198)
+#define VSCOEFF1       __REG_2700G(0x0000219c)
+#define VSCOEFF2       __REG_2700G(0x000021a0)
+#define VSCOEFF3       __REG_2700G(0x000021a4)
+#define VSCOEFF4       __REG_2700G(0x000021a8)
+
+#define SHCTRL         __REG_2700G(0x000021b0)
+
+/* 0x0000_21B4 */
+/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */
+#define HSCOEFF0       __REG_2700G(0x000021b4)
+#define HSCOEFF1       __REG_2700G(0x000021b8)
+#define HSCOEFF2       __REG_2700G(0x000021bc)
+#define HSCOEFF3       __REG_2700G(0x000021b0)
+#define HSCOEFF4       __REG_2700G(0x000021c4)
+#define HSCOEFF5       __REG_2700G(0x000021c8)
+#define HSCOEFF6       __REG_2700G(0x000021cc)
+#define HSCOEFF7       __REG_2700G(0x000021d0)
+#define HSCOEFF8       __REG_2700G(0x000021d4)
+
+#define SSSIZE         __REG_2700G(0x000021D8)
+
+/* 0x0000_2200 */
+/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */
+#define VIDGAM0                __REG_2700G(0x00002200)
+#define VIDGAM1                __REG_2700G(0x00002204)
+#define VIDGAM2                __REG_2700G(0x00002208)
+#define VIDGAM3                __REG_2700G(0x0000220c)
+#define VIDGAM4                __REG_2700G(0x00002210)
+#define VIDGAM5                __REG_2700G(0x00002214)
+#define VIDGAM6                __REG_2700G(0x00002218)
+#define VIDGAM7                __REG_2700G(0x0000221c)
+#define VIDGAM8                __REG_2700G(0x00002220)
+#define VIDGAM9                __REG_2700G(0x00002224)
+#define VIDGAM10       __REG_2700G(0x00002228)
+#define VIDGAM11       __REG_2700G(0x0000222c)
+#define VIDGAM12       __REG_2700G(0x00002230)
+#define VIDGAM13       __REG_2700G(0x00002234)
+#define VIDGAM14       __REG_2700G(0x00002238)
+#define VIDGAM15       __REG_2700G(0x0000223c)
+#define VIDGAM16       __REG_2700G(0x00002240)
+
+/* 0x0000_2250 */
+/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */
+#define GFXGAM0                __REG_2700G(0x00002250)
+#define GFXGAM1                __REG_2700G(0x00002254)
+#define GFXGAM2                __REG_2700G(0x00002258)
+#define GFXGAM3                __REG_2700G(0x0000225c)
+#define GFXGAM4                __REG_2700G(0x00002260)
+#define GFXGAM5                __REG_2700G(0x00002264)
+#define GFXGAM6                __REG_2700G(0x00002268)
+#define GFXGAM7                __REG_2700G(0x0000226c)
+#define GFXGAM8                __REG_2700G(0x00002270)
+#define GFXGAM9                __REG_2700G(0x00002274)
+#define GFXGAM10       __REG_2700G(0x00002278)
+#define GFXGAM11       __REG_2700G(0x0000227c)
+#define GFXGAM12       __REG_2700G(0x00002280)
+#define GFXGAM13       __REG_2700G(0x00002284)
+#define GFXGAM14       __REG_2700G(0x00002288)
+#define GFXGAM15       __REG_2700G(0x0000228c)
+#define GFXGAM16       __REG_2700G(0x00002290)
+
+#define DLSTS          __REG_2700G(0x00002300)
+#define DLLCTRL                __REG_2700G(0x00002304)
+#define DVLNUM         __REG_2700G(0x00002308)
+#define DUCTRL         __REG_2700G(0x0000230c)
+#define DVECTRL                __REG_2700G(0x00002310)
+#define DHDET          __REG_2700G(0x00002314)
+#define DVDET          __REG_2700G(0x00002318)
+#define DODMSK         __REG_2700G(0x0000231c)
+#define CSC01          __REG_2700G(0x00002330)
+#define CSC02          __REG_2700G(0x00002334)
+#define CSC03          __REG_2700G(0x00002338)
+#define CSC04          __REG_2700G(0x0000233c)
+#define CSC05          __REG_2700G(0x00002340)
+
+#define FB_MEMORY_START        __REG_2700G(0x00060000)
+
+#endif /* __REGS_2700G_ */
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
new file mode 100644 (file)
index 0000000..5b75ae4
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Backlight code for nVidia based graphic cards
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * This program is free software; you can 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/backlight.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#include <asm/machdep.h>
+#endif
+
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
+
+static struct backlight_properties nvidia_bl_data;
+
+/* Call with fb_info->bl_mutex held */
+static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
+               int level)
+{
+       struct fb_info *info = pci_get_drvdata(par->pci_dev);
+       int nlevel;
+
+       /* Get and convert the value */
+       nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
+
+       if (nlevel < 0)
+               nlevel = 0;
+       else if (nlevel < MIN_LEVEL)
+               nlevel = MIN_LEVEL;
+       else if (nlevel > MAX_LEVEL)
+               nlevel = MAX_LEVEL;
+
+       return nlevel;
+}
+
+/* Call with fb_info->bl_mutex held */
+static int __nvidia_bl_update_status(struct backlight_device *bd)
+{
+       struct nvidia_par *par = class_get_devdata(&bd->class_dev);
+       u32 tmp_pcrt, tmp_pmc, fpcontrol;
+       int level;
+
+       if (!par->FlatPanel)
+               return 0;
+
+       if (bd->props->power != FB_BLANK_UNBLANK ||
+           bd->props->fb_blank != FB_BLANK_UNBLANK)
+               level = 0;
+       else
+               level = bd->props->brightness;
+
+       tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+       tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+       fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+       if (level > 0) {
+               tmp_pcrt |= 0x1;
+               tmp_pmc |= (1 << 31); /* backlight bit */
+               tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
+               fpcontrol |= par->fpSyncs;
+       } else
+               fpcontrol |= 0x20000022;
+
+       NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+       NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+       NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+       return 0;
+}
+
+static int nvidia_bl_update_status(struct backlight_device *bd)
+{
+       struct nvidia_par *par = class_get_devdata(&bd->class_dev);
+       struct fb_info *info = pci_get_drvdata(par->pci_dev);
+       int ret;
+
+       mutex_lock(&info->bl_mutex);
+       ret = __nvidia_bl_update_status(bd);
+       mutex_unlock(&info->bl_mutex);
+
+       return ret;
+}
+
+static int nvidia_bl_get_brightness(struct backlight_device *bd)
+{
+       return bd->props->brightness;
+}
+
+static struct backlight_properties nvidia_bl_data = {
+       .owner          = THIS_MODULE,
+       .get_brightness = nvidia_bl_get_brightness,
+       .update_status  = nvidia_bl_update_status,
+       .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void nvidia_bl_set_power(struct fb_info *info, int power)
+{
+       mutex_lock(&info->bl_mutex);
+
+       if (info->bl_dev) {
+               down(&info->bl_dev->sem);
+               info->bl_dev->props->power = power;
+               __nvidia_bl_update_status(info->bl_dev);
+               up(&info->bl_dev->sem);
+       }
+
+       mutex_unlock(&info->bl_mutex);
+}
+
+void nvidia_bl_init(struct nvidia_par *par)
+{
+       struct fb_info *info = pci_get_drvdata(par->pci_dev);
+       struct backlight_device *bd;
+       char name[12];
+
+       if (!par->FlatPanel)
+               return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       if (!machine_is(powermac) ||
+           !pmac_has_backlight_type("mnca"))
+               return;
+#endif
+
+       snprintf(name, sizeof(name), "nvidiabl%d", info->node);
+
+       bd = backlight_device_register(name, par, &nvidia_bl_data);
+       if (IS_ERR(bd)) {
+               info->bl_dev = NULL;
+               printk(KERN_WARNING "nvidia: Backlight registration failed\n");
+               goto error;
+       }
+
+       mutex_lock(&info->bl_mutex);
+       info->bl_dev = bd;
+       fb_bl_default_curve(info, 0,
+               0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+               0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+       mutex_unlock(&info->bl_mutex);
+
+       down(&bd->sem);
+       bd->props->brightness = nvidia_bl_data.max_brightness;
+       bd->props->power = FB_BLANK_UNBLANK;
+       bd->props->update_status(bd);
+       up(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_lock(&pmac_backlight_mutex);
+       if (!pmac_backlight)
+               pmac_backlight = bd;
+       mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+       printk("nvidia: Backlight initialized (%s)\n", name);
+
+       return;
+
+error:
+       return;
+}
+
+void nvidia_bl_exit(struct nvidia_par *par)
+{
+       struct fb_info *info = pci_get_drvdata(par->pci_dev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_lock(&pmac_backlight_mutex);
+#endif
+
+       mutex_lock(&info->bl_mutex);
+       if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+               if (pmac_backlight == info->bl_dev)
+                       pmac_backlight = NULL;
+#endif
+
+               backlight_device_unregister(info->bl_dev);
+
+               printk("nvidia: Backlight unloaded\n");
+       }
+       mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
diff --git a/drivers/video/pnx4008/Makefile b/drivers/video/pnx4008/Makefile
new file mode 100644 (file)
index 0000000..636aacc
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the new PNX4008 framebuffer device driver
+#
+
+obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o
+obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnxrgbfb.o
+
diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h
new file mode 100644 (file)
index 0000000..d80a614
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * linux/drivers/video/pnx4008/dum.h
+ *
+ * Internal header for SDUM
+ *
+ * 2005 (c) Koninklijke Philips N.V. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PNX008_DUM_H__
+#define __PNX008_DUM_H__
+
+#include <asm/arch/platform.h>
+
+#define PNX4008_DUMCONF_VA_BASE                IO_ADDRESS(PNX4008_DUMCONF_BASE)
+#define PNX4008_DUM_MAIN_VA_BASE       IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE)
+
+/* DUM CFG ADDRESSES */
+#define DUM_CH_BASE_ADR                (PNX4008_DUMCONF_VA_BASE + 0x00)
+#define DUM_CH_MIN_ADR         (PNX4008_DUMCONF_VA_BASE + 0x00)
+#define DUM_CH_MAX_ADR         (PNX4008_DUMCONF_VA_BASE + 0x04)
+#define DUM_CH_CONF_ADR                (PNX4008_DUMCONF_VA_BASE + 0x08)
+#define DUM_CH_STAT_ADR                (PNX4008_DUMCONF_VA_BASE + 0x0C)
+#define DUM_CH_CTRL_ADR                (PNX4008_DUMCONF_VA_BASE + 0x10)
+
+#define CH_MARG                (0x100 / sizeof(u32))
+#define DUM_CH_MIN(i)  (*((volatile u32 *)DUM_CH_MIN_ADR + (i) * CH_MARG))
+#define DUM_CH_MAX(i)  (*((volatile u32 *)DUM_CH_MAX_ADR + (i) * CH_MARG))
+#define DUM_CH_CONF(i) (*((volatile u32 *)DUM_CH_CONF_ADR + (i) * CH_MARG))
+#define DUM_CH_STAT(i) (*((volatile u32 *)DUM_CH_STAT_ADR + (i) * CH_MARG))
+#define DUM_CH_CTRL(i) (*((volatile u32 *)DUM_CH_CTRL_ADR + (i) * CH_MARG))
+
+#define DUM_CONF_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x00)
+#define DUM_CTRL_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x04)
+#define DUM_STAT_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x08)
+#define DUM_DECODE_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x0C)
+#define DUM_COM_BASE_ADR      (PNX4008_DUM_MAIN_VA_BASE + 0x10)
+#define DUM_SYNC_C_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x14)
+#define DUM_CLK_DIV_ADR       (PNX4008_DUM_MAIN_VA_BASE + 0x18)
+#define DUM_DIRTY_LOW_ADR     (PNX4008_DUM_MAIN_VA_BASE + 0x20)
+#define DUM_DIRTY_HIGH_ADR    (PNX4008_DUM_MAIN_VA_BASE + 0x24)
+#define DUM_FORMAT_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x28)
+#define DUM_WTCFG1_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x30)
+#define DUM_RTCFG1_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x34)
+#define DUM_WTCFG2_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x38)
+#define DUM_RTCFG2_ADR        (PNX4008_DUM_MAIN_VA_BASE + 0x3C)
+#define DUM_TCFG_ADR          (PNX4008_DUM_MAIN_VA_BASE + 0x40)
+#define DUM_OUTP_FORMAT1_ADR  (PNX4008_DUM_MAIN_VA_BASE + 0x44)
+#define DUM_OUTP_FORMAT2_ADR  (PNX4008_DUM_MAIN_VA_BASE + 0x48)
+#define DUM_SYNC_MODE_ADR     (PNX4008_DUM_MAIN_VA_BASE + 0x4C)
+#define DUM_SYNC_OUT_C_ADR    (PNX4008_DUM_MAIN_VA_BASE + 0x50)
+
+#define DUM_CONF              (*(volatile u32 *)(DUM_CONF_ADR))
+#define DUM_CTRL              (*(volatile u32 *)(DUM_CTRL_ADR))
+#define DUM_STAT              (*(volatile u32 *)(DUM_STAT_ADR))
+#define DUM_DECODE            (*(volatile u32 *)(DUM_DECODE_ADR))
+#define DUM_COM_BASE          (*(volatile u32 *)(DUM_COM_BASE_ADR))
+#define DUM_SYNC_C            (*(volatile u32 *)(DUM_SYNC_C_ADR))
+#define DUM_CLK_DIV           (*(volatile u32 *)(DUM_CLK_DIV_ADR))
+#define DUM_DIRTY_LOW         (*(volatile u32 *)(DUM_DIRTY_LOW_ADR))
+#define DUM_DIRTY_HIGH        (*(volatile u32 *)(DUM_DIRTY_HIGH_ADR))
+#define DUM_FORMAT            (*(volatile u32 *)(DUM_FORMAT_ADR))
+#define DUM_WTCFG1            (*(volatile u32 *)(DUM_WTCFG1_ADR))
+#define DUM_RTCFG1            (*(volatile u32 *)(DUM_RTCFG1_ADR))
+#define DUM_WTCFG2            (*(volatile u32 *)(DUM_WTCFG2_ADR))
+#define DUM_RTCFG2            (*(volatile u32 *)(DUM_RTCFG2_ADR))
+#define DUM_TCFG              (*(volatile u32 *)(DUM_TCFG_ADR))
+#define DUM_OUTP_FORMAT1      (*(volatile u32 *)(DUM_OUTP_FORMAT1_ADR))
+#define DUM_OUTP_FORMAT2      (*(volatile u32 *)(DUM_OUTP_FORMAT2_ADR))
+#define DUM_SYNC_MODE         (*(volatile u32 *)(DUM_SYNC_MODE_ADR))
+#define DUM_SYNC_OUT_C        (*(volatile u32 *)(DUM_SYNC_OUT_C_ADR))
+
+/* DUM SLAVE ADDRESSES */
+#define DUM_SLAVE_WRITE_ADR      (PNX4008_DUM_MAINCFG_BASE + 0x0000000)
+#define DUM_SLAVE_READ1_I_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000000)
+#define DUM_SLAVE_READ1_R_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000004)
+#define DUM_SLAVE_READ2_I_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x1000008)
+#define DUM_SLAVE_READ2_R_ADR    (PNX4008_DUM_MAINCFG_BASE + 0x100000C)
+
+#define DUM_SLAVE_WRITE_W  ((volatile u32 *)(DUM_SLAVE_WRITE_ADR))
+#define DUM_SLAVE_WRITE_HW ((volatile u16 *)(DUM_SLAVE_WRITE_ADR))
+#define DUM_SLAVE_READ1_I  ((volatile u8 *)(DUM_SLAVE_READ1_I_ADR))
+#define DUM_SLAVE_READ1_R  ((volatile u16 *)(DUM_SLAVE_READ1_R_ADR))
+#define DUM_SLAVE_READ2_I  ((volatile u8 *)(DUM_SLAVE_READ2_I_ADR))
+#define DUM_SLAVE_READ2_R  ((volatile u16 *)(DUM_SLAVE_READ2_R_ADR))
+
+/* Sony display register addresses */
+#define DISP_0_REG            (0x00)
+#define DISP_1_REG            (0x01)
+#define DISP_CAL_REG          (0x20)
+#define DISP_ID_REG           (0x2A)
+#define DISP_XMIN_L_REG       (0x30)
+#define DISP_XMIN_H_REG       (0x31)
+#define DISP_YMIN_REG         (0x32)
+#define DISP_XMAX_L_REG       (0x34)
+#define DISP_XMAX_H_REG       (0x35)
+#define DISP_YMAX_REG         (0x36)
+#define DISP_SYNC_EN_REG      (0x38)
+#define DISP_SYNC_RISE_L_REG  (0x3C)
+#define DISP_SYNC_RISE_H_REG  (0x3D)
+#define DISP_SYNC_FALL_L_REG  (0x3E)
+#define DISP_SYNC_FALL_H_REG  (0x3F)
+#define DISP_PIXEL_REG        (0x0B)
+#define DISP_DUMMY1_REG       (0x28)
+#define DISP_DUMMY2_REG       (0x29)
+#define DISP_TIMING_REG       (0x98)
+#define DISP_DUMP_REG         (0x99)
+
+/* Sony display constants */
+#define SONY_ID1              (0x22)
+#define SONY_ID2              (0x23)
+
+/* Philips display register addresses */
+#define PH_DISP_ORIENT_REG    (0x003)
+#define PH_DISP_YPOINT_REG    (0x200)
+#define PH_DISP_XPOINT_REG    (0x201)
+#define PH_DISP_PIXEL_REG     (0x202)
+#define PH_DISP_YMIN_REG      (0x406)
+#define PH_DISP_YMAX_REG      (0x407)
+#define PH_DISP_XMIN_REG      (0x408)
+#define PH_DISP_XMAX_REG      (0x409)
+
+/* Misc constants */
+#define NO_VALID_DISPLAY_FOUND      (0)
+#define DISPLAY2_IS_NOT_CONNECTED   (0)
+
+/* register values */
+#define V_BAC_ENABLE           (BIT(0))
+#define V_BAC_DISABLE_IDLE     (BIT(1))
+#define V_BAC_DISABLE_TRIG     (BIT(2))
+#define V_DUM_RESET            (BIT(3))
+#define V_MUX_RESET            (BIT(4))
+#define BAC_ENABLED            (BIT(0))
+#define BAC_DISABLED           0
+
+/* Sony LCD commands */
+#define V_LCD_STANDBY_OFF      ((BIT(25)) | (0 << 16) | DISP_0_REG)
+#define V_LCD_USE_9BIT_BUS     ((BIT(25)) | (2 << 16) | DISP_1_REG)
+#define V_LCD_SYNC_RISE_L      ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_L_REG)
+#define V_LCD_SYNC_RISE_H      ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_H_REG)
+#define V_LCD_SYNC_FALL_L      ((BIT(25)) | (160 << 16) | DISP_SYNC_FALL_L_REG)
+#define V_LCD_SYNC_FALL_H      ((BIT(25)) | (0 << 16) | DISP_SYNC_FALL_H_REG)
+#define V_LCD_SYNC_ENABLE      ((BIT(25)) | (128 << 16) | DISP_SYNC_EN_REG)
+#define V_LCD_DISPLAY_ON       ((BIT(25)) | (64 << 16) | DISP_0_REG)
+
+enum {
+       PAD_NONE,
+       PAD_512,
+       PAD_1024
+};
+
+enum {
+       RGB888,
+       RGB666,
+       RGB565,
+       BGR565,
+       ARGB1555,
+       ABGR1555,
+       ARGB4444,
+       ABGR4444
+};
+
+struct dum_setup {
+       int sync_neg_edge;
+       int round_robin;
+       int mux_int;
+       int synced_dirty_flag_int;
+       int dirty_flag_int;
+       int error_int;
+       int pf_empty_int;
+       int sf_empty_int;
+       int bac_dis_int;
+       u32 dirty_base_adr;
+       u32 command_base_adr;
+       u32 sync_clk_div;
+       int sync_output;
+       u32 sync_restart_val;
+       u32 set_sync_high;
+       u32 set_sync_low;
+};
+
+struct dum_ch_setup {
+       int disp_no;
+       u32 xmin;
+       u32 ymin;
+       u32 xmax;
+       u32 ymax;
+       int xmirror;
+       int ymirror;
+       int rotate;
+       u32 minadr;
+       u32 maxadr;
+       u32 dirtybuffer;
+       int pad;
+       int format;
+       int hwdirty;
+       int slave_trans;
+};
+
+struct disp_window {
+       u32 xmin_l;
+       u32 xmin_h;
+       u32 ymin;
+       u32 xmax_l;
+       u32 xmax_h;
+       u32 ymax;
+};
+
+#endif                         /* #ifndef __PNX008_DUM_H__ */
diff --git a/drivers/video/pnx4008/fbcommon.h b/drivers/video/pnx4008/fbcommon.h
new file mode 100644 (file)
index 0000000..4ebc87d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005 Philips Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
+*/
+
+#define QCIF_W  (176)
+#define QCIF_H  (144)
+
+#define CIF_W   (352)
+#define CIF_H   (288)
+
+#define LCD_X_RES      208
+#define LCD_Y_RES      320
+#define LCD_X_PAD      256
+#define LCD_BBP                4       /* Bytes Per Pixel */
+
+#define DISP_MAX_X_SIZE     (320)
+#define DISP_MAX_Y_SIZE     (208)
+
+#define RETURNVAL_BASE (0x400)
+
+enum fb_ioctl_returntype {
+       ENORESOURCESLEFT = RETURNVAL_BASE,
+       ERESOURCESNOTFREED,
+       EPROCNOTOWNER,
+       EFBNOTOWNER,
+       ECOPYFAILED,
+       EIOREMAPFAILED,
+};
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
new file mode 100644 (file)
index 0000000..7d9453c
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * drivers/video/pnx4008/pnxrgbfb.c
+ *
+ * PNX4008's framebuffer support
+ *
+ * Author: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
+ * Based on Philips Semiconductors's code
+ *
+ * Copyrght (c) 2005 MontaVista Software, Inc.
+ * Copyright (c) 2005 Philips Semiconductors
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/uaccess.h>
+#include "sdum.h"
+#include "fbcommon.h"
+
+static u32 colreg[16];
+
+static struct fb_var_screeninfo rgbfb_var __initdata = {
+       .xres = LCD_X_RES,
+       .yres = LCD_Y_RES,
+       .xres_virtual = LCD_X_RES,
+       .yres_virtual = LCD_Y_RES,
+       .bits_per_pixel = 32,
+       .red.offset = 16,
+       .red.length = 8,
+       .green.offset = 8,
+       .green.length = 8,
+       .blue.offset = 0,
+       .blue.length = 8,
+       .left_margin = 0,
+       .right_margin = 0,
+       .upper_margin = 0,
+       .lower_margin = 0,
+       .vmode = FB_VMODE_NONINTERLACED,
+};
+static struct fb_fix_screeninfo rgbfb_fix __initdata = {
+       .id = "RGBFB",
+       .line_length = LCD_X_RES * LCD_BBP,
+       .type = FB_TYPE_PACKED_PIXELS,
+       .visual = FB_VISUAL_TRUECOLOR,
+       .xpanstep = 0,
+       .ypanstep = 0,
+       .ywrapstep = 0,
+       .accel = FB_ACCEL_NONE,
+};
+
+static int channel_owned;
+
+static int no_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       return 0;
+}
+
+static int rgbfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                          u_int transp, struct fb_info *info)
+{
+       if (regno > 15)
+               return 1;
+
+       colreg[regno] = ((red & 0xff00) << 8) | (green & 0xff00) |
+           ((blue & 0xff00) >> 8);
+       return 0;
+}
+
+static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       return pnx4008_sdum_mmap(info, vma, NULL);
+}
+
+static struct fb_ops rgbfb_ops = {
+       .fb_mmap = rgbfb_mmap,
+       .fb_setcolreg = rgbfb_setcolreg,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+};
+
+static int rgbfb_remove(struct platform_device *pdev)
+{
+       struct fb_info *info = platform_get_drvdata(pdev);
+
+       if (info) {
+               unregister_framebuffer(info);
+               fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
+               platform_set_drvdata(pdev, NULL);
+               kfree(info);
+       }
+
+       pnx4008_free_dum_channel(channel_owned, pdev->id);
+       pnx4008_set_dum_exit_notification(pdev->id);
+
+       return 0;
+}
+
+static int __devinit rgbfb_probe(struct platform_device *pdev)
+{
+       struct fb_info *info;
+       struct dumchannel_uf chan_uf;
+       int ret;
+       char *option;
+
+       info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
+       if (!info) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       pnx4008_get_fb_addresses(FB_TYPE_RGB, (void **)&info->screen_base,
+                                (dma_addr_t *) &rgbfb_fix.smem_start,
+                                &rgbfb_fix.smem_len);
+
+       if ((ret = pnx4008_alloc_dum_channel(pdev->id)) < 0)
+               goto err0;
+       else {
+               channel_owned = ret;
+               chan_uf.channelnr = channel_owned;
+               chan_uf.dirty = (u32 *) NULL;
+               chan_uf.source = (u32 *) rgbfb_fix.smem_start;
+               chan_uf.x_offset = 0;
+               chan_uf.y_offset = 0;
+               chan_uf.width = LCD_X_RES;
+               chan_uf.height = LCD_Y_RES;
+
+               if ((ret = pnx4008_put_dum_channel_uf(chan_uf, pdev->id))< 0)
+                       goto err1;
+
+               if ((ret =
+                    pnx4008_set_dum_channel_sync(channel_owned, CONF_SYNC_ON,
+                                                 pdev->id)) < 0)
+                       goto err1;
+
+               if ((ret =
+                    pnx4008_set_dum_channel_dirty_detect(channel_owned,
+                                                        CONF_DIRTYDETECTION_ON,
+                                                        pdev->id)) < 0)
+                       goto err1;
+       }
+
+       if (!fb_get_options("pnxrgbfb", &option) && !strcmp(option, "nocursor"))
+               rgbfb_ops.fb_cursor = no_cursor;
+
+       info->node = -1;
+       info->flags = FBINFO_FLAG_DEFAULT;
+       info->fbops = &rgbfb_ops;
+       info->fix = rgbfb_fix;
+       info->var = rgbfb_var;
+       info->screen_size = rgbfb_fix.smem_len;
+       info->pseudo_palette = info->par;
+       info->par = NULL;
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret < 0)
+               goto err2;
+
+       ret = register_framebuffer(info);
+       if (ret < 0)
+               goto err3;
+       platform_set_drvdata(pdev, info);
+
+       return 0;
+
+err3:
+       fb_dealloc_cmap(&info->cmap);
+err2:
+       framebuffer_release(info);
+err1:
+       pnx4008_free_dum_channel(channel_owned, pdev->id);
+err0:
+       kfree(info);
+err:
+       return ret;
+}
+
+static struct platform_driver rgbfb_driver = {
+       .driver = {
+               .name = "rgbfb",
+       },
+       .probe = rgbfb_probe,
+       .remove = rgbfb_remove,
+};
+
+static int __init rgbfb_init(void)
+{
+       return platform_driver_register(&rgbfb_driver);
+}
+
+static void __exit rgbfb_exit(void)
+{
+       platform_driver_unregister(&rgbfb_driver);
+}
+
+module_init(rgbfb_init);
+module_exit(rgbfb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
new file mode 100644 (file)
index 0000000..51f0ecc
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * drivers/video/pnx4008/sdum.c
+ *
+ * Display Update Master support
+ *
+ * Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
+ *          Vitaly Wool <vitalywool@gmail.com>
+ * Based on Philips Semiconductors's code
+ *
+ * Copyrght (c) 2005-2006 MontaVista Software, Inc.
+ * Copyright (c) 2005 Philips Semiconductors
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <asm/uaccess.h>
+#include <asm/arch/gpio.h>
+
+#include "sdum.h"
+#include "fbcommon.h"
+#include "dum.h"
+
+/* Framebuffers we have */
+
+static struct pnx4008_fb_addr {
+       int fb_type;
+       long addr_offset;
+       long fb_length;
+} fb_addr[] = {
+       [0] = {
+               FB_TYPE_YUV, 0, 0xB0000
+       },
+       [1] = {
+               FB_TYPE_RGB, 0xB0000, 0x50000
+       },
+};
+
+static struct dum_data {
+       u32 lcd_phys_start;
+       u32 lcd_virt_start;
+       u32 slave_phys_base;
+       u32 *slave_virt_base;
+       int fb_owning_channel[MAX_DUM_CHANNELS];
+       struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS];
+} dum_data;
+
+/* Different local helper functions */
+
+static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup)
+{
+       return (ch_setup->xmax - ch_setup->xmin + 1);
+}
+
+static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup)
+{
+       return (ch_setup->ymax - ch_setup->ymin + 1);
+}
+
+static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup)
+{
+       return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup));
+}
+
+static u32 nof_bytes(struct dum_ch_setup *ch_setup)
+{
+       u32 r = nof_pixels_dxy(ch_setup);
+       switch (ch_setup->format) {
+       case RGB888:
+       case RGB666:
+               r *= 4;
+               break;
+
+       default:
+               r *= 2;
+               break;
+       }
+       return r;
+}
+
+static u32 build_command(int disp_no, u32 reg, u32 val)
+{
+       return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) |
+               (reg << 0));
+}
+
+static u32 build_double_index(int disp_no, u32 val)
+{
+       return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0));
+}
+
+static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw)
+{
+       dw->ymin = ch_setup->ymin;
+       dw->ymax = ch_setup->ymax;
+       dw->xmin_l = ch_setup->xmin & 0xFF;
+       dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8;
+       dw->xmax_l = ch_setup->xmax & 0xFF;
+       dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8;
+}
+
+static int put_channel(struct dumchannel chan)
+{
+       int i = chan.channelnr;
+
+       if (i < 0 || i > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else {
+               DUM_CH_MIN(i) = chan.dum_ch_min;
+               DUM_CH_MAX(i) = chan.dum_ch_max;
+               DUM_CH_CONF(i) = chan.dum_ch_conf;
+               DUM_CH_CTRL(i) = chan.dum_ch_ctrl;
+       }
+
+       return 0;
+}
+
+static void clear_channel(int channr)
+{
+       struct dumchannel chan;
+
+       chan.channelnr = channr;
+       chan.dum_ch_min = 0;
+       chan.dum_ch_max = 0;
+       chan.dum_ch_conf = 0;
+       chan.dum_ch_ctrl = 0;
+
+       put_channel(chan);
+}
+
+static int put_cmd_string(struct cmdstring cmds)
+{
+       u16 *cmd_str_virtaddr;
+       u32 *cmd_ptr0_virtaddr;
+       u32 cmd_str_physaddr;
+
+       int i = cmds.channelnr;
+
+       if (i < 0 || i > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if ((cmd_ptr0_virtaddr =
+                 (int *)ioremap_nocache(DUM_COM_BASE,
+                                        sizeof(int) * MAX_DUM_CHANNELS)) ==
+                NULL)
+               return -EIOREMAPFAILED;
+       else {
+               cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]);
+               if ((cmd_str_virtaddr =
+                    (u16 *) ioremap_nocache(cmd_str_physaddr,
+                                            sizeof(cmds))) == NULL) {
+                       iounmap(cmd_ptr0_virtaddr);
+                       return -EIOREMAPFAILED;
+               } else {
+                       int t;
+                       for (t = 0; t < 8; t++)
+                               iowrite16(*((u16 *)&cmds.prestringlen + t),
+                                         cmd_str_virtaddr + t);
+
+                       for (t = 0; t < cmds.prestringlen / 2; t++)
+                                iowrite16(*((u16 *)&cmds.precmd + t),
+                                          cmd_str_virtaddr + t + 8);
+
+                       for (t = 0; t < cmds.poststringlen / 2; t++)
+                               iowrite16(*((u16 *)&cmds.postcmd + t),
+                                         cmd_str_virtaddr + t + 8 +
+                                               cmds.prestringlen / 2);
+
+                       iounmap(cmd_ptr0_virtaddr);
+                       iounmap(cmd_str_virtaddr);
+               }
+       }
+
+       return 0;
+}
+
+static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup)
+{
+       struct cmdstring cmds_c;
+       struct cmdstring *cmds = &cmds_c;
+       struct disp_window dw;
+       int standard;
+       u32 orientation = 0;
+       struct dumchannel chan = { 0 };
+       int ret;
+
+       if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) {
+               standard = 0;
+
+               orientation = BIT(1);   /* always set 9-bit-bus */
+               if (ch_setup->xmirror)
+                       orientation |= BIT(4);
+               if (ch_setup->ymirror)
+                       orientation |= BIT(3);
+               if (ch_setup->rotate)
+                       orientation |= BIT(0);
+       } else
+               standard = 1;
+
+       cmds->channelnr = ch_no;
+
+       /* build command string header */
+       if (standard) {
+               cmds->prestringlen = 32;
+               cmds->poststringlen = 0;
+       } else {
+               cmds->prestringlen = 48;
+               cmds->poststringlen = 16;
+       }
+
+       cmds->format =
+           (u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format));
+       cmds->reserved = 0x0;
+       cmds->startaddr_low = (ch_setup->minadr & 0xFFFF);
+       cmds->startaddr_high = (ch_setup->minadr >> 16);
+
+       if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0)
+           && (ch_setup->xmin == 0)
+           && (ch_setup->ymin == 0) && (ch_setup->xmax == 0)
+           && (ch_setup->ymax == 0)) {
+               cmds->pixdatlen_low = 0;
+               cmds->pixdatlen_high = 0;
+       } else {
+               u32 nbytes = nof_bytes(ch_setup);
+               cmds->pixdatlen_low = (nbytes & 0xFFFF);
+               cmds->pixdatlen_high = (nbytes >> 16);
+       }
+
+       if (ch_setup->slave_trans)
+               cmds->pixdatlen_high |= BIT(15);
+
+       /* build pre-string */
+       build_disp_window(ch_setup, &dw);
+
+       if (standard) {
+               cmds->precmd[0] =
+                   build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99);
+               cmds->precmd[1] =
+                   build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
+                                 dw.xmin_l);
+               cmds->precmd[2] =
+                   build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
+                                 dw.xmin_h);
+               cmds->precmd[3] =
+                   build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
+               cmds->precmd[4] =
+                   build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
+                                 dw.xmax_l);
+               cmds->precmd[5] =
+                   build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
+                                 dw.xmax_h);
+               cmds->precmd[6] =
+                   build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
+               cmds->precmd[7] =
+                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
+       } else {
+               if (dw.xmin_l == ch_no)
+                       cmds->precmd[0] =
+                           build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
+                                         0x99);
+               else
+                       cmds->precmd[0] =
+                           build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
+                                         ch_no);
+
+               cmds->precmd[1] =
+                   build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
+                                 dw.xmin_l);
+               cmds->precmd[2] =
+                   build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
+                                 dw.xmin_h);
+               cmds->precmd[3] =
+                   build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
+               cmds->precmd[4] =
+                   build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
+                                 dw.xmax_l);
+               cmds->precmd[5] =
+                   build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
+                                 dw.xmax_h);
+               cmds->precmd[6] =
+                   build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
+               cmds->precmd[7] =
+                   build_command(ch_setup->disp_no, DISP_1_REG, orientation);
+               cmds->precmd[8] =
+                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
+               cmds->precmd[9] =
+                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
+               cmds->precmd[0xA] =
+                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
+               cmds->precmd[0xB] =
+                   build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
+               cmds->postcmd[0] =
+                   build_command(ch_setup->disp_no, DISP_1_REG, BIT(1));
+               cmds->postcmd[1] =
+                   build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1);
+               cmds->postcmd[2] =
+                   build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2);
+               cmds->postcmd[3] =
+                   build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3);
+       }
+
+       if ((ret = put_cmd_string(cmds_c)) != 0) {
+               return ret;
+       }
+
+       chan.channelnr = cmds->channelnr;
+       chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr;
+       chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr;
+       chan.dum_ch_conf = 0x002;
+       chan.dum_ch_ctrl = 0x04;
+
+       put_channel(chan);
+
+       return 0;
+}
+
+static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer,
+                       u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h)
+{
+
+       struct dum_ch_setup k;
+       int ret;
+
+       /* keep width & height within display area */
+       if ((xpos + w) > DISP_MAX_X_SIZE)
+               w = DISP_MAX_X_SIZE - xpos;
+
+       if ((ypos + h) > DISP_MAX_Y_SIZE)
+               h = DISP_MAX_Y_SIZE - ypos;
+
+       /* assume 1 display only */
+       k.disp_no = 0;
+       k.xmin = xpos;
+       k.ymin = ypos;
+       k.xmax = xpos + (w - 1);
+       k.ymax = ypos + (h - 1);
+
+       /* adjust min and max values if necessary */
+       if (k.xmin > DISP_MAX_X_SIZE - 1)
+               k.xmin = DISP_MAX_X_SIZE - 1;
+       if (k.ymin > DISP_MAX_Y_SIZE - 1)
+               k.ymin = DISP_MAX_Y_SIZE - 1;
+
+       if (k.xmax > DISP_MAX_X_SIZE - 1)
+               k.xmax = DISP_MAX_X_SIZE - 1;
+       if (k.ymax > DISP_MAX_Y_SIZE - 1)
+               k.ymax = DISP_MAX_Y_SIZE - 1;
+
+       k.xmirror = 0;
+       k.ymirror = 0;
+       k.rotate = 0;
+       k.minadr = (u32) frame_buffer;
+       k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2));
+       k.pad = PAD_1024;
+       k.dirtybuffer = (u32) dirty_buffer;
+       k.format = RGB888;
+       k.hwdirty = 0;
+       k.slave_trans = 0;
+
+       ret = dum_ch_setup(ch_no, &k);
+
+       return ret;
+}
+
+static void lcd_reset(void)
+{
+       u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE);
+
+       udelay(1);
+       iowrite32(BIT(19), &dum_pio_base[2]);
+       udelay(1);
+       iowrite32(BIT(19), &dum_pio_base[1]);
+       udelay(1);
+}
+
+static int dum_init(struct platform_device *pdev)
+{
+       struct clk *clk;
+
+       /* enable DUM clock */
+       clk = clk_get(&pdev->dev, "dum_ck");
+       if (IS_ERR(clk)) {
+               printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n");
+               return PTR_ERR(clk);
+       }
+
+       clk_set_rate(clk, 1);
+       clk_put(clk);
+
+       DUM_CTRL = V_DUM_RESET;
+
+       /* set priority to "round-robin". All other params to "false" */
+       DUM_CONF = BIT(9);
+
+       /* Display 1 */
+       DUM_WTCFG1 = PNX4008_DUM_WT_CFG;
+       DUM_RTCFG1 = PNX4008_DUM_RT_CFG;
+       DUM_TCFG = PNX4008_DUM_T_CFG;
+
+       return 0;
+}
+
+static void dum_chan_init(void)
+{
+       int i = 0, ch = 0;
+       u32 *cmdptrs;
+       u32 *cmdstrings;
+
+       DUM_COM_BASE =
+               CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS;
+
+       if ((cmdptrs =
+            (u32 *) ioremap_nocache(DUM_COM_BASE,
+                                    sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL)
+               return;
+
+       for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++)
+               iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch,
+                         cmdptrs + ch);
+
+       for (ch = 0; ch < MAX_DUM_CHANNELS; ch++)
+               clear_channel(ch);
+
+       /* Clear the cmdstrings */
+       cmdstrings =
+           (u32 *)ioremap_nocache(*cmdptrs,
+                                  BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS);
+
+       if (!cmdstrings)
+               goto out;
+
+       for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32);
+            i++)
+               iowrite32(0, cmdstrings + i);
+
+       iounmap((u32 *)cmdstrings);
+
+out:
+       iounmap((u32 *)cmdptrs);
+}
+
+static void lcd_init(void)
+{
+       lcd_reset();
+
+       DUM_OUTP_FORMAT1 = 0; /* RGB666 */
+
+       udelay(1);
+       iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base);
+       udelay(1);
+       iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base);
+       udelay(1);
+}
+
+/* Interface exported to framebuffer drivers */
+
+int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
+                            dma_addr_t *phys_addr, int *fb_length)
+{
+       int i;
+       int ret = -1;
+       for (i = 0; i < ARRAY_SIZE(fb_addr); i++)
+               if (fb_addr[i].fb_type == fb_type) {
+                       *virt_addr = (void *)(dum_data.lcd_virt_start +
+                                       fb_addr[i].addr_offset);
+                       *phys_addr =
+                           dum_data.lcd_phys_start + fb_addr[i].addr_offset;
+                       *fb_length = fb_addr[i].fb_length;
+                       ret = 0;
+                       break;
+               }
+
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_get_fb_addresses);
+
+int pnx4008_alloc_dum_channel(int dev_id)
+{
+       int i = 0;
+
+       while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1))
+               i++;
+
+       if (i == MAX_DUM_CHANNELS)
+               return -ENORESOURCESLEFT;
+       else {
+               dum_data.fb_owning_channel[i] = dev_id;
+               return i;
+       }
+}
+
+EXPORT_SYMBOL(pnx4008_alloc_dum_channel);
+
+int pnx4008_free_dum_channel(int channr, int dev_id)
+{
+       if (channr < 0 || channr > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if (dum_data.fb_owning_channel[channr] != dev_id)
+               return -EFBNOTOWNER;
+       else {
+               clear_channel(channr);
+               dum_data.fb_owning_channel[channr] = -1;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_free_dum_channel);
+
+int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id)
+{
+       int i = chan_uf.channelnr;
+       int ret;
+
+       if (i < 0 || i > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if (dum_data.fb_owning_channel[i] != dev_id)
+               return -EFBNOTOWNER;
+       else if ((ret =
+                 display_open(chan_uf.channelnr, 0, chan_uf.dirty,
+                              chan_uf.source, chan_uf.y_offset,
+                              chan_uf.x_offset, chan_uf.height,
+                              chan_uf.width)) != 0)
+               return ret;
+       else {
+               dum_data.chan_uf_store[i].dirty = chan_uf.dirty;
+               dum_data.chan_uf_store[i].source = chan_uf.source;
+               dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset;
+               dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset;
+               dum_data.chan_uf_store[i].width = chan_uf.width;
+               dum_data.chan_uf_store[i].height = chan_uf.height;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_put_dum_channel_uf);
+
+int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id)
+{
+       if (channr < 0 || channr > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if (dum_data.fb_owning_channel[channr] != dev_id)
+               return -EFBNOTOWNER;
+       else {
+               if (val == CONF_SYNC_ON) {
+                       DUM_CH_CONF(channr) |= CONF_SYNCENABLE;
+                       DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK |
+                               DUM_CHANNEL_CFG_SYNC_MASK_SET;
+               } else if (val == CONF_SYNC_OFF)
+                       DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE;
+               else
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_set_dum_channel_sync);
+
+int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id)
+{
+       if (channr < 0 || channr > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if (dum_data.fb_owning_channel[channr] != dev_id)
+               return -EFBNOTOWNER;
+       else {
+               if (val == CONF_DIRTYDETECTION_ON)
+                       DUM_CH_CONF(channr) |= CONF_DIRTYENABLE;
+               else if (val == CONF_DIRTYDETECTION_OFF)
+                       DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE;
+               else
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect);
+
+#if 0 /* Functions not used currently, but likely to be used in future */
+
+static int get_channel(struct dumchannel *p_chan)
+{
+       int i = p_chan->channelnr;
+
+       if (i < 0 || i > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else {
+               p_chan->dum_ch_min = DUM_CH_MIN(i);
+               p_chan->dum_ch_max = DUM_CH_MAX(i);
+               p_chan->dum_ch_conf = DUM_CH_CONF(i);
+               p_chan->dum_ch_stat = DUM_CH_STAT(i);
+               p_chan->dum_ch_ctrl = 0;        /* WriteOnly control register */
+       }
+
+       return 0;
+}
+
+int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id)
+{
+       int i = p_chan_uf->channelnr;
+
+       if (i < 0 || i > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if (dum_data.fb_owning_channel[i] != dev_id)
+               return -EFBNOTOWNER;
+       else {
+               p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty;
+               p_chan_uf->source = dum_data.chan_uf_store[i].source;
+               p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset;
+               p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset;
+               p_chan_uf->width = dum_data.chan_uf_store[i].width;
+               p_chan_uf->height = dum_data.chan_uf_store[i].height;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_get_dum_channel_uf);
+
+int pnx4008_get_dum_channel_config(int channr, int dev_id)
+{
+       int ret;
+       struct dumchannel chan;
+
+       if (channr < 0 || channr > MAX_DUM_CHANNELS)
+               return -EINVAL;
+       else if (dum_data.fb_owning_channel[channr] != dev_id)
+               return -EFBNOTOWNER;
+       else {
+               chan.channelnr = channr;
+               if ((ret = get_channel(&chan)) != 0)
+                       return ret;
+       }
+
+       return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK);
+}
+
+EXPORT_SYMBOL(pnx4008_get_dum_channel_config);
+
+int pnx4008_force_update_dum_channel(int channr, int dev_id)
+{
+       if (channr < 0 || channr > MAX_DUM_CHANNELS)
+               return -EINVAL;
+
+       else if (dum_data.fb_owning_channel[channr] != dev_id)
+               return -EFBNOTOWNER;
+       else
+               DUM_CH_CTRL(channr) = CTRL_SETDIRTY;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_force_update_dum_channel);
+
+#endif
+
+int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma,
+                     struct device *dev)
+{
+       unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+
+       if (off < info->fix.smem_len) {
+               vma->vm_pgoff += 1;
+               return dma_mmap_writecombine(dev, vma,
+                               (void *)dum_data.lcd_virt_start,
+                               dum_data.lcd_phys_start,
+                               FB_DMA_SIZE);
+       }
+       return -EINVAL;
+}
+
+EXPORT_SYMBOL(pnx4008_sdum_mmap);
+
+int pnx4008_set_dum_exit_notification(int dev_id)
+{
+       int i;
+
+       for (i = 0; i < MAX_DUM_CHANNELS; i++)
+               if (dum_data.fb_owning_channel[i] == dev_id)
+                       return -ERESOURCESNOTFREED;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(pnx4008_set_dum_exit_notification);
+
+/* Platform device driver for DUM */
+
+static int sdum_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       int retval = 0;
+       struct clk *clk;
+
+       clk = clk_get(0, "dum_ck");
+       if (!IS_ERR(clk)) {
+               clk_set_rate(clk, 0);
+               clk_put(clk);
+       } else
+               retval = PTR_ERR(clk);
+
+       /* disable BAC */
+       DUM_CTRL = V_BAC_DISABLE_IDLE;
+
+       /* LCD standby & turn off display */
+       lcd_reset();
+
+       return retval;
+}
+
+static int sdum_resume(struct platform_device *pdev)
+{
+       int retval = 0;
+       struct clk *clk;
+
+       clk = clk_get(0, "dum_ck");
+       if (!IS_ERR(clk)) {
+               clk_set_rate(clk, 1);
+               clk_put(clk);
+       } else
+               retval = PTR_ERR(clk);
+
+       /* wait for BAC disable */
+       DUM_CTRL = V_BAC_DISABLE_TRIG;
+
+       while (DUM_CTRL & BAC_ENABLED)
+               udelay(10);
+
+       /* re-init LCD */
+       lcd_init();
+
+       /* enable BAC and reset MUX */
+       DUM_CTRL = V_BAC_ENABLE;
+       udelay(1);
+       DUM_CTRL = V_MUX_RESET;
+       return 0;
+}
+
+static int __devinit sdum_probe(struct platform_device *pdev)
+{
+       int ret = 0, i = 0;
+
+       /* map frame buffer */
+       dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev,
+                                                      FB_DMA_SIZE,
+                                                      &dum_data.lcd_phys_start,
+                                                      GFP_KERNEL);
+
+       if (!dum_data.lcd_virt_start) {
+               ret = -ENOMEM;
+               goto out_3;
+       }
+
+       /* map slave registers */
+       dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE;
+       dum_data.slave_virt_base =
+           (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32));
+
+       if (dum_data.slave_virt_base == NULL) {
+               ret = -ENOMEM;
+               goto out_2;
+       }
+
+       /* initialize DUM and LCD display */
+       ret = dum_init(pdev);
+       if (ret)
+               goto out_1;
+
+       dum_chan_init();
+       lcd_init();
+
+       DUM_CTRL = V_BAC_ENABLE;
+       udelay(1);
+       DUM_CTRL = V_MUX_RESET;
+
+       /* set decode address and sync clock divider */
+       DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK;
+       DUM_CLK_DIV = PNX4008_DUM_CLK_DIV;
+
+       for (i = 0; i < MAX_DUM_CHANNELS; i++)
+               dum_data.fb_owning_channel[i] = -1;
+
+       /*setup wakeup interrupt */
+       start_int_set_rising_edge(SE_DISP_SYNC_INT);
+       start_int_ack(SE_DISP_SYNC_INT);
+       start_int_umask(SE_DISP_SYNC_INT);
+
+       return 0;
+
+out_1:
+       iounmap((void *)dum_data.slave_virt_base);
+out_2:
+       dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
+                       (void *)dum_data.lcd_virt_start,
+                       dum_data.lcd_phys_start);
+out_3:
+       return ret;
+}
+
+static int sdum_remove(struct platform_device *pdev)
+{
+       struct clk *clk;
+
+       start_int_mask(SE_DISP_SYNC_INT);
+
+       clk = clk_get(0, "dum_ck");
+       if (!IS_ERR(clk)) {
+               clk_set_rate(clk, 0);
+               clk_put(clk);
+       }
+
+       iounmap((void *)dum_data.slave_virt_base);
+
+       dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
+                       (void *)dum_data.lcd_virt_start,
+                       dum_data.lcd_phys_start);
+
+       return 0;
+}
+
+static struct platform_driver sdum_driver = {
+       .driver = {
+               .name = "sdum",
+       },
+       .probe = sdum_probe,
+       .remove = sdum_remove,
+       .suspend = sdum_suspend,
+       .resume = sdum_resume,
+};
+
+int __init sdum_init(void)
+{
+       return platform_driver_register(&sdum_driver);
+}
+
+static void __exit sdum_exit(void)
+{
+       platform_driver_unregister(&sdum_driver);
+};
+
+module_init(sdum_init);
+module_exit(sdum_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.h b/drivers/video/pnx4008/sdum.h
new file mode 100644 (file)
index 0000000..e8c5dcd
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2005 Philips Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
+*/
+
+#define MAX_DUM_CHANNELS       64
+
+#define RGB_MEM_WINDOW(x) (0x10000000 + (x)*0x00100000)
+
+#define QCIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x30000: -1)
+#define CIF_OFFSET(x)  (((x) == 0) ? 0x00000: ((x) == 1) ? 0x60000: -1)
+
+#define CTRL_SETDIRTY          (0x00000001)
+#define CONF_DIRTYENABLE       (0x00000020)
+#define CONF_SYNCENABLE                (0x00000004)
+
+#define DIRTY_ENABLED(conf)    ((conf) & 0x0020)
+#define SYNC_ENABLED(conf)     ((conf) & 0x0004)
+
+/* Display 1 & 2 Write Timing Configuration */
+#define PNX4008_DUM_WT_CFG             0x00372000
+
+/* Display 1 & 2 Read Timing Configuration */
+#define PNX4008_DUM_RT_CFG             0x00003A47
+
+/* DUM Transit State Timing Configuration */
+#define PNX4008_DUM_T_CFG              0x1D    /* 29 HCLK cycles */
+
+/* DUM Sync count clock divider */
+#define PNX4008_DUM_CLK_DIV            0x02DD
+
+/* Memory size for framebuffer, allocated through dma_alloc_writecombine().
+ * Must be PAGE aligned
+ */
+#define FB_DMA_SIZE (PAGE_ALIGN(SZ_1M + PAGE_SIZE))
+
+#define OFFSET_RGBBUFFER (0xB0000)
+#define OFFSET_YUVBUFFER (0x00000)
+
+#define YUVBUFFER (lcd_video_start + OFFSET_YUVBUFFER)
+#define RGBBUFFER (lcd_video_start + OFFSET_RGBBUFFER)
+
+#define CMDSTRING_BASEADDR     (0x00C000)      /* iram */
+#define BYTES_PER_CMDSTRING    (0x80)
+#define NR_OF_CMDSTRINGS       (64)
+
+#define MAX_NR_PRESTRINGS (0x40)
+#define MAX_NR_POSTSTRINGS (0x40)
+
+/* various mask definitions */
+#define DUM_CLK_ENABLE 0x01
+#define DUM_CLK_DISABLE 0
+#define DUM_DECODE_MASK 0x1FFFFFFF
+#define DUM_CHANNEL_CFG_MASK 0x01FF
+#define DUM_CHANNEL_CFG_SYNC_MASK 0xFFFE00FF
+#define DUM_CHANNEL_CFG_SYNC_MASK_SET 0x0CA00
+
+#define SDUM_RETURNVAL_BASE (0x500)
+
+#define CONF_SYNC_OFF          (0x602)
+#define CONF_SYNC_ON           (0x603)
+
+#define CONF_DIRTYDETECTION_OFF        (0x600)
+#define CONF_DIRTYDETECTION_ON (0x601)
+
+/* Set the corresponding bit. */
+#define BIT(n) (0x1U << (n))
+
+struct dumchannel_uf {
+       int channelnr;
+       u32 *dirty;
+       u32 *source;
+       u32 x_offset;
+       u32 y_offset;
+       u32 width;
+       u32 height;
+};
+
+enum {
+       FB_TYPE_YUV,
+       FB_TYPE_RGB
+};
+
+struct cmdstring {
+       int channelnr;
+       uint16_t prestringlen;
+       uint16_t poststringlen;
+       uint16_t format;
+       uint16_t reserved;
+       uint16_t startaddr_low;
+       uint16_t startaddr_high;
+       uint16_t pixdatlen_low;
+       uint16_t pixdatlen_high;
+       u32 precmd[MAX_NR_PRESTRINGS];
+       u32 postcmd[MAX_NR_POSTSTRINGS];
+
+};
+
+struct dumchannel {
+       int channelnr;
+       int dum_ch_min;
+       int dum_ch_max;
+       int dum_ch_conf;
+       int dum_ch_stat;
+       int dum_ch_ctrl;
+};
+
+int pnx4008_alloc_dum_channel(int dev_id);
+int pnx4008_free_dum_channel(int channr, int dev_id);
+
+int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id);
+int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id);
+
+int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id);
+int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id);
+
+int pnx4008_force_dum_update_channel(int channr, int dev_id);
+
+int pnx4008_get_dum_channel_config(int channr, int dev_id);
+
+int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev);
+int pnx4008_set_dum_exit_notification(int dev_id);
+
+int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
+                            dma_addr_t * phys_addr, int *fb_length);
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
new file mode 100644 (file)
index 0000000..299e274
--- /dev/null
@@ -0,0 +1,947 @@
+/*
+ *     dscore.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/usb.h>
+
+#include "../w1_int.h"
+#include "../w1.h"
+
+/* COMMAND TYPE CODES */
+#define CONTROL_CMD                    0x00
+#define COMM_CMD                       0x01
+#define MODE_CMD                       0x02
+
+/* CONTROL COMMAND CODES */
+#define CTL_RESET_DEVICE               0x0000
+#define CTL_START_EXE                  0x0001
+#define CTL_RESUME_EXE                 0x0002
+#define CTL_HALT_EXE_IDLE              0x0003
+#define CTL_HALT_EXE_DONE              0x0004
+#define CTL_FLUSH_COMM_CMDS            0x0007
+#define CTL_FLUSH_RCV_BUFFER           0x0008
+#define CTL_FLUSH_XMT_BUFFER           0x0009
+#define CTL_GET_COMM_CMDS              0x000A
+
+/* MODE COMMAND CODES */
+#define MOD_PULSE_EN                   0x0000
+#define MOD_SPEED_CHANGE_EN            0x0001
+#define MOD_1WIRE_SPEED                        0x0002
+#define MOD_STRONG_PU_DURATION         0x0003
+#define MOD_PULLDOWN_SLEWRATE          0x0004
+#define MOD_PROG_PULSE_DURATION                0x0005
+#define MOD_WRITE1_LOWTIME             0x0006
+#define MOD_DSOW0_TREC                 0x0007
+
+/* COMMUNICATION COMMAND CODES */
+#define COMM_ERROR_ESCAPE              0x0601
+#define COMM_SET_DURATION              0x0012
+#define COMM_BIT_IO                    0x0020
+#define COMM_PULSE                     0x0030
+#define COMM_1_WIRE_RESET              0x0042
+#define COMM_BYTE_IO                   0x0052
+#define COMM_MATCH_ACCESS              0x0064
+#define COMM_BLOCK_IO                  0x0074
+#define COMM_READ_STRAIGHT             0x0080
+#define COMM_DO_RELEASE                        0x6092
+#define COMM_SET_PATH                  0x00A2
+#define COMM_WRITE_SRAM_PAGE           0x00B2
+#define COMM_WRITE_EPROM               0x00C4
+#define COMM_READ_CRC_PROT_PAGE                0x00D4
+#define COMM_READ_REDIRECT_PAGE_CRC    0x21E4
+#define COMM_SEARCH_ACCESS             0x00F4
+
+/* Communication command bits */
+#define COMM_TYPE                      0x0008
+#define COMM_SE                                0x0008
+#define COMM_D                         0x0008
+#define COMM_Z                         0x0008
+#define COMM_CH                                0x0008
+#define COMM_SM                                0x0008
+#define COMM_R                         0x0008
+#define COMM_IM                                0x0001
+
+#define COMM_PS                                0x4000
+#define COMM_PST                       0x4000
+#define COMM_CIB                       0x4000
+#define COMM_RTS                       0x4000
+#define COMM_DT                                0x2000
+#define COMM_SPU                       0x1000
+#define COMM_F                         0x0800
+#define COMM_NTP                       0x0400
+#define COMM_ICP                       0x0200
+#define COMM_RST                       0x0100
+
+#define PULSE_PROG                     0x01
+#define PULSE_SPUE                     0x02
+
+#define BRANCH_MAIN                    0xCC
+#define BRANCH_AUX                     0x33
+
+/*
+ * Duration of the strong pull-up pulse in milliseconds.
+ */
+#define PULLUP_PULSE_DURATION          750
+
+/* Status flags */
+#define ST_SPUA                                0x01  /* Strong Pull-up is active */
+#define ST_PRGA                                0x02  /* 12V programming pulse is being generated */
+#define ST_12VP                                0x04  /* external 12V programming voltage is present */
+#define ST_PMOD                                0x08  /* DS2490 powered from USB and external sources */
+#define ST_HALT                                0x10  /* DS2490 is currently halted */
+#define ST_IDLE                                0x20  /* DS2490 is currently idle */
+#define ST_EPOF                                0x80
+
+#define SPEED_NORMAL                   0x00
+#define SPEED_FLEXIBLE                 0x01
+#define SPEED_OVERDRIVE                        0x02
+
+#define NUM_EP                         4
+#define EP_CONTROL                     0
+#define EP_STATUS                      1
+#define EP_DATA_OUT                    2
+#define EP_DATA_IN                     3
+
+struct ds_device
+{
+       struct list_head        ds_entry;
+
+       struct usb_device       *udev;
+       struct usb_interface    *intf;
+
+       int                     ep[NUM_EP];
+
+       struct w1_bus_master    master;
+};
+
+struct ds_status
+{
+       u8                      enable;
+       u8                      speed;
+       u8                      pullup_dur;
+       u8                      ppuls_dur;
+       u8                      pulldown_slew;
+       u8                      write1_time;
+       u8                      write0_time;
+       u8                      reserved0;
+       u8                      status;
+       u8                      command0;
+       u8                      command1;
+       u8                      command_buffer_status;
+       u8                      data_out_buffer_status;
+       u8                      data_in_buffer_status;
+       u8                      reserved1;
+       u8                      reserved2;
+
+};
+
+static struct usb_device_id ds_id_table [] = {
+       { USB_DEVICE(0x04fa, 0x2490) },
+       { },
+};
+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);
+
+static LIST_HEAD(ds_devices);
+static DEFINE_MUTEX(ds_mutex);
+
+static struct usb_driver ds_driver = {
+       .name =         "DS9490R",
+       .probe =        ds_probe,
+       .disconnect =   ds_disconnect,
+       .id_table =     ds_id_table,
+};
+
+static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
+{
+       int err;
+
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+                       CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
+                               value, index, err);
+               return err;
+       }
+
+       return err;
+}
+#if 0
+static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
+{
+       int err;
+
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+                       MODE_CMD, 0x40, value, index, NULL, 0, 1000);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
+                               value, index, err);
+               return err;
+       }
+
+       return err;
+}
+#endif
+static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
+{
+       int err;
+
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+                       COMM_CMD, 0x40, value, index, NULL, 0, 1000);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
+                               value, index, err);
+               return err;
+       }
+
+       return err;
+}
+
+static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
+{
+       printk("%45s: %8x\n", str, buf[off]);
+}
+
+static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+                                unsigned char *buf, int size)
+{
+       int count, err;
+
+       memset(st, 0, sizeof(st));
+
+       count = 0;
+       err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
+               return err;
+       }
+
+       if (count >= sizeof(*st))
+               memcpy(st, buf, sizeof(*st));
+
+       return count;
+}
+
+static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+{
+       unsigned char buf[64];
+       int count, err = 0, i;
+
+       memcpy(st, buf, sizeof(*st));
+
+       count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+       if (count < 0)
+               return err;
+
+       printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+       for (i=0; i<count; ++i)
+               printk("%02x ", buf[i]);
+       printk("\n");
+
+       if (count >= 16) {
+               ds_dump_status(buf, "enable flag", 0);
+               ds_dump_status(buf, "1-wire speed", 1);
+               ds_dump_status(buf, "strong pullup duration", 2);
+               ds_dump_status(buf, "programming pulse duration", 3);
+               ds_dump_status(buf, "pulldown slew rate control", 4);
+               ds_dump_status(buf, "write-1 low time", 5);
+               ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
+               ds_dump_status(buf, "reserved (test register)", 7);
+               ds_dump_status(buf, "device status flags", 8);
+               ds_dump_status(buf, "communication command byte 1", 9);
+               ds_dump_status(buf, "communication command byte 2", 10);
+               ds_dump_status(buf, "communication command buffer status", 11);
+               ds_dump_status(buf, "1-wire data output buffer status", 12);
+               ds_dump_status(buf, "1-wire data input buffer status", 13);
+               ds_dump_status(buf, "reserved", 14);
+               ds_dump_status(buf, "reserved", 15);
+       }
+
+       memcpy(st, buf, sizeof(*st));
+
+       if (st->status & ST_EPOF) {
+               printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+               err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+               if (err)
+                       return err;
+               count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+               if (count < 0)
+                       return err;
+       }
+#if 0
+       if (st->status & ST_IDLE) {
+               printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
+               err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+               if (err)
+                       return err;
+       }
+#endif
+
+       return err;
+}
+
+static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+{
+       int count, err;
+       struct ds_status st;
+
+       count = 0;
+       err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+                               buf, size, &count, 1000);
+       if (err < 0) {
+               printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+               usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+               ds_recv_status(dev, &st);
+               return err;
+       }
+
+#if 0
+       {
+               int i;
+
+               printk("%s: count=%d: ", __func__, count);
+               for (i=0; i<count; ++i)
+                       printk("%02x ", buf[i]);
+               printk("\n");
+       }
+#endif
+       return count;
+}
+
+static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+{
+       int count, err;
+
+       count = 0;
+       err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
+       if (err < 0) {
+               printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+               return err;
+       }
+
+       return err;
+}
+
+#if 0
+
+int ds_stop_pulse(struct ds_device *dev, int limit)
+{
+       struct ds_status st;
+       int count = 0, err = 0;
+       u8 buf[0x20];
+
+       do {
+               err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+               if (err)
+                       break;
+               err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+               if (err)
+                       break;
+               err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+               if (err)
+                       break;
+
+               if ((st.status & ST_SPUA) == 0) {
+                       err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
+                       if (err)
+                               break;
+               }
+       } while(++count < limit);
+
+       return err;
+}
+
+int ds_detect(struct ds_device *dev, struct ds_status *st)
+{
+       int err;
+
+       err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+       if (err)
+               return err;
+
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
+       if (err)
+               return err;
+
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
+       if (err)
+               return err;
+
+       err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
+       if (err)
+               return err;
+
+       err = ds_recv_status(dev, st);
+
+       return err;
+}
+
+#endif  /*  0  */
+
+static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+{
+       u8 buf[0x20];
+       int err, count = 0;
+
+       do {
+               err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+#if 0
+               if (err >= 0) {
+                       int i;
+                       printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+                       for (i=0; i<err; ++i)
+                               printk("%02x ", buf[i]);
+                       printk("\n");
+               }
+#endif
+       } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+
+
+       if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
+               ds_recv_status(dev, st);
+               return -1;
+       } else
+               return 0;
+}
+
+static int ds_reset(struct ds_device *dev, struct ds_status *st)
+{
+       int err;
+
+       //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
+       err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, st);
+#if 0
+       if (st->command_buffer_status) {
+               printk(KERN_INFO "Short circuit.\n");
+               return -EIO;
+       }
+#endif
+
+       return 0;
+}
+
+#if 0
+static int ds_set_speed(struct ds_device *dev, int speed)
+{
+       int err;
+
+       if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
+               return -EINVAL;
+
+       if (speed != SPEED_OVERDRIVE)
+               speed = SPEED_FLEXIBLE;
+
+       speed &= 0xff;
+
+       err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
+       if (err)
+               return err;
+
+       return err;
+}
+#endif  /*  0  */
+
+static int ds_start_pulse(struct ds_device *dev, int delay)
+{
+       int err;
+       u8 del = 1 + (u8)(delay >> 4);
+       struct ds_status st;
+
+#if 0
+       err = ds_stop_pulse(dev, 10);
+       if (err)
+               return err;
+
+       err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+       if (err)
+               return err;
+#endif
+       err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
+       if (err)
+               return err;
+
+       err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
+       if (err)
+               return err;
+
+       mdelay(delay);
+
+       ds_wait_status(dev, &st);
+
+       return err;
+}
+
+static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
+{
+       int err, count;
+       struct ds_status st;
+       u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
+       u16 cmd;
+
+       err = ds_send_control(dev, value, 0);
+       if (err)
+               return err;
+
+       count = 0;
+       do {
+               err = ds_wait_status(dev, &st);
+               if (err)
+                       return err;
+
+               cmd = st.command0 | (st.command1 << 8);
+       } while (cmd != value && ++count < 10);
+
+       if (err < 0 || count >= 10) {
+               printk(KERN_ERR "Failed to obtain status.\n");
+               return -EINVAL;
+       }
+
+       err = ds_recv_data(dev, tbit, sizeof(*tbit));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+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);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       return 0;
+}
+
+static int ds_write_byte(struct ds_device *dev, u8 byte)
+{
+       int err;
+       struct ds_status st;
+       u8 rbyte;
+
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+       if (err)
+               return err;
+
+       err = ds_wait_status(dev, &st);
+       if (err)
+               return err;
+
+       err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+       if (err < 0)
+               return err;
+
+       ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+
+       return !(byte == rbyte);
+}
+
+static int ds_read_byte(struct ds_device *dev, u8 *byte)
+{
+       int err;
+       struct ds_status st;
+
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       err = ds_recv_data(dev, byte, sizeof(*byte));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+{
+       struct ds_status st;
+       int err;
+
+       if (len > 64*1024)
+               return -E2BIG;
+
+       memset(buf, 0xFF, len);
+
+       err = ds_send_data(dev, buf, len);
+       if (err < 0)
+               return err;
+
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       memset(buf, 0x00, len);
+       err = ds_recv_data(dev, buf, len);
+
+       return err;
+}
+
+static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
+{
+       int err;
+       struct ds_status st;
+
+       err = ds_send_data(dev, buf, len);
+       if (err < 0)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       err = ds_recv_data(dev, buf, len);
+       if (err < 0)
+               return err;
+
+       ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+
+       return !(err == len);
+}
+
+#if 0
+
+static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+{
+       int err;
+       u16 value, index;
+       struct ds_status st;
+
+       memset(buf, 0, sizeof(buf));
+
+       err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
+       if (err)
+               return err;
+
+       ds_wait_status(ds_dev, &st);
+
+       value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
+       index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
+       err = ds_send_control(ds_dev, value, index);
+       if (err)
+               return err;
+
+       ds_wait_status(ds_dev, &st);
+
+       err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
+       if (err < 0)
+               return err;
+
+       return err/8;
+}
+
+static int ds_match_access(struct ds_device *dev, u64 init)
+{
+       int err;
+       struct ds_status st;
+
+       err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       return 0;
+}
+
+static int ds_set_path(struct ds_device *dev, u64 init)
+{
+       int err;
+       struct ds_status st;
+       u8 buf[9];
+
+       memcpy(buf, &init, 8);
+       buf[8] = BRANCH_MAIN;
+
+       err = ds_send_data(dev, buf, sizeof(buf));
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
+       if (err)
+               return err;
+
+       ds_wait_status(dev, &st);
+
+       return 0;
+}
+
+#endif  /*  0  */
+
+static u8 ds9490r_touch_bit(void *data, u8 bit)
+{
+       u8 ret;
+       struct ds_device *dev = data;
+
+       if (ds_touch_bit(dev, bit, &ret))
+               return 0;
+
+       return ret;
+}
+
+static void ds9490r_write_bit(void *data, u8 bit)
+{
+       struct ds_device *dev = data;
+
+       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;
+       int err;
+       u8 bit = 0;
+
+       err = ds_touch_bit(dev, 1, &bit);
+       if (err)
+               return 0;
+
+       return bit & 1;
+}
+
+static u8 ds9490r_read_byte(void *data)
+{
+       struct ds_device *dev = data;
+       int err;
+       u8 byte = 0;
+
+       err = ds_read_byte(dev, &byte);
+       if (err)
+               return 0;
+
+       return byte;
+}
+
+static void ds9490r_write_block(void *data, const u8 *buf, int len)
+{
+       struct ds_device *dev = data;
+
+       ds_write_block(dev, (u8 *)buf, len);
+}
+
+static u8 ds9490r_read_block(void *data, u8 *buf, int len)
+{
+       struct ds_device *dev = data;
+       int err;
+
+       err = ds_read_block(dev, buf, len);
+       if (err < 0)
+               return 0;
+
+       return 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);
+       if (err)
+               return 1;
+
+       return 0;
+}
+
+static int ds_w1_init(struct ds_device *dev)
+{
+       memset(&dev->master, 0, sizeof(struct w1_bus_master));
+
+       dev->master.data        = dev;
+       dev->master.touch_bit   = &ds9490r_touch_bit;
+       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;
+
+       return w1_add_master_device(&dev->master);
+}
+
+static void ds_w1_fini(struct ds_device *dev)
+{
+       w1_remove_master_device(&dev->master);
+}
+
+static int ds_probe(struct usb_interface *intf,
+                   const struct usb_device_id *udev_id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_endpoint_descriptor *endpoint;
+       struct usb_host_interface *iface_desc;
+       struct ds_device *dev;
+       int i, err;
+
+       dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+       if (!dev) {
+               printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
+               return -ENOMEM;
+       }
+       dev->udev = usb_get_dev(udev);
+       if (!dev->udev) {
+               err = -ENOMEM;
+               goto err_out_free;
+       }
+       memset(dev->ep, 0, sizeof(dev->ep));
+
+       usb_set_intfdata(intf, dev);
+
+       err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+       if (err) {
+               printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
+                               intf->altsetting[0].desc.bInterfaceNumber, err);
+               goto err_out_clear;
+       }
+
+       err = usb_reset_configuration(dev->udev);
+       if (err) {
+               printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+               goto err_out_clear;
+       }
+
+       iface_desc = &intf->altsetting[0];
+       if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+               printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
+               err = -EINVAL;
+               goto err_out_clear;
+       }
+
+       /*
+        * This loop doesn'd show control 0 endpoint,
+        * so we will fill only 1-3 endpoints entry.
+        */
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               dev->ep[i+1] = endpoint->bEndpointAddress;
+#if 0
+               printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
+                       i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
+                       (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
+                       endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+#endif
+       }
+
+       err = ds_w1_init(dev);
+       if (err)
+               goto err_out_clear;
+
+       mutex_lock(&ds_mutex);
+       list_add_tail(&dev->ds_entry, &ds_devices);
+       mutex_unlock(&ds_mutex);
+
+       return 0;
+
+err_out_clear:
+       usb_set_intfdata(intf, NULL);
+       usb_put_dev(dev->udev);
+err_out_free:
+       kfree(dev);
+       return err;
+}
+
+static void ds_disconnect(struct usb_interface *intf)
+{
+       struct ds_device *dev;
+
+       dev = usb_get_intfdata(intf);
+       if (!dev)
+               return;
+
+       mutex_lock(&ds_mutex);
+       list_del(&dev->ds_entry);
+       mutex_unlock(&ds_mutex);
+
+       ds_w1_fini(dev);
+
+       usb_set_intfdata(intf, NULL);
+
+       usb_put_dev(dev->udev);
+       kfree(dev);
+}
+
+static int ds_init(void)
+{
+       int err;
+
+       err = usb_register(&ds_driver);
+       if (err) {
+               printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void ds_fini(void)
+{
+       usb_deregister(&ds_driver);
+}
+
+module_init(ds_init);
+module_exit(ds_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)");
diff --git a/drivers/xen/blktap/blktapmain.c b/drivers/xen/blktap/blktapmain.c
new file mode 100644 (file)
index 0000000..15b368b
--- /dev/null
@@ -0,0 +1,1393 @@
+/******************************************************************************
+ * drivers/xen/blktap/blktap.c
+ * 
+ * Back-end driver for user level virtual block devices. This portion of the
+ * driver exports a 'unified' block-device interface that can be accessed
+ * by any operating system that implements a compatible front end. Requests
+ * are remapped to a user-space memory region.
+ *
+ * Based on the blkback driver code.
+ * 
+ * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <asm/hypervisor.h>
+#include "common.h"
+#include <xen/balloon.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/gfp.h>
+#include <linux/poll.h>
+#include <asm/tlbflush.h>
+
+#define MAX_TAP_DEV 100     /*the maximum number of tapdisk ring devices    */
+#define MAX_DEV_NAME 100    /*the max tapdisk ring device name e.g. blktap0 */
+
+
+struct class *xen_class;
+EXPORT_SYMBOL_GPL(xen_class);
+
+/*
+ * Setup the xen class.  This should probably go in another file, but
+ * since blktap is the only user of it so far, it gets to keep it.
+ */
+int setup_xen_class(void)
+{
+       int ret;
+
+       if (xen_class)
+               return 0;
+
+       xen_class = class_create(THIS_MODULE, "xen");
+       if ((ret = IS_ERR(xen_class))) {
+               xen_class = NULL;
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * The maximum number of requests that can be outstanding at any time
+ * is determined by 
+ *
+ *   [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] 
+ *
+ * where mmap_alloc < MAX_DYNAMIC_MEM.
+ *
+ * TODO:
+ * mmap_alloc is initialised to 2 and should be adjustable on the fly via
+ * sysfs.
+ */
+#define MAX_DYNAMIC_MEM 64
+#define MAX_PENDING_REQS 64   
+#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req,_seg)                                   \
+        (_start +                                                       \
+         ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +        \
+         ((_seg) * PAGE_SIZE))
+static int blkif_reqs = MAX_PENDING_REQS;
+static int mmap_pages = MMAP_PAGES;
+
+#define RING_PAGES 1 /* BLKTAP - immediately before the mmap area, we
+                     * have a bunch of pages reserved for shared
+                     * memory rings.
+                     */
+
+/*Data struct associated with each of the tapdisk devices*/
+typedef struct tap_blkif {
+       struct vm_area_struct *vma;   /*Shared memory area                   */
+       unsigned long rings_vstart;   /*Kernel memory mapping                */
+       unsigned long user_vstart;    /*User memory mapping                  */
+       unsigned long dev_inuse;      /*One process opens device at a time.  */
+       unsigned long dev_pending;    /*In process of being opened           */
+       unsigned long ring_ok;        /*make this ring->state                */
+       blkif_front_ring_t ufe_ring;  /*Rings up to user space.              */
+       wait_queue_head_t wait;       /*for poll                             */
+       unsigned long mode;           /*current switching mode               */
+       int minor;                    /*Minor number for tapdisk device      */
+       pid_t pid;                    /*tapdisk process id                   */
+       enum { RUNNING, CLEANSHUTDOWN } status; /*Detect a clean userspace 
+                                                 shutdown                   */
+       unsigned long *idx_map;       /*Record the user ring id to kern 
+                                       [req id, idx] tuple                  */
+       blkif_t *blkif;               /*Associate blkif with tapdev          */
+       int sysfs_set;                /*Set if it has a class device.        */
+} tap_blkif_t;
+
+/*Data struct handed back to userspace for tapdisk device to VBD mapping*/
+typedef struct domid_translate {
+       unsigned short domid;
+       unsigned short busid;
+} domid_translate_t ;
+
+static domid_translate_t  translate_domid[MAX_TAP_DEV];
+static tap_blkif_t *tapfds[MAX_TAP_DEV];
+
+static int __init set_blkif_reqs(char *str)
+{
+       get_option(&str, &blkif_reqs);
+       return 1;
+}
+__setup("blkif_reqs=", set_blkif_reqs);
+
+/* Run-time switchable: /sys/module/blktap/parameters/ */
+static unsigned int log_stats = 0;
+static unsigned int debug_lvl = 0;
+module_param(log_stats, int, 0644);
+module_param(debug_lvl, int, 0644);
+
+/*
+ * Each outstanding request that we've passed to the lower device layers has a 
+ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
+ * the pendcnt towards zero. When it hits zero, the specified domain has a 
+ * response queued for it, with the saved 'id' passed back.
+ */
+typedef struct {
+       blkif_t       *blkif;
+       unsigned long  id;
+       unsigned short mem_idx;
+       int            nr_pages;
+       atomic_t       pendcnt;
+       unsigned short operation;
+       int            status;
+       struct list_head free_list;
+       int            inuse;
+} pending_req_t;
+
+static pending_req_t *pending_reqs[MAX_PENDING_REQS];
+static struct list_head pending_free;
+static DEFINE_SPINLOCK(pending_free_lock);
+static DECLARE_WAIT_QUEUE_HEAD (pending_free_wq);
+static int alloc_pending_reqs;
+
+typedef unsigned int PEND_RING_IDX;
+
+static inline int MASK_PEND_IDX(int i) { 
+       return (i & (MAX_PENDING_REQS-1));
+}
+
+static inline unsigned int RTN_PEND_IDX(pending_req_t *req, int idx) {
+       return (req - pending_reqs[idx]);
+}
+
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+#define BLKBACK_INVALID_HANDLE (~0)
+
+static struct page **foreign_pages[MAX_DYNAMIC_MEM];
+static inline unsigned long idx_to_kaddr(
+       unsigned int mmap_idx, unsigned int req_idx, unsigned int sg_idx)
+{
+       unsigned int arr_idx = req_idx*BLKIF_MAX_SEGMENTS_PER_REQUEST + sg_idx;
+       unsigned long pfn = page_to_pfn(foreign_pages[mmap_idx][arr_idx]);
+       return (unsigned long)pfn_to_kaddr(pfn);
+}
+
+static unsigned short mmap_alloc = 0;
+static unsigned short mmap_lock = 0;
+static unsigned short mmap_inuse = 0;
+
+/******************************************************************
+ * GRANT HANDLES
+ */
+
+/* When using grant tables to map a frame for device access then the
+ * handle returned must be used to unmap the frame. This is needed to
+ * drop the ref count on the frame.
+ */
+struct grant_handle_pair
+{
+        grant_handle_t kernel;
+        grant_handle_t user;
+};
+
+static struct grant_handle_pair 
+    pending_grant_handles[MAX_DYNAMIC_MEM][MMAP_PAGES];
+#define pending_handle(_id, _idx, _i) \
+    (pending_grant_handles[_id][((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) \
+    + (_i)])
+
+
+static int blktap_read_ufe_ring(tap_blkif_t *info); /*local prototypes*/
+
+#define BLKTAP_MINOR 0  /*/dev/xen/blktap has a dynamic major */
+#define BLKTAP_DEV_DIR  "/dev/xen"
+
+static int blktap_major;
+
+/* blktap IOCTLs: */
+#define BLKTAP_IOCTL_KICK_FE         1
+#define BLKTAP_IOCTL_KICK_BE         2 /* currently unused */
+#define BLKTAP_IOCTL_SETMODE         3
+#define BLKTAP_IOCTL_SENDPID        4
+#define BLKTAP_IOCTL_NEWINTF        5
+#define BLKTAP_IOCTL_MINOR          6
+#define BLKTAP_IOCTL_MAJOR          7
+#define BLKTAP_QUERY_ALLOC_REQS      8
+#define BLKTAP_IOCTL_FREEINTF        9
+#define BLKTAP_IOCTL_PRINT_IDXS      100  
+
+/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */
+#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
+#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
+#define BLKTAP_MODE_INTERCEPT_BE     0x00000002  /* unimp.             */
+
+#define BLKTAP_MODE_INTERPOSE \
+           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
+
+
+static inline int BLKTAP_MODE_VALID(unsigned long arg)
+{
+       return ((arg == BLKTAP_MODE_PASSTHROUGH ) ||
+               (arg == BLKTAP_MODE_INTERCEPT_FE) ||
+                (arg == BLKTAP_MODE_INTERPOSE   ));
+}
+
+/* Requests passing through the tap to userspace are re-assigned an ID.
+ * We must record a mapping between the BE [IDX,ID] tuple and the userspace
+ * ring ID. 
+ */
+
+static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
+{
+        return ((fe_dom << 16) | MASK_PEND_IDX(idx));
+}
+
+extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id)
+{
+        return (PEND_RING_IDX)(id & 0x0000ffff);
+}
+
+extern inline int ID_TO_MIDX(unsigned long id)
+{
+        return (int)(id >> 16);
+}
+
+#define INVALID_REQ 0xdead0000
+
+/*TODO: Convert to a free list*/
+static inline int GET_NEXT_REQ(unsigned long *idx_map)
+{
+       int i;
+       for (i = 0; i < MAX_PENDING_REQS; i++)
+               if (idx_map[i] == INVALID_REQ)
+                       return i;
+
+       return INVALID_REQ;
+}
+
+
+#define BLKTAP_INVALID_HANDLE(_g) \
+    (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF))
+
+#define BLKTAP_INVALIDATE_HANDLE(_g) do {       \
+    (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \
+    } while(0)
+
+
+/******************************************************************
+ * BLKTAP VM OPS
+ */
+
+static struct page *blktap_nopage(struct vm_area_struct *vma,
+                                 unsigned long address,
+                                 int *type)
+{
+       /*
+        * if the page has not been mapped in by the driver then return
+        * NOPAGE_SIGBUS to the domain.
+        */
+
+       return NOPAGE_SIGBUS;
+}
+
+struct vm_operations_struct blktap_vm_ops = {
+       nopage:   blktap_nopage,
+};
+
+/******************************************************************
+ * BLKTAP FILE OPS
+ */
+/*Function Declarations*/
+static int get_next_free_dev(void);
+static int blktap_open(struct inode *inode, struct file *filp);
+static int blktap_release(struct inode *inode, struct file *filp);
+static int blktap_mmap(struct file *filp, struct vm_area_struct *vma);
+static int blktap_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg);
+static unsigned int blktap_poll(struct file *file, poll_table *wait);
+
+static struct file_operations blktap_fops = {
+       .owner   = THIS_MODULE,
+       .poll    = blktap_poll,
+       .ioctl   = blktap_ioctl,
+       .open    = blktap_open,
+       .release = blktap_release,
+       .mmap    = blktap_mmap,
+};
+
+
+static int get_next_free_dev(void)
+{
+       tap_blkif_t *info;
+       int i = 0, ret = -1;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pending_free_lock, flags);
+       
+       while (i < MAX_TAP_DEV) {
+               info = tapfds[i];
+               if ( (tapfds[i] != NULL) && (info->dev_inuse == 0)
+                       && (info->dev_pending == 0) ) {
+                       info->dev_pending = 1;
+                       ret = i;
+                       goto done;
+               }
+               i++;
+       }
+       
+done:
+       spin_unlock_irqrestore(&pending_free_lock, flags);
+
+       /*
+        * We are protected by having the dev_pending set.
+        */
+       if (!tapfds[i]->sysfs_set && xen_class) {
+               class_device_create(xen_class, NULL,
+                                   MKDEV(blktap_major, ret), NULL,
+                                   "blktap%d", ret);
+               tapfds[i]->sysfs_set = 1;
+       }
+       return ret;
+}
+
+int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif) 
+{
+       int i;
+               
+       for (i = 0; i < MAX_TAP_DEV; i++)
+               if ( (translate_domid[i].domid == domid)
+                   && (translate_domid[i].busid == xenbus_id) ) {
+                       tapfds[i]->blkif = blkif;
+                       tapfds[i]->status = RUNNING;
+                       return i;
+               }
+       return -1;
+}
+
+void signal_tapdisk(int idx) 
+{
+       tap_blkif_t *info;
+       struct task_struct *ptask;
+
+       info = tapfds[idx];
+       if ( (idx > 0) && (idx < MAX_TAP_DEV) && (info->pid > 0) ) {
+               ptask = find_task_by_pid(info->pid);
+               if (ptask)
+                       info->status = CLEANSHUTDOWN;
+       }
+       info->blkif = NULL;
+       return;
+}
+
+static int blktap_open(struct inode *inode, struct file *filp)
+{
+       blkif_sring_t *sring;
+       int idx = iminor(inode) - BLKTAP_MINOR;
+       tap_blkif_t *info;
+       int i;
+       
+       if (tapfds[idx] == NULL) {
+               WPRINTK("Unable to open device /dev/xen/blktap%d\n",
+                      idx);
+               return -ENOMEM;
+       }
+       DPRINTK("Opening device /dev/xen/blktap%d\n",idx);
+       
+       info = tapfds[idx];
+       
+       /*Only one process can access device at a time*/
+       if (test_and_set_bit(0, &info->dev_inuse))
+               return -EBUSY;
+
+       info->dev_pending = 0;
+           
+       /* Allocate the fe ring. */
+       sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+       if (sring == NULL)
+               goto fail_nomem;
+
+       SetPageReserved(virt_to_page(sring));
+    
+       SHARED_RING_INIT(sring);
+       FRONT_RING_INIT(&info->ufe_ring, sring, PAGE_SIZE);
+       
+       filp->private_data = info;
+       info->vma = NULL;
+
+       info->idx_map = kmalloc(sizeof(unsigned long) * MAX_PENDING_REQS, 
+                               GFP_KERNEL);
+       
+       if (idx > 0) {
+               init_waitqueue_head(&info->wait);
+               for (i = 0; i < MAX_PENDING_REQS; i++) 
+                       info->idx_map[i] = INVALID_REQ;
+       }
+
+       DPRINTK("Tap open: device /dev/xen/blktap%d\n",idx);
+       return 0;
+
+ fail_nomem:
+       return -ENOMEM;
+}
+
+static int blktap_release(struct inode *inode, struct file *filp)
+{
+       tap_blkif_t *info = filp->private_data;
+       
+       /* can this ever happen? - sdr */
+       if (!info) {
+               WPRINTK("Trying to free device that doesn't exist "
+                      "[/dev/xen/blktap%d]\n",iminor(inode) - BLKTAP_MINOR);
+               return -EBADF;
+       }
+       info->dev_inuse = 0;
+       DPRINTK("Freeing device [/dev/xen/blktap%d]\n",info->minor);
+
+       /* Free the ring page. */
+       ClearPageReserved(virt_to_page(info->ufe_ring.sring));
+       free_page((unsigned long) info->ufe_ring.sring);
+
+       /* Clear any active mappings and free foreign map table */
+       if (info->vma) {
+               zap_page_range(
+                       info->vma, info->vma->vm_start, 
+                       info->vma->vm_end - info->vma->vm_start, NULL);
+               info->vma = NULL;
+       }
+       
+       if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) {
+               kthread_stop(info->blkif->xenblkd);
+               info->blkif->xenblkd = NULL;
+               info->status = CLEANSHUTDOWN;
+       }       
+       return 0;
+}
+
+
+/* Note on mmap:
+ * We need to map pages to user space in a way that will allow the block
+ * subsystem set up direct IO to them.  This couldn't be done before, because
+ * there isn't really a sane way to translate a user virtual address down to a 
+ * physical address when the page belongs to another domain.
+ *
+ * My first approach was to map the page in to kernel memory, add an entry
+ * for it in the physical frame list (using alloc_lomem_region as in blkback)
+ * and then attempt to map that page up to user space.  This is disallowed
+ * by xen though, which realizes that we don't really own the machine frame
+ * underlying the physical page.
+ *
+ * The new approach is to provide explicit support for this in xen linux.
+ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
+ * mapped from other vms.  vma->vm_private_data is set up as a mapping 
+ * from pages to actual page structs.  There is a new clause in get_user_pages
+ * that does the right thing for this sort of mapping.
+ */
+static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       int size;
+       struct page **map;
+       int i;
+       tap_blkif_t *info = filp->private_data;
+
+       if (info == NULL) {
+               WPRINTK("blktap: mmap, retrieving idx failed\n");
+               return -ENOMEM;
+       }
+       
+       vma->vm_flags |= VM_RESERVED;
+       vma->vm_ops = &blktap_vm_ops;
+
+       size = vma->vm_end - vma->vm_start;
+       if (size != ((mmap_pages + RING_PAGES) << PAGE_SHIFT)) {
+               WPRINTK("you _must_ map exactly %d pages!\n",
+                      mmap_pages + RING_PAGES);
+               return -EAGAIN;
+       }
+
+       size >>= PAGE_SHIFT;
+       info->rings_vstart = vma->vm_start;
+       info->user_vstart  = info->rings_vstart + (RING_PAGES << PAGE_SHIFT);
+    
+       /* Map the ring pages to the start of the region and reserve it. */
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       if (remap_pfn_range(vma, vma->vm_start, 
+                           __pa(info->ufe_ring.sring) >> PAGE_SHIFT, 
+                           PAGE_SIZE, vma->vm_page_prot)) {
+               WPRINTK("Mapping user ring failed!\n");
+               goto fail;
+       }
+
+       /* Mark this VM as containing foreign pages, and set up mappings. */
+       map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
+                     * sizeof(struct page_struct*),
+                     GFP_KERNEL);
+       if (map == NULL) {
+               WPRINTK("Couldn't alloc VM_FOREIGN map.\n");
+               goto fail;
+       }
+
+       for (i = 0; i < ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
+               map[i] = NULL;
+    
+       vma->vm_private_data = map;
+       vma->vm_flags |= VM_FOREIGN;
+
+       info->vma = vma;
+       info->ring_ok = 1;
+       return 0;
+ fail:
+       /* Clear any active mappings. */
+       zap_page_range(vma, vma->vm_start, 
+                      vma->vm_end - vma->vm_start, NULL);
+
+       return -ENOMEM;
+}
+
+
+static int blktap_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg)
+{
+       tap_blkif_t *info = filp->private_data;
+
+       switch(cmd) {
+       case BLKTAP_IOCTL_KICK_FE: 
+       {
+               /* There are fe messages to process. */
+               return blktap_read_ufe_ring(info);
+       }
+       case BLKTAP_IOCTL_SETMODE:
+       {
+               if (info) {
+                       if (BLKTAP_MODE_VALID(arg)) {
+                               info->mode = arg;
+                               /* XXX: may need to flush rings here. */
+                               DPRINTK("blktap: set mode to %lx\n", 
+                                      arg);
+                               return 0;
+                       }
+               }
+               return 0;
+       }
+       case BLKTAP_IOCTL_PRINT_IDXS:
+        {
+               if (info) {
+                       printk("User Rings: \n-----------\n");
+                       printk("UF: rsp_cons: %2d, req_prod_prv: %2d "
+                               "| req_prod: %2d, rsp_prod: %2d\n",
+                               info->ufe_ring.rsp_cons,
+                               info->ufe_ring.req_prod_pvt,
+                               info->ufe_ring.sring->req_prod,
+                               info->ufe_ring.sring->rsp_prod);
+               }
+               return 0;
+        }
+       case BLKTAP_IOCTL_SENDPID:
+       {
+               if (info) {
+                       info->pid = (pid_t)arg;
+                       DPRINTK("blktap: pid received %d\n", 
+                              info->pid);
+               }
+               return 0;
+       }
+       case BLKTAP_IOCTL_NEWINTF:
+       {               
+               uint64_t val = (uint64_t)arg;
+               domid_translate_t *tr = (domid_translate_t *)&val;
+               int newdev;
+
+               DPRINTK("NEWINTF Req for domid %d and bus id %d\n", 
+                      tr->domid, tr->busid);
+               newdev = get_next_free_dev();
+               if (newdev < 1) {
+                       WPRINTK("Error initialising /dev/xen/blktap - "
+                               "No more devices\n");
+                       return -1;
+               }
+               translate_domid[newdev].domid = tr->domid;
+               translate_domid[newdev].busid = tr->busid;
+               return newdev;
+       }
+       case BLKTAP_IOCTL_FREEINTF:
+       {
+               unsigned long dev = arg;
+               unsigned long flags;
+
+               /* Looking at another device */
+               info = NULL;
+
+               if ( (dev > 0) && (dev < MAX_TAP_DEV) )
+                       info = tapfds[dev];
+
+               spin_lock_irqsave(&pending_free_lock, flags);
+               if ( (info != NULL) && (info->dev_pending) )
+                       info->dev_pending = 0;
+               spin_unlock_irqrestore(&pending_free_lock, flags);
+
+               return 0;
+       }
+       case BLKTAP_IOCTL_MINOR:
+       {
+               unsigned long dev = arg;
+
+               /* Looking at another device */
+               info = NULL;
+               
+               if ( (dev > 0) && (dev < MAX_TAP_DEV) )
+                       info = tapfds[dev];
+               
+               if (info != NULL)
+                       return info->minor;
+               else
+                       return -1;
+       }
+       case BLKTAP_IOCTL_MAJOR:
+               return blktap_major;
+
+       case BLKTAP_QUERY_ALLOC_REQS:
+       {
+               WPRINTK("BLKTAP_QUERY_ALLOC_REQS ioctl: %d/%d\n",
+                      alloc_pending_reqs, blkif_reqs);
+               return (alloc_pending_reqs/blkif_reqs) * 100;
+       }
+       }
+       return -ENOIOCTLCMD;
+}
+
+static unsigned int blktap_poll(struct file *filp, poll_table *wait)
+{
+       tap_blkif_t *info = filp->private_data;
+       
+       if (!info) {
+               WPRINTK(" poll, retrieving idx failed\n");
+               return 0;
+       }
+
+       /* do not work on the control device */
+       if (!info->minor)
+               return 0;
+
+       poll_wait(filp, &info->wait, wait);
+       if (info->ufe_ring.req_prod_pvt != info->ufe_ring.sring->req_prod) {
+               RING_PUSH_REQUESTS(&info->ufe_ring);
+               return POLLIN | POLLRDNORM;
+       }
+       return 0;
+}
+
+void blktap_kick_user(int idx)
+{
+       tap_blkif_t *info;
+
+       if (idx == 0)
+               return;
+       
+       info = tapfds[idx];
+       
+       if (info != NULL)
+               wake_up_interruptible(&info->wait);
+
+       return;
+}
+
+static int do_block_io_op(blkif_t *blkif);
+static void dispatch_rw_block_io(blkif_t *blkif,
+                                blkif_request_t *req,
+                                pending_req_t *pending_req);
+static void make_response(blkif_t *blkif, unsigned long id, 
+                          unsigned short op, int st);
+
+/******************************************************************
+ * misc small helpers
+ */
+static int req_increase(void)
+{
+       int i, j;
+
+       if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) 
+               return -EINVAL;
+
+       pending_reqs[mmap_alloc]  = kzalloc(sizeof(pending_req_t)
+                                           * blkif_reqs, GFP_KERNEL);
+       foreign_pages[mmap_alloc] = alloc_empty_pages_and_pagevec(mmap_pages);
+
+       if (!pending_reqs[mmap_alloc] || !foreign_pages[mmap_alloc])
+               goto out_of_memory;
+
+       DPRINTK("%s: reqs=%d, pages=%d\n",
+               __FUNCTION__, blkif_reqs, mmap_pages);
+
+       for (i = 0; i < MAX_PENDING_REQS; i++) {
+               list_add_tail(&pending_reqs[mmap_alloc][i].free_list, 
+                             &pending_free);
+               pending_reqs[mmap_alloc][i].mem_idx = mmap_alloc;
+               for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
+                       BLKTAP_INVALIDATE_HANDLE(&pending_handle(mmap_alloc, 
+                                                                i, j));
+       }
+
+       mmap_alloc++;
+       DPRINTK("# MMAPs increased to %d\n",mmap_alloc);
+       return 0;
+
+ out_of_memory:
+       free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
+       kfree(pending_reqs[mmap_alloc]);
+       WPRINTK("%s: out of memory\n", __FUNCTION__);
+       return -ENOMEM;
+}
+
+static void mmap_req_del(int mmap)
+{
+       BUG_ON(!spin_is_locked(&pending_free_lock));
+
+       kfree(pending_reqs[mmap]);
+       pending_reqs[mmap] = NULL;
+
+       free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
+       foreign_pages[mmap] = NULL;
+
+       mmap_lock = 0;
+       DPRINTK("# MMAPs decreased to %d\n",mmap_alloc);
+       mmap_alloc--;
+}
+
+static pending_req_t* alloc_req(void)
+{
+       pending_req_t *req = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pending_free_lock, flags);
+
+       if (!list_empty(&pending_free)) {
+               req = list_entry(pending_free.next, pending_req_t, free_list);
+               list_del(&req->free_list);
+       }
+
+       if (req) {
+               req->inuse = 1;
+               alloc_pending_reqs++;
+       }
+       spin_unlock_irqrestore(&pending_free_lock, flags);
+
+       return req;
+}
+
+static void free_req(pending_req_t *req)
+{
+       unsigned long flags;
+       int was_empty;
+
+       spin_lock_irqsave(&pending_free_lock, flags);
+
+       alloc_pending_reqs--;
+       req->inuse = 0;
+       if (mmap_lock && (req->mem_idx == mmap_alloc-1)) {
+               mmap_inuse--;
+               if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1);
+               spin_unlock_irqrestore(&pending_free_lock, flags);
+               return;
+       }
+       was_empty = list_empty(&pending_free);
+       list_add(&req->free_list, &pending_free);
+
+       spin_unlock_irqrestore(&pending_free_lock, flags);
+
+       if (was_empty)
+               wake_up(&pending_free_wq);
+}
+
+static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx, int 
+                           tapidx)
+{
+       struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+       unsigned int i, invcount = 0;
+       struct grant_handle_pair *khandle;
+       uint64_t ptep;
+       int ret, mmap_idx;
+       unsigned long kvaddr, uvaddr;
+
+       tap_blkif_t *info = tapfds[tapidx];
+       
+       if (info == NULL) {
+               WPRINTK("fast_flush: Couldn't get info!\n");
+               return;
+       }
+       mmap_idx = req->mem_idx;
+
+       for (i = 0; i < req->nr_pages; i++) {
+               kvaddr = idx_to_kaddr(mmap_idx, k_idx, i);
+               uvaddr = MMAP_VADDR(info->user_vstart, u_idx, i);
+
+               khandle = &pending_handle(mmap_idx, k_idx, i);
+               if (BLKTAP_INVALID_HANDLE(khandle)) {
+                       WPRINTK("BLKTAP_INVALID_HANDLE\n");
+                       continue;
+               }
+               gnttab_set_unmap_op(&unmap[invcount], 
+                                   idx_to_kaddr(mmap_idx, k_idx, i), 
+                                   GNTMAP_host_map, khandle->kernel);
+               invcount++;
+
+               if (create_lookup_pte_addr(
+                   info->vma->vm_mm,
+                   MMAP_VADDR(info->user_vstart, u_idx, i), 
+                   &ptep) !=0) {
+                       WPRINTK("Couldn't get a pte addr!\n");
+                       return;
+               }
+
+               gnttab_set_unmap_op(&unmap[invcount], 
+                       ptep, GNTMAP_host_map,
+                       khandle->user);
+               invcount++;
+            
+               BLKTAP_INVALIDATE_HANDLE(khandle);
+       }
+       ret = HYPERVISOR_grant_table_op(
+               GNTTABOP_unmap_grant_ref, unmap, invcount);
+       BUG_ON(ret);
+       
+       if (info->vma != NULL)
+               zap_page_range(info->vma, 
+                              MMAP_VADDR(info->user_vstart, u_idx, 0), 
+                              req->nr_pages << PAGE_SHIFT, NULL);
+}
+
+/******************************************************************
+ * SCHEDULER FUNCTIONS
+ */
+
+static void print_stats(blkif_t *blkif)
+{
+       printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d\n",
+              current->comm, blkif->st_oo_req,
+              blkif->st_rd_req, blkif->st_wr_req);
+       blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
+       blkif->st_rd_req = 0;
+       blkif->st_wr_req = 0;
+       blkif->st_oo_req = 0;
+}
+
+int tap_blkif_schedule(void *arg)
+{
+       blkif_t *blkif = arg;
+
+       blkif_get(blkif);
+
+       if (debug_lvl)
+               printk(KERN_DEBUG "%s: started\n", current->comm);
+
+       while (!kthread_should_stop()) {
+               wait_event_interruptible(
+                       blkif->wq,
+                       blkif->waiting_reqs || kthread_should_stop());
+               wait_event_interruptible(
+                       pending_free_wq,
+                       !list_empty(&pending_free) || kthread_should_stop());
+
+               blkif->waiting_reqs = 0;
+               smp_mb(); /* clear flag *before* checking for work */
+
+               if (do_block_io_op(blkif))
+                       blkif->waiting_reqs = 1;
+
+               if (log_stats && time_after(jiffies, blkif->st_print))
+                       print_stats(blkif);
+       }
+
+       if (log_stats)
+               print_stats(blkif);
+       if (debug_lvl)
+               printk(KERN_DEBUG "%s: exiting\n", current->comm);
+
+       blkif->xenblkd = NULL;
+       blkif_put(blkif);
+
+       return 0;
+}
+
+/******************************************************************
+ * COMPLETION CALLBACK -- Called by user level ioctl()
+ */
+
+static int blktap_read_ufe_ring(tap_blkif_t *info)
+{
+       /* This is called to read responses from the UFE ring. */
+       RING_IDX i, j, rp;
+       blkif_response_t *resp;
+       blkif_t *blkif=NULL;
+       int pending_idx, usr_idx, mmap_idx;
+       pending_req_t *pending_req;
+       
+       if (!info)
+               return 0;
+
+       /* We currently only forward packets in INTERCEPT_FE mode. */
+       if (!(info->mode & BLKTAP_MODE_INTERCEPT_FE))
+               return 0;
+
+       /* for each outstanding message on the UFEring  */
+       rp = info->ufe_ring.sring->rsp_prod;
+       rmb();
+        
+       for (i = info->ufe_ring.rsp_cons; i != rp; i++) {
+               resp = RING_GET_RESPONSE(&info->ufe_ring, i);
+               ++info->ufe_ring.rsp_cons;
+
+               /*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/
+               usr_idx = (int)resp->id;
+               pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx]));
+               mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]);
+
+               if ( (mmap_idx >= mmap_alloc) || 
+                  (ID_TO_IDX(info->idx_map[usr_idx]) >= MAX_PENDING_REQS) )
+                       WPRINTK("Incorrect req map"
+                              "[%d], internal map [%d,%d (%d)]\n", 
+                              usr_idx, mmap_idx, 
+                              ID_TO_IDX(info->idx_map[usr_idx]),
+                              MASK_PEND_IDX(
+                                      ID_TO_IDX(info->idx_map[usr_idx])));
+
+               pending_req = &pending_reqs[mmap_idx][pending_idx];
+               blkif = pending_req->blkif;
+
+               for (j = 0; j < pending_req->nr_pages; j++) {
+
+                       unsigned long kvaddr, uvaddr;
+                       struct page **map = info->vma->vm_private_data;
+                       struct page *pg;
+                       int offset;
+
+                       uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, j);
+                       kvaddr = idx_to_kaddr(mmap_idx, pending_idx, j);
+
+                       pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+                       ClearPageReserved(pg);
+                       offset = (uvaddr - info->vma->vm_start) 
+                               >> PAGE_SHIFT;
+                       map[offset] = NULL;
+               }
+               fast_flush_area(pending_req, pending_idx, usr_idx, info->minor);
+               make_response(blkif, pending_req->id, resp->operation,
+                             resp->status);
+               info->idx_map[usr_idx] = INVALID_REQ;
+               blkif_put(pending_req->blkif);
+               free_req(pending_req);
+       }
+               
+       return 0;
+}
+
+
+/******************************************************************************
+ * NOTIFICATION FROM GUEST OS.
+ */
+
+static void blkif_notify_work(blkif_t *blkif)
+{
+       blkif->waiting_reqs = 1;
+       wake_up(&blkif->wq);
+}
+
+irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+       blkif_notify_work(dev_id);
+       return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************
+ * DOWNWARD CALLS -- These interface with the block-device layer proper.
+ */
+static int print_dbug = 1;
+static int do_block_io_op(blkif_t *blkif)
+{
+       blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+       blkif_request_t *req;
+       pending_req_t *pending_req;
+       RING_IDX rc, rp;
+       int more_to_do = 0;
+       tap_blkif_t *info;
+
+       rc = blk_ring->req_cons;
+       rp = blk_ring->sring->req_prod;
+       rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+       /*Check blkif has corresponding UE ring*/
+       if (blkif->dev_num == -1) {
+               /*oops*/
+               if (print_dbug) {
+                       WPRINTK("Corresponding UE " 
+                              "ring does not exist!\n");
+                       print_dbug = 0; /*We only print this message once*/
+               }
+               return 0;
+       }
+
+       info = tapfds[blkif->dev_num];
+       if (info == NULL || !info->dev_inuse) {
+               if (print_dbug) {
+                       WPRINTK("Can't get UE info!\n");
+                       print_dbug = 0;
+               }
+               return 0;
+       }
+
+       while (rc != rp) {
+               
+               if (RING_FULL(&info->ufe_ring)) {
+                       WPRINTK("RING_FULL! More to do\n");
+                       more_to_do = 1;
+                       break;
+               }
+               
+               if (RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) {
+                       WPRINTK("RING_REQUEST_CONS_OVERFLOW!"
+                              " More to do\n");
+                       more_to_do = 1;
+                       break;          
+               }
+
+               pending_req = alloc_req();
+               if (NULL == pending_req) {
+                       blkif->st_oo_req++;
+                       more_to_do = 1;
+                       break;
+               }
+
+               req = RING_GET_REQUEST(blk_ring, rc);
+               blk_ring->req_cons = ++rc; /* before make_response() */ 
+
+               switch (req->operation) {
+               case BLKIF_OP_READ:
+                       blkif->st_rd_req++;
+                       dispatch_rw_block_io(blkif, req, pending_req);
+                       break;
+
+               case BLKIF_OP_WRITE:
+                       blkif->st_wr_req++;
+                       dispatch_rw_block_io(blkif, req, pending_req);
+                       break;
+
+               default:
+                       WPRINTK("unknown operation [%d]\n",
+                               req->operation);
+                       make_response(blkif, req->id, req->operation,
+                                     BLKIF_RSP_ERROR);
+                       free_req(pending_req);
+                       break;
+               }
+       }
+               
+       blktap_kick_user(blkif->dev_num);
+
+       return more_to_do;
+}
+
+static void dispatch_rw_block_io(blkif_t *blkif,
+                                blkif_request_t *req,
+                                pending_req_t *pending_req)
+{
+       extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
+       int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
+       struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+       unsigned int nseg;
+       int ret, i;
+       tap_blkif_t *info = tapfds[blkif->dev_num];
+       uint64_t sector;
+       
+       blkif_request_t *target;
+       int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
+       int usr_idx = GET_NEXT_REQ(info->idx_map);
+       uint16_t mmap_idx = pending_req->mem_idx;
+
+       /*Check we have space on user ring - should never fail*/
+       if(usr_idx == INVALID_REQ) goto fail_flush;
+       
+       /* Check that number of segments is sane. */
+       nseg = req->nr_segments;
+       if ( unlikely(nseg == 0) || 
+           unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) ) {
+               WPRINTK("Bad number of segments in request (%d)\n", nseg);
+               goto fail_response;
+       }
+       
+       /* Make sure userspace is ready. */
+       if (!info->ring_ok) {
+               WPRINTK("blktap: ring not ready for requests!\n");
+               goto fail_response;
+       }
+
+       if (RING_FULL(&info->ufe_ring)) {
+               WPRINTK("blktap: fe_ring is full, can't add "
+                       "IO Request will be dropped. %d %d\n",
+                       RING_SIZE(&info->ufe_ring),
+                       RING_SIZE(&blkif->blk_ring));
+               goto fail_response;
+       }
+
+       pending_req->blkif     = blkif;
+       pending_req->id        = req->id;
+       pending_req->operation = operation;
+       pending_req->status    = BLKIF_RSP_OKAY;
+       pending_req->nr_pages  = nseg;
+       op = 0;
+       for (i = 0; i < nseg; i++) {
+               unsigned long uvaddr;
+               unsigned long kvaddr;
+               uint64_t ptep;
+               struct page *page;
+               uint32_t flags;
+
+               uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
+               kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
+               page = virt_to_page(kvaddr);
+
+               sector = req->sector_number + (8*i);
+               if( (blkif->sectors > 0) && (sector >= blkif->sectors) ) {
+                       WPRINTK("BLKTAP: Sector request greater" 
+                              "than size\n");
+                       WPRINTK("BLKTAP: %s request sector" 
+                              "[%llu,%llu], Total [%llu]\n",
+                              (req->operation == 
+                               BLKIF_OP_WRITE ? "WRITE" : "READ"),
+                               (long long unsigned) sector,
+                               (long long unsigned) sector>>9,
+                               blkif->sectors);
+               }
+
+               flags = GNTMAP_host_map;
+               if (operation == WRITE)
+                       flags |= GNTMAP_readonly;
+               gnttab_set_map_op(&map[op], kvaddr, flags,
+                                 req->seg[i].gref, blkif->domid);
+               op++;
+
+               /* Now map it to user. */
+               ret = create_lookup_pte_addr(info->vma->vm_mm, 
+                                            uvaddr, &ptep);
+               if (ret) {
+                       WPRINTK("Couldn't get a pte addr!\n");
+                       fast_flush_area(pending_req, pending_idx, usr_idx, 
+                                       blkif->dev_num);
+                       goto fail_flush;
+               }
+
+               flags = GNTMAP_host_map | GNTMAP_application_map
+                       | GNTMAP_contains_pte;
+               if (operation == WRITE)
+                       flags |= GNTMAP_readonly;
+               gnttab_set_map_op(&map[op], ptep, flags,
+                                 req->seg[i].gref, blkif->domid);
+               op++;
+       }
+
+       ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op);
+       BUG_ON(ret);
+
+       for (i = 0; i < (nseg*2); i+=2) {
+               unsigned long uvaddr;
+               unsigned long kvaddr;
+               unsigned long offset;
+               struct page *pg;
+
+               uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2);
+               kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i/2);
+
+               if (unlikely(map[i].status != 0)) {
+                       WPRINTK("invalid kernel buffer -- "
+                               "could not remap it\n");
+                       goto fail_flush;
+               }
+
+               if (unlikely(map[i+1].status != 0)) {
+                       WPRINTK("invalid user buffer -- "
+                               "could not remap it\n");
+                       goto fail_flush;
+               }
+
+               pending_handle(mmap_idx, pending_idx, i/2).kernel 
+                       = map[i].handle;
+               pending_handle(mmap_idx, pending_idx, i/2).user   
+                       = map[i+1].handle;
+               set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
+                       FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
+               offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT;
+               pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+               ((struct page **)info->vma->vm_private_data)[offset] =
+                       pg;
+       }
+       /* Mark mapped pages as reserved: */
+       for (i = 0; i < req->nr_segments; i++) {
+               unsigned long kvaddr;
+               struct page *pg;
+
+               kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
+               pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+               SetPageReserved(pg);
+       }
+       
+       /*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
+       info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);
+
+       blkif_get(blkif);
+       /* Finally, write the request message to the user ring. */
+       target = RING_GET_REQUEST(&info->ufe_ring,
+                                 info->ufe_ring.req_prod_pvt);
+       memcpy(target, req, sizeof(*req));
+       target->id = usr_idx;
+       info->ufe_ring.req_prod_pvt++;
+       return;
+
+ fail_flush:
+       WPRINTK("Reached Fail_flush\n");
+       fast_flush_area(pending_req, pending_idx, usr_idx, blkif->dev_num);
+ fail_response:
+       make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+       free_req(pending_req);
+} 
+
+
+
+/******************************************************************
+ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+ */
+
+
+static void make_response(blkif_t *blkif, unsigned long id, 
+                          unsigned short op, int st)
+{
+       blkif_response_t *resp;
+       unsigned long     flags;
+       blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+       int more_to_do = 0;
+       int notify;
+
+       spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+       /* Place on the response ring for the relevant domain. */ 
+       resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+       resp->id        = id;
+       resp->operation = op;
+       resp->status    = st;
+       blk_ring->rsp_prod_pvt++;
+       RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify);
+
+       if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) {
+               /*
+                * Tail check for pending requests. Allows frontend to avoid
+                * notifications if requests are already in flight (lower
+                * overheads and promotes batching).
+                */
+               RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do);
+       } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) {
+               more_to_do = 1;
+
+       }       
+       spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+       if (more_to_do)
+               blkif_notify_work(blkif);
+       if (notify)
+               notify_remote_via_irq(blkif->irq);
+}
+
+static int __init blkif_init(void)
+{
+       int i, ret;
+       tap_blkif_t *info;
+
+       if (!is_running_on_xen())
+               return -ENODEV;
+
+       INIT_LIST_HEAD(&pending_free);
+        for(i = 0; i < 2; i++) {
+               ret = req_increase();
+               if (ret)
+                       break;
+       }
+       if (i == 0)
+               return ret;
+
+       tap_blkif_interface_init();
+
+       alloc_pending_reqs = 0;
+
+       tap_blkif_xenbus_init();
+
+       /*Create the blktap devices, but do not map memory or waitqueue*/
+       for(i = 0; i < MAX_TAP_DEV; i++) translate_domid[i].domid = 0xFFFF;
+
+       /* Dynamically allocate a major for this device */
+       ret = register_chrdev(0, "blktap", &blktap_fops);
+
+       if ( (ret < 0) ) {
+               WPRINTK("Couldn't register /dev/xen/blktap\n");
+               return -ENOMEM;
+       }       
+       
+       blktap_major = ret;
+
+       for(i = 0; i < MAX_TAP_DEV; i++ ) {
+               info = tapfds[i] = kzalloc(sizeof(tap_blkif_t),GFP_KERNEL);
+               if(tapfds[i] == NULL)
+                       return -ENOMEM;
+               info->minor = i;
+               info->pid = 0;
+               info->blkif = NULL;
+
+               info->dev_pending = info->dev_inuse = 0;
+
+               DPRINTK("Created misc_dev [/dev/xen/blktap%d]\n",i);
+       }
+       
+       /* Make sure the xen class exists */
+       if (!setup_xen_class()) {
+               /*
+                * This will allow udev to create the blktap ctrl device.
+                * We only want to create blktap0 first.  We don't want
+                * to flood the sysfs system with needless blktap devices.
+                * We only create the device when a request of a new device is
+                * made.
+                */
+               class_device_create(xen_class, NULL,
+                                   MKDEV(blktap_major, 0), NULL,
+                                   "blktap0");
+               tapfds[0]->sysfs_set = 1;
+       } else {
+               /* this is bad, but not fatal */
+               WPRINTK("blktap: sysfs xen_class not created\n");
+       }
+
+       DPRINTK("Blktap device successfully created\n");
+
+       return 0;
+}
+
+module_init(blkif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/xen/xenfb/Makefile b/drivers/xen/xenfb/Makefile
new file mode 100644 (file)
index 0000000..de96da7
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_XEN_FRAMEBUFFER)  := xenfb.o
diff --git a/drivers/xen/xenfb/xenfb.c b/drivers/xen/xenfb/xenfb.c
new file mode 100644 (file)
index 0000000..481aef6
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * linux/drivers/video/xenfb.c -- Xen para-virtual frame buffer device
+ *
+ * Copyright (C) 2005-2006
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  Based on linux/drivers/video/q40fb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <asm/hypervisor.h>
+#include <xen/evtchn.h>
+#include <xen/xenbus.h>
+#include <linux/xenfb.h>
+#include <linux/kthread.h>
+
+#define XENFB_WIDTH 800
+#define XENFB_HEIGHT 600
+#define XENFB_DEPTH 32
+
+static int xenfb_fps = 20;
+static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
+
+struct xenfb_mapping
+{
+       struct list_head        next;
+       struct vm_area_struct   *vma;
+       atomic_t                map_refs;
+       int                     faults;
+       struct xenfb_info       *info;
+};
+
+struct xenfb_info
+{
+       struct task_struct              *kthread;
+       wait_queue_head_t               wq;
+
+       unsigned char                   *fb;
+       struct fb_fix_screeninfo        *fix;
+       struct fb_var_screeninfo        *var;
+       struct fb_info                  *fb_info;
+       struct timer_list               refresh;
+       int                             dirty;
+       int                             y1, y2;
+       int                             x1, x2;
+
+       struct semaphore                mm_lock;
+       int                             nr_pages;
+       struct page                     **pages;
+       struct list_head                mappings;
+
+       unsigned                        evtchn;
+       int                             irq;
+       struct xenfb_page               *page;
+       unsigned long                   *mfns;
+       u32                             flags;
+};
+
+static void xenfb_do_update(struct xenfb_info *info,
+                           int x, int y, int w, int h)
+{
+       union xenfb_out_event event;
+       __u32 prod;
+
+       event.type = XENFB_TYPE_UPDATE;
+       event.update.x = x;
+       event.update.y = y;
+       event.update.width = w;
+       event.update.height = h;
+
+       prod = info->page->out_prod;
+       if (prod - info->page->out_cons == XENFB_OUT_RING_LEN)
+               return;         /* ring buffer full, event lost */
+       mb();                   /* ensure ring space available */
+       XENFB_OUT_RING_REF(info->page, prod) = event;
+       wmb();                  /* ensure ring contents visible */
+       info->page->out_prod = prod + 1;
+
+       notify_remote_via_evtchn(info->evtchn);
+}
+
+static int xenfb_queue_full(struct xenfb_info *info)
+{
+       __u32 cons, prod;
+
+       prod = info->page->out_prod;
+       cons = info->page->out_cons;
+       return prod - cons == XENFB_OUT_RING_LEN;
+}
+
+static void xenfb_update_screen(struct xenfb_info *info)
+{
+       int y1, y2, x1, x2;
+       struct list_head *item;
+       struct xenfb_mapping *map;
+
+       if (!(info->flags & XENFB_FLAG_UPDATE))
+               return;
+       if (xenfb_queue_full(info))
+               return;
+
+       y1 = info->y1;
+       y2 = info->y2;
+       x1 = info->x1;
+       x2 = info->x2;
+       info->y1 = info->y2 = info->x1 = info->x2 = 0;
+       down(&info->mm_lock);
+       list_for_each(item, &info->mappings) {
+               map = list_entry(item, struct xenfb_mapping, next);
+               if (!map->faults)
+                       continue;
+               zap_page_range(map->vma, map->vma->vm_start,
+                              map->vma->vm_end - map->vma->vm_start, NULL);
+               map->faults = 0;
+       }
+       up(&info->mm_lock);
+
+       xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
+}
+
+static int xenfb_thread(void *data)
+{
+       struct xenfb_info *info = data;
+
+       for (;;) {
+               if (kthread_should_stop())
+                       break;
+               if (info->dirty) {
+                       info->dirty = 0;
+                       xenfb_update_screen(info);
+               }
+               wait_event_interruptible(info->wq,
+                       kthread_should_stop() || info->dirty);
+       }
+       return 0;
+}
+
+static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       u32 v;
+
+       if (regno > info->cmap.len)
+               return 1;
+
+       red   >>= (16 - info->var.red.length);
+       green >>= (16 - info->var.green.length);
+       blue  >>= (16 - info->var.blue.length);
+
+       v = (red << info->var.red.offset) |
+           (green << info->var.green.offset) |
+           (blue << info->var.blue.offset);
+
+       switch (info->var.bits_per_pixel) {
+       case 16:
+       case 24:
+       case 32:
+               ((u32 *)info->pseudo_palette)[regno] = v;
+               break;
+       }
+       
+       return 0;
+}
+
+static void xenfb_timer(unsigned long data)
+{
+       struct xenfb_info *info = (struct xenfb_info *)data;
+       info->dirty = 1;
+       wake_up(&info->wq);
+}
+
+static void xenfb_refresh(struct xenfb_info *info,
+                         int x1, int y1, int w, int h)
+{
+       int y2, x2;
+
+       y2 = y1 + h;
+       x2 = x1 + w;
+       if (info->y2 == 0) {
+               info->y1 = y1;
+               info->y2 = y2;
+       }
+       if (info->x2 == 0) {
+               info->x1 = x1;
+               info->x2 = x2;
+       }
+
+       if (info->y1 > y1)
+               info->y1 = y1;
+       if (info->y2 < y2)
+               info->y2 = y2;
+       if (info->x1 > x1)
+               info->x1 = x1;
+       if (info->x2 < x2)
+               info->x2 = x2;
+
+       if (timer_pending(&info->refresh))
+               return;
+
+       mod_timer(&info->refresh, jiffies + HZ/xenfb_fps);
+}
+
+static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+       struct xenfb_info *info = p->par;
+
+       cfb_fillrect(p, rect);
+       xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+       struct xenfb_info *info = p->par;
+
+       cfb_imageblit(p, image);
+       xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
+}
+
+static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+       struct xenfb_info *info = p->par;
+
+       cfb_copyarea(p, area);
+       xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
+}
+
+static void xenfb_vm_open(struct vm_area_struct *vma)
+{
+       struct xenfb_mapping *map = vma->vm_private_data;
+       atomic_inc(&map->map_refs);
+}
+
+static void xenfb_vm_close(struct vm_area_struct *vma)
+{
+       struct xenfb_mapping *map = vma->vm_private_data;
+       struct xenfb_info *info = map->info;
+
+       down(&info->mm_lock);
+       if (atomic_dec_and_test(&map->map_refs)) {
+               list_del(&map->next);
+               kfree(map);
+       }
+       up(&info->mm_lock);
+}
+
+static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
+                                   unsigned long vaddr, int *type)
+{
+       struct xenfb_mapping *map = vma->vm_private_data;
+       struct xenfb_info *info = map->info;
+       int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
+       struct page *page;
+       int y1, y2;
+
+       if (pgnr >= info->nr_pages)
+               return NOPAGE_SIGBUS;
+
+       down(&info->mm_lock);
+       page = info->pages[pgnr];
+       get_page(page);
+       map->faults++;
+
+       y1 = pgnr * PAGE_SIZE / info->fix->line_length;
+       y2 = (pgnr * PAGE_SIZE + PAGE_SIZE - 1) / info->fix->line_length;
+       if (y2 > info->var->yres)
+               y2 = info->var->yres;
+       xenfb_refresh(info, 0, y1, info->var->xres, y2 - y1);
+       up(&info->mm_lock);
+
+       if (type)
+               *type = VM_FAULT_MINOR;
+
+       return page;
+}
+
+static struct vm_operations_struct xenfb_vm_ops = {
+       .open   = xenfb_vm_open,
+       .close  = xenfb_vm_close,
+       .nopage = xenfb_vm_nopage,
+};
+
+static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
+{
+       struct xenfb_info *info = fb_info->par;
+       struct xenfb_mapping *map;
+       int ret;
+       int map_pages;
+
+       down(&info->mm_lock);
+
+       ret = -EINVAL;
+       if (!(vma->vm_flags & VM_WRITE))
+               goto out;
+       if (!(vma->vm_flags & VM_SHARED))
+               goto out;
+       if (vma->vm_pgoff != 0)
+               goto out;
+
+       map_pages = (vma->vm_end - vma->vm_start + PAGE_SIZE-1) >> PAGE_SHIFT;
+       if (map_pages > info->nr_pages)
+               goto out;
+
+       ret = -ENOMEM;
+       map = kmalloc(sizeof(*map), GFP_KERNEL);
+       if (map == NULL)
+               goto out;
+       memset(map, 0, sizeof(*map));
+
+       map->vma = vma;
+       map->faults = 0;
+       map->info = info;
+       atomic_set(&map->map_refs, 1);
+       list_add(&map->next, &info->mappings);
+       vma->vm_ops = &xenfb_vm_ops;
+       vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
+       vma->vm_private_data = map;
+       ret = 0;
+
+ out:
+       up(&info->mm_lock);
+       return ret;
+}
+
+static struct fb_ops xenfb_fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_setcolreg   = xenfb_setcolreg,
+       .fb_fillrect    = xenfb_fillrect,
+       .fb_copyarea    = xenfb_copyarea,
+       .fb_imageblit   = xenfb_imageblit,
+       .fb_mmap        = xenfb_mmap,
+};
+
+static irqreturn_t xenfb_event_handler(int rq, void *dev_id,
+                                      struct pt_regs *regs)
+{
+       struct xenfb_info *info = dev_id;
+       __u32 cons, prod;
+
+       prod = info->page->in_prod;
+       rmb();                  /* ensure we see ring contents up to prod */
+       for (cons = info->page->in_cons; cons != prod; cons++) {
+               union xenfb_in_event *event;
+               event = &XENFB_IN_RING_REF(info->page, cons);
+
+               switch (event->type) {
+               case XENFB_TYPE_SET_EVENTS:
+                       info->flags = event->set_events.flags;
+                       break;
+               }
+       }
+       mb();                   /* ensure we're done with ring contents */
+       info->page->in_cons = cons;
+       notify_remote_via_evtchn(info->evtchn);
+
+       return IRQ_HANDLED;
+}
+
+static unsigned long vmalloc_to_mfn(void *address)
+{
+       return pfn_to_mfn(vmalloc_to_pfn(address));
+       //return arbitrary_virt_to_machine(address) >> PAGE_SHIFT;
+}
+
+static struct xenfb_info *xenfb_info;
+
+static int __init xenfb_probe(void)
+{
+       struct xenfb_info *info;
+       int i, ret;
+       struct fb_info *fb_info;
+       struct evtchn_alloc_unbound alloc_unbound;
+       struct evtchn_close close;
+       struct xenbus_transaction xbt;
+
+        /* Nothing to do if running in dom0. */
+        if (is_initial_xendomain())
+               return -ENODEV;
+#if 1
+        /* if we're not set up to use graphics mode, then don't initialize */
+       if (xenbus_scanf(XBT_NIL, "console", "use_graphics", "%d", &ret) < 0)
+               return -ENODEV;
+       if (ret == 0)
+               return -ENODEV;
+#endif
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (info == NULL)
+               return -ENOMEM;
+       memset(info, 0, sizeof(*info));
+
+       INIT_LIST_HEAD(&info->mappings);
+
+       info->fb = vmalloc(xenfb_mem_len);
+       if (info->fb == NULL)
+               goto error;
+       memset(info->fb, 0, xenfb_mem_len);
+       info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       info->pages = kmalloc(sizeof(struct page*)*info->nr_pages, GFP_KERNEL);
+       if (info->pages == NULL)
+               goto error_vfree;
+       for (i = 0; i < info->nr_pages; i++)
+               info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE);
+
+       fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
+       // FIXME sizeof(struct xenfb_info)
+       if (fb_info == NULL)
+               goto error_kfree;
+
+       info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
+       /* set up shared page */
+       info->page = (void *)__get_free_page(GFP_KERNEL);
+       if (!info->page)
+               goto error_kfree;
+       /* set up event channel */
+       alloc_unbound.dom = DOMID_SELF;
+       alloc_unbound.remote_dom = 0;
+       ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+                                         &alloc_unbound);
+       if (ret)
+               goto error_freep;
+       info->evtchn = alloc_unbound.port;
+
+       for (i = 0; i < info->nr_pages; i++)
+               info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+       info->page->pd[0] = vmalloc_to_mfn(info->mfns);
+       info->page->pd[1] = 0;
+       info->page->width = XENFB_WIDTH;
+       info->page->height = XENFB_HEIGHT;
+       info->page->depth = XENFB_DEPTH;
+       info->page->line_length = (info->page->depth / 8) * info->page->width;
+       info->page->mem_length = xenfb_mem_len;
+       info->page->in_cons = info->page->in_prod = 0;
+       info->page->out_cons = info->page->out_prod = 0;
+
+       ret = bind_evtchn_to_irqhandler(info->evtchn, xenfb_event_handler,
+                                       0, "xenfb", info);
+       if (ret < 0) {
+               close.port = info->evtchn;
+               HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+               goto error_freep;
+       }
+
+       info->irq = ret;
+       xenfb_info = info;
+
+       fb_info->pseudo_palette = fb_info->par;
+       fb_info->par = info;
+       fb_info->screen_base = info->fb;
+
+       memset(&fb_info->var, 0, sizeof(fb_info->var));
+       memset(&fb_info->fix, 0, sizeof(fb_info->fix));
+
+       fb_info->fbops = &xenfb_fb_ops;
+       fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
+       fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
+       fb_info->var.bits_per_pixel = info->page->depth;
+
+       fb_info->var.red = (struct fb_bitfield){16, 8, 0};
+       fb_info->var.green = (struct fb_bitfield){8, 8, 0};
+       fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
+
+       fb_info->var.activate = FB_ACTIVATE_NOW;
+       fb_info->var.height = -1;
+       fb_info->var.width = -1;
+       fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+
+       fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
+       fb_info->fix.line_length = info->page->line_length;
+       fb_info->fix.smem_start = 0;
+       fb_info->fix.smem_len = xenfb_mem_len;
+       strcpy(fb_info->fix.id, "xen");
+       fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+       fb_info->fix.accel = FB_ACCEL_NONE;
+
+       fb_info->flags = FBINFO_FLAG_DEFAULT;
+
+       fb_alloc_cmap(&fb_info->cmap, 256, 0);
+
+       info->fb_info = fb_info;
+       info->fix = &fb_info->fix;
+       info->var = &fb_info->var;
+
+       init_MUTEX(&info->mm_lock);
+       init_waitqueue_head(&info->wq);
+       init_timer(&info->refresh);
+       info->refresh.function = xenfb_timer;
+       info->refresh.data = (unsigned long)info;
+
+       info->kthread = kthread_run(xenfb_thread, info, "xenfb thread");
+       if (IS_ERR(info->kthread))
+               goto error_unbind;
+
+       ret = register_framebuffer(fb_info);
+       if (ret)
+               goto error_unbind;
+
+ again:
+       ret = xenbus_transaction_start(&xbt);
+       if (ret)
+               goto error_unreg;
+       ret = xenbus_printf(xbt, "vfb", "page-ref", "%lu",
+                           virt_to_mfn(info->page));
+       // FIXME grant tables?
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, "vfb", "event-channel", "%u",
+                           info->evtchn);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_transaction_end(xbt, 0);
+       if (ret) {
+               if (ret == -EAGAIN)
+                       goto again;
+               goto error_unreg;
+       }
+
+       return 0;
+
+ error_xenbus:
+       xenbus_transaction_end(xbt, 1);
+ error_unreg:
+       unregister_framebuffer(fb_info);
+ error_unbind:
+       unbind_from_irqhandler(info->irq, info);
+       // FIXME do we have to stop info->kthread?
+ error_freep:
+       free_page((unsigned long)info->page);
+ error_kfree:
+       kfree(info->pages);
+ error_vfree:
+       vfree(info->fb);
+ error:
+       kfree(info);
+       xenfb_info = NULL;
+
+       return -ENODEV;
+}
+
+static int __init xenfb_init(void)
+{
+       return xenfb_probe();
+}
+
+static void __exit xenfb_cleanup(void)
+{
+       struct xenfb_info *info = xenfb_info;
+
+       unregister_framebuffer(info->fb_info);
+       unbind_from_irqhandler(info->irq, info);
+       free_page((unsigned long)info->page);
+       kfree(info->pages);
+       vfree(info->fb);
+       kfree(info);
+       xenfb_info = NULL;
+}
+
+module_init(xenfb_init);
+module_exit(xenfb_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/xen/xenkbd/Makefile b/drivers/xen/xenkbd/Makefile
new file mode 100644 (file)
index 0000000..724efe2
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_XEN_KEYBOARD)     += xenkbd.o
diff --git a/drivers/xen/xenkbd/xenkbd.c b/drivers/xen/xenkbd/xenkbd.c
new file mode 100644 (file)
index 0000000..26749ff
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  Based on linux/drivers/input/mouse/sermouse.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <asm/hypervisor.h>
+#include <xen/evtchn.h>
+#include <xen/xenbus.h>
+#include <linux/xenkbd.h>
+
+struct xenkbd_device
+{
+       struct input_dev *dev;
+       struct xenkbd_info *info;
+       unsigned evtchn;
+       int irq;
+};
+
+static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs)
+{
+       struct xenkbd_device *dev = dev_id;
+       struct xenkbd_info *info = dev ? dev->info : 0;
+       static int button_map[3] = { BTN_RIGHT, BTN_MIDDLE, BTN_LEFT };
+       __u32 cons, prod;
+
+       prod = info->in_prod;
+       rmb();                  /* ensure we see ring contents up to prod */
+       for (cons = info->in_cons; cons != prod; cons++) {
+               union xenkbd_in_event *event;
+               event = &XENKBD_IN_RING_REF(info, cons);
+       
+               switch (event->type) {
+               case XENKBD_TYPE_MOTION:
+                       input_report_rel(dev->dev, REL_X, event->motion.rel_x);
+                       input_report_rel(dev->dev, REL_Y, event->motion.rel_y);
+                       break;
+               case XENKBD_TYPE_BUTTON:
+                       if (event->button.button < 3)
+                               input_report_key(dev->dev,
+                                                button_map[event->button.button],
+                                                event->button.pressed);
+                       break;
+               case XENKBD_TYPE_KEY:
+                       input_report_key(dev->dev, event->key.keycode, event->key.pressed);
+                       break;
+               }
+       }
+       input_sync(dev->dev);
+       mb();                   /* ensure we got ring contents */
+       info->in_cons = cons;
+       notify_remote_via_evtchn(dev->evtchn);
+
+       return IRQ_HANDLED;
+}
+
+static struct xenkbd_device *xenkbd_dev;
+
+int __init xenkbd_init(void)
+{
+       int ret = 0;
+       int i;
+       struct xenkbd_device *dev;
+       struct input_dev *input_dev;
+       struct evtchn_alloc_unbound alloc_unbound;
+       struct xenbus_transaction xbt;
+
+        /* Nothing to do if running in dom0. */
+        if (is_initial_xendomain())
+         return -ENODEV;
+#if 1
+        /* if we're not set up to use graphics mode, then don't initialize */
+       if (xenbus_scanf(XBT_NIL, "console", "use_graphics", "%d", &ret) < 0)
+         return -ENODEV;
+       if (ret == 0)
+         return -ENODEV;
+#endif
+
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!dev || !input_dev)
+               return -ENOMEM;
+
+       dev->dev = input_dev;
+       dev->info = (void *)__get_free_page(GFP_KERNEL);
+       if (!dev->info) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       alloc_unbound.dom = DOMID_SELF;
+       alloc_unbound.remote_dom = 0;
+       ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+                                         &alloc_unbound);
+       if (ret)
+               goto error_freep;
+       dev->evtchn = alloc_unbound.port;
+       ret = bind_evtchn_to_irqhandler(dev->evtchn, input_handler, 0,
+                                       "xenkbd", dev);
+       if (ret < 0)
+               goto error_freep;
+       dev->irq = ret;
+
+       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+       input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+       input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+
+       /* FIXME not sure this is quite right */
+       for (i = 0; i < 256; i++)
+               set_bit(i, input_dev->keybit);
+
+       input_dev->name = "Xen Virtual Keyboard/Mouse";
+
+       input_register_device(input_dev);
+
+ again:
+       ret = xenbus_transaction_start(&xbt);
+       if (ret)
+               goto error_unreg;
+       ret = xenbus_printf(xbt, "vkbd", "page-ref", "%lu",
+                           virt_to_mfn(dev->info));
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_printf(xbt, "vkbd", "event-channel", "%u",
+                           dev->evtchn);
+       if (ret)
+               goto error_xenbus;
+       ret = xenbus_transaction_end(xbt, 0);
+       if (ret) {
+               if (ret == -EAGAIN)
+                       goto again;
+               goto error_unreg;
+       }
+
+       dev->info->in_cons = dev->info->in_prod = 0;
+       dev->info->out_cons = dev->info->out_prod = 0;
+       xenkbd_dev = dev;
+
+       return ret;
+
+       
+ error_xenbus:
+       xenbus_transaction_end(xbt, 1);
+ error_unreg:
+       input_unregister_device(input_dev);
+       unbind_from_irqhandler(dev->irq, dev);
+ error_freep:
+       free_page((unsigned long)dev->info);
+ error:
+       kfree(dev);
+       return ret;
+}
+
+static void __exit xenkbd_cleanup(void)
+{
+       input_unregister_device(xenkbd_dev->dev);
+       unbind_from_irqhandler(xenkbd_dev->irq, xenkbd_dev);
+       free_page((unsigned long)xenkbd_dev->info);
+       kfree(xenkbd_dev);
+       xenkbd_dev = NULL;
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile
new file mode 100644 (file)
index 0000000..c1522d9
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Makefile for caching in a mounted filesystem
+#
+
+cachefiles-objs := \
+       cf-bind.o \
+       cf-interface.o \
+       cf-key.o \
+       cf-main.o \
+       cf-namei.o \
+       cf-proc.o \
+       cf-xattr.o
+
+ifeq ($(CONFIG_SYSCTL),y)
+cachefiles-objs += cf-sysctl.o
+endif
+
+obj-$(CONFIG_CACHEFILES) := cachefiles.o
diff --git a/fs/cachefiles/cf-bind.c b/fs/cachefiles/cf-bind.c
new file mode 100644 (file)
index 0000000..d8cb4c3
--- /dev/null
@@ -0,0 +1,279 @@
+/* cf-bind.c: bind and unbind a cache from the filesystem backing it
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/namespace.h>
+#include <linux/statfs.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include "internal.h"
+
+static int cachefiles_proc_add_cache(struct cachefiles_cache *cache,
+                                    struct vfsmount *mnt);
+
+/*****************************************************************************/
+/*
+ * bind a directory as a cache
+ */
+int cachefiles_proc_bind(struct cachefiles_cache *cache, char *args)
+{
+       _enter("{%u,%u,%u},%s",
+              cache->brun_percent,
+              cache->bcull_percent,
+              cache->bstop_percent,
+              args);
+
+       /* start by checking things over */
+       ASSERT(cache->bstop_percent >= 0 &&
+              cache->bstop_percent < cache->bcull_percent &&
+              cache->bcull_percent < cache->brun_percent &&
+              cache->brun_percent  < 100);
+
+       if (*args) {
+               kerror("'bind' command doesn't take an argument");
+               return -EINVAL;
+       }
+
+       if (!cache->rootdirname) {
+               kerror("No cache directory specified");
+               return -EINVAL;
+       }
+
+       /* don't permit already bound caches to be re-bound */
+       if (test_bit(CACHEFILES_READY, &cache->flags)) {
+               kerror("Cache already bound");
+               return -EBUSY;
+       }
+
+       /* make sure we have copies of the tag and dirname strings */
+       if (!cache->tag) {
+               /* the tag string is released by the fops->release()
+                * function, so we don't release it on error here */
+               cache->tag = kstrdup("CacheFiles", GFP_KERNEL);
+               if (!cache->tag)
+                       return -ENOMEM;
+       }
+
+       /* add the cache */
+       return cachefiles_proc_add_cache(cache, NULL);
+}
+
+/*****************************************************************************/
+/*
+ * add a cache
+ */
+static int cachefiles_proc_add_cache(struct cachefiles_cache *cache,
+                                    struct vfsmount *mnt)
+{
+       struct cachefiles_object *fsdef;
+       struct nameidata nd;
+       struct kstatfs stats;
+       struct dentry *graveyard, *cachedir, *root;
+       int ret;
+
+       _enter("");
+
+       /* allocate the root index object */
+       ret = -ENOMEM;
+
+       fsdef = kmem_cache_alloc(cachefiles_object_jar, SLAB_KERNEL);
+       if (!fsdef)
+               goto error_root_object;
+
+       atomic_set(&fsdef->usage, 1);
+       atomic_set(&fsdef->fscache_usage, 1);
+       fsdef->type = FSCACHE_COOKIE_TYPE_INDEX;
+
+       _debug("- fsdef %p", fsdef);
+
+       /* look up the directory at the root of the cache */
+       memset(&nd, 0, sizeof(nd));
+
+       ret = path_lookup(cache->rootdirname, LOOKUP_DIRECTORY, &nd);
+       if (ret < 0)
+               goto error_open_root;
+
+       /* bind to the special mountpoint we've prepared */
+       if (mnt) {
+               atomic_inc(&nd.mnt->mnt_sb->s_active);
+               mnt->mnt_sb = nd.mnt->mnt_sb;
+               mnt->mnt_flags = nd.mnt->mnt_flags;
+               mnt->mnt_flags |= MNT_NOSUID | MNT_NOEXEC | MNT_NODEV;
+               mnt->mnt_root = dget(nd.dentry);
+               mnt->mnt_mountpoint = mnt->mnt_root;
+
+               /* copy the name, but ignore kstrdup() failing ENOMEM - we'll
+                * just end up with an devicenameless mountpoint */
+               mnt->mnt_devname = kstrdup(nd.mnt->mnt_devname, GFP_KERNEL);
+               path_release(&nd);
+
+               cache->mnt = mntget(mnt);
+               root = dget(mnt->mnt_root);
+       } else {
+               cache->mnt = nd.mnt;
+               root = nd.dentry;
+
+               nd.mnt = NULL;
+               nd.dentry = NULL;
+               path_release(&nd);
+       }
+
+       /* check parameters */
+       ret = -EOPNOTSUPP;
+       if (!root->d_inode ||
+           !root->d_inode->i_op ||
+           !root->d_inode->i_op->lookup ||
+           !root->d_inode->i_op->mkdir ||
+           !root->d_inode->i_op->setxattr ||
+           !root->d_inode->i_op->getxattr ||
+           !root->d_sb ||
+           !root->d_sb->s_op ||
+           !root->d_sb->s_op->statfs ||
+           !root->d_sb->s_op->sync_fs)
+               goto error_unsupported;
+
+       ret = -EROFS;
+       if (root->d_sb->s_flags & MS_RDONLY)
+               goto error_unsupported;
+
+       /* get the cache size and blocksize */
+       ret = root->d_sb->s_op->statfs(root, &stats);
+       if (ret < 0)
+               goto error_unsupported;
+
+       ret = -ERANGE;
+       if (stats.f_bsize <= 0)
+               goto error_unsupported;
+
+       ret = -EOPNOTSUPP;
+       if (stats.f_bsize > PAGE_SIZE)
+               goto error_unsupported;
+
+       cache->bsize = stats.f_bsize;
+       cache->bshift = 0;
+       if (stats.f_bsize < PAGE_SIZE)
+               cache->bshift = PAGE_SHIFT - long_log2(stats.f_bsize);
+
+       _debug("blksize %u (shift %u)",
+              cache->bsize, cache->bshift);
+
+       _debug("size %llu, avail %llu", stats.f_blocks, stats.f_bavail);
+
+       /* set up caching limits */
+       stats.f_blocks >>= cache->bshift;
+       do_div(stats.f_blocks, 100);
+       cache->bstop = stats.f_blocks * cache->bstop_percent;
+       cache->bcull = stats.f_blocks * cache->bcull_percent;
+       cache->brun  = stats.f_blocks * cache->brun_percent;
+
+       _debug("limits {%llu,%llu,%llu}",
+              cache->brun,
+              cache->bcull,
+              cache->bstop);
+
+       /* get the cache directory and check its type */
+       cachedir = cachefiles_get_directory(cache, root, "cache");
+       if (IS_ERR(cachedir)) {
+               ret = PTR_ERR(cachedir);
+               goto error_unsupported;
+       }
+
+       fsdef->dentry = cachedir;
+
+       ret = cachefiles_check_object_type(fsdef);
+       if (ret < 0)
+               goto error_unsupported;
+
+       /* get the graveyard directory */
+       graveyard = cachefiles_get_directory(cache, root, "graveyard");
+       if (IS_ERR(graveyard)) {
+               ret = PTR_ERR(graveyard);
+               goto error_unsupported;
+       }
+
+       cache->graveyard = graveyard;
+
+       /* publish the cache */
+       fscache_init_cache(&cache->cache,
+                          &cachefiles_cache_ops,
+                          "%02x:%02x",
+                          MAJOR(fsdef->dentry->d_sb->s_dev),
+                          MINOR(fsdef->dentry->d_sb->s_dev)
+                          );
+
+       ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag);
+       if (ret < 0)
+               goto error_add_cache;
+
+       /* done */
+       set_bit(CACHEFILES_READY, &cache->flags);
+       dput(root);
+
+       printk(KERN_INFO "CacheFiles:"
+              " File cache on %s registered\n",
+              cache->cache.identifier);
+
+       /* check how much space the cache has */
+       cachefiles_has_space(cache, 0);
+
+       return 0;
+
+error_add_cache:
+       dput(cache->graveyard);
+       cache->graveyard = NULL;
+error_unsupported:
+       mntput(cache->mnt);
+       cache->mnt = NULL;
+       dput(fsdef->dentry);
+       fsdef->dentry = NULL;
+       dput(root);
+error_open_root:
+       kmem_cache_free(cachefiles_object_jar, fsdef);
+error_root_object:
+       kerror("Failed to register: %d", ret);
+       return ret;
+}
+
+/*****************************************************************************/
+/*
+ * unbind a cache on fd release
+ */
+void cachefiles_proc_unbind(struct cachefiles_cache *cache)
+{
+       _enter("");
+
+       if (test_bit(CACHEFILES_READY, &cache->flags)) {
+               printk(KERN_INFO "CacheFiles:"
+                      " File cache on %s unregistering\n",
+                      cache->cache.identifier);
+
+               fscache_withdraw_cache(&cache->cache);
+       }
+
+       if (cache->cache.fsdef)
+               cache->cache.ops->put_object(cache->cache.fsdef);
+
+       dput(cache->graveyard);
+       mntput(cache->mnt);
+
+       kfree(cache->rootdirname);
+       kfree(cache->tag);
+
+       _leave("");
+}
diff --git a/fs/cachefiles/cf-interface.c b/fs/cachefiles/cf-interface.c
new file mode 100644 (file)
index 0000000..b5ca30f
--- /dev/null
@@ -0,0 +1,1299 @@
+/* cf-interface.c: CacheFiles to FS-Cache interface
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/statfs.h>
+#include <linux/buffer_head.h>
+#include "internal.h"
+
+#define list_to_page(head) (list_entry((head)->prev, struct page, lru))
+#define log2(n) ffz(~(n))
+
+/*****************************************************************************/
+/*
+ * look up the nominated node in this cache, creating it if necessary
+ */
+static struct fscache_object *cachefiles_lookup_object(
+       struct fscache_cache *_cache,
+       struct fscache_object *_parent,
+       struct fscache_cookie *cookie)
+{
+       struct cachefiles_object *parent, *object;
+       struct cachefiles_cache *cache;
+       struct cachefiles_xattr *auxdata;
+       unsigned keylen, auxlen;
+       void *buffer;
+       char *key;
+       int ret;
+
+       ASSERT(_parent);
+
+       cache = container_of(_cache, struct cachefiles_cache, cache);
+       parent = container_of(_parent, struct cachefiles_object, fscache);
+
+       _enter("{%s},%p,%p", cache->cache.identifier, parent, cookie);
+
+       /* create a new object record and a temporary leaf image */
+       object = kmem_cache_alloc(cachefiles_object_jar, SLAB_KERNEL);
+       if (!object)
+               goto nomem_object;
+
+       atomic_set(&object->usage, 1);
+       atomic_set(&object->fscache_usage, 1);
+
+       fscache_object_init(&object->fscache);
+       object->fscache.cookie = cookie;
+       object->fscache.cache = parent->fscache.cache;
+
+       object->type = cookie->def->type;
+
+       /* get hold of the raw key
+        * - stick the length on the front and leave space on the back for the
+        *   encoder
+        */
+       buffer = kmalloc((2 + 512) + 3, GFP_KERNEL);
+       if (!buffer)
+               goto nomem_buffer;
+
+       keylen = cookie->def->get_key(cookie->netfs_data, buffer + 2, 512);
+       ASSERTCMP(keylen, <, 512);
+
+       *(uint16_t *)buffer = keylen;
+       ((char *)buffer)[keylen + 2] = 0;
+       ((char *)buffer)[keylen + 3] = 0;
+       ((char *)buffer)[keylen + 4] = 0;
+
+       /* turn the raw key into something that can work with as a filename */
+       key = cachefiles_cook_key(buffer, keylen + 2, object->type);
+       if (!key)
+               goto nomem_key;
+
+       /* get hold of the auxiliary data and prepend the object type */
+       auxdata = buffer;
+       auxlen = 0;
+       if (cookie->def->get_aux) {
+               auxlen = cookie->def->get_aux(cookie->netfs_data,
+                                             auxdata->data, 511);
+               ASSERTCMP(auxlen, <, 511);
+       }
+
+       auxdata->len = auxlen + 1;
+       auxdata->type = cookie->def->type;
+
+       /* look up the key, creating any missing bits */
+       ret = cachefiles_walk_to_object(parent, object, key, auxdata);
+       if (ret < 0)
+               goto lookup_failed;
+
+       kfree(buffer);
+       kfree(key);
+       _leave(" = %p", &object->fscache);
+       return &object->fscache;
+
+lookup_failed:
+       kmem_cache_free(cachefiles_object_jar, object);
+       kfree(buffer);
+       kfree(key);
+       _leave(" = %d", ret);
+       return ERR_PTR(ret);
+
+nomem_key:
+       kfree(buffer);
+nomem_buffer:
+       kmem_cache_free(cachefiles_object_jar, object);
+nomem_object:
+       _leave(" = -ENOMEM");
+       return ERR_PTR(-ENOMEM);
+
+}
+
+/*****************************************************************************/
+/*
+ * increment the usage count on an inode object (may fail if unmounting)
+ */
+static struct fscache_object *cachefiles_grab_object(struct fscache_object *_object)
+{
+       struct cachefiles_object *object;
+
+       _enter("%p", _object);
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+
+#ifdef CACHEFILES_DEBUG_SLAB
+       ASSERT((atomic_read(&object->fscache_usage) & 0xffff0000) != 0x6b6b0000);
+#endif
+
+       atomic_inc(&object->fscache_usage);
+       return &object->fscache;
+
+}
+
+/*****************************************************************************/
+/*
+ * lock the semaphore on an object object
+ */
+static void cachefiles_lock_object(struct fscache_object *_object)
+{
+       struct cachefiles_object *object;
+
+       _enter("%p", _object);
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+
+#ifdef CACHEFILES_DEBUG_SLAB
+       ASSERT((atomic_read(&object->fscache_usage) & 0xffff0000) != 0x6b6b0000);
+#endif
+
+       down_write(&object->sem);
+
+}
+
+/*****************************************************************************/
+/*
+ * unlock the semaphore on an object object
+ */
+static void cachefiles_unlock_object(struct fscache_object *_object)
+{
+       struct cachefiles_object *object;
+
+       _enter("%p", _object);
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       up_write(&object->sem);
+
+}
+
+/*****************************************************************************/
+/*
+ * update the auxilliary data for an object object on disk
+ */
+static void cachefiles_update_object(struct fscache_object *_object)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+
+       _enter("%p", _object);
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       cache = container_of(object->fscache.cache, struct cachefiles_cache, cache);
+
+       //cachefiles_tree_update_object(super, object);
+
+}
+
+/*****************************************************************************/
+/*
+ * dispose of a reference to an object object
+ */
+static void cachefiles_put_object(struct fscache_object *_object)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+
+       ASSERT(_object);
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       _enter("%p{%d}", object, atomic_read(&object->usage));
+
+       ASSERT(object);
+
+       cache = container_of(object->fscache.cache,
+                            struct cachefiles_cache, cache);
+
+#ifdef CACHEFILES_DEBUG_SLAB
+       ASSERT((atomic_read(&object->fscache_usage) & 0xffff0000) != 0x6b6b0000);
+#endif
+
+       if (!atomic_dec_and_test(&object->fscache_usage))
+               return;
+
+       _debug("- kill object %p", object);
+
+       /* delete retired objects */
+       if (test_bit(FSCACHE_OBJECT_RECYCLING, &object->fscache.flags) &&
+           _object != cache->cache.fsdef
+           ) {
+               _debug("- retire object %p", object);
+               cachefiles_delete_object(cache, object);
+       }
+
+       /* close the filesystem stuff attached to the object */
+       if (object->backer != object->dentry) {
+               dput(object->backer);
+               object->backer = NULL;
+       }
+
+       /* note that an object is now inactive */
+       write_lock(&cache->active_lock);
+       rb_erase(&object->active_node, &cache->active_nodes);
+       write_unlock(&cache->active_lock);
+
+       dput(object->dentry);
+       object->dentry = NULL;
+
+       /* then dispose of the object */
+       kmem_cache_free(cachefiles_object_jar, object);
+
+       _leave("");
+
+}
+
+/*****************************************************************************/
+/*
+ * sync a cache
+ */
+static void cachefiles_sync_cache(struct fscache_cache *_cache)
+{
+       struct cachefiles_cache *cache;
+       int ret;
+
+       _enter("%p", _cache);
+
+       cache = container_of(_cache, struct cachefiles_cache, cache);
+
+       /* make sure all pages pinned by operations on behalf of the netfs are
+        * written to disc */
+       ret = fsync_super(cache->mnt->mnt_sb);
+       if (ret == -EIO)
+               cachefiles_io_error(cache,
+                                   "Attempt to sync backing fs superblock"
+                                   " returned error %d",
+                                   ret);
+
+}
+
+/*****************************************************************************/
+/*
+ * set the data size on an object
+ */
+static int cachefiles_set_i_size(struct fscache_object *_object, loff_t i_size)
+{
+       struct cachefiles_object *object;
+       struct iattr newattrs;
+       int ret;
+
+       _enter("%p,%llu", _object, i_size);
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+
+       if (i_size == object->i_size)
+               return 0;
+
+       if (!object->backer)
+               return -ENOBUFS;
+
+       ASSERT(S_ISREG(object->backer->d_inode->i_mode));
+
+       newattrs.ia_size = i_size;
+       newattrs.ia_valid = ATTR_SIZE;
+
+       mutex_lock(&object->backer->d_inode->i_mutex);
+       ret = notify_change(object->backer, &newattrs);
+       mutex_unlock(&object->backer->d_inode->i_mutex);
+
+       if (ret == -EIO) {
+               cachefiles_io_error_obj(object, "Size set failed");
+               ret = -ENOBUFS;
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+}
+
+/*****************************************************************************/
+/*
+ * see if we have space for a number of pages in the cache
+ */
+int cachefiles_has_space(struct cachefiles_cache *cache, unsigned nr)
+{
+       struct kstatfs stats;
+       int ret;
+
+       _enter("{%llu,%llu,%llu},%d",
+              cache->brun, cache->bcull, cache->bstop,  nr);
+
+       /* find out how many pages of blockdev are available */
+       memset(&stats, 0, sizeof(stats));
+
+       ret = cache->mnt->mnt_sb->s_op->statfs(cache->mnt->mnt_root, &stats);
+       if (ret < 0) {
+               if (ret == -EIO)
+                       cachefiles_io_error(cache, "statfs failed");
+               return ret;
+       }
+
+       stats.f_bavail >>= cache->bshift;
+
+       _debug("avail %llu", stats.f_bavail);
+
+       /* see if there is sufficient space */
+       stats.f_bavail -= nr;
+
+       ret = -ENOBUFS;
+       if (stats.f_bavail < cache->bstop)
+               goto begin_cull;
+
+       ret = 0;
+       if (stats.f_bavail < cache->bcull)
+               goto begin_cull;
+
+       if (test_bit(CACHEFILES_CULLING, &cache->flags) &&
+           stats.f_bavail >= cache->brun
+           ) {
+               if (test_and_clear_bit(CACHEFILES_CULLING, &cache->flags)) {
+                       _debug("cease culling");
+                       send_sigurg(&cache->cachefilesd->f_owner);
+               }
+       }
+
+       _leave(" = 0");
+       return 0;
+
+begin_cull:
+       if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) {
+               _debug("### CULL CACHE ###");
+               send_sigurg(&cache->cachefilesd->f_owner);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+}
+
+/*****************************************************************************/
+/*
+ * waiting reading backing files
+ */
+static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode,
+                                 int sync, void *_key)
+{
+       struct cachefiles_one_read *monitor =
+               container_of(wait, struct cachefiles_one_read, monitor);
+       struct wait_bit_key *key = _key;
+       struct page *page = wait->private;
+
+       ASSERT(key);
+
+       _enter("{%lu},%u,%d,{%p,%u}",
+              monitor->netfs_page->index, mode, sync,
+              key->flags, key->bit_nr);
+
+       if (key->flags != &page->flags ||
+           key->bit_nr != PG_locked)
+               return 0;
+
+       _debug("--- monitor %p %lx ---", page, page->flags);
+
+       if (!PageUptodate(page) && !PageError(page))
+               dump_stack();
+
+       /* remove from the waitqueue */
+       list_del(&wait->task_list);
+
+       /* move onto the action list and queue for keventd */
+       ASSERT(monitor->object);
+
+       spin_lock(&monitor->object->work_lock);
+       list_move(&monitor->obj_link, &monitor->object->read_list);
+       spin_unlock(&monitor->object->work_lock);
+
+       schedule_work(&monitor->object->read_work);
+
+       return 0;
+
+}
+
+/*****************************************************************************/
+/*
+ * let keventd drive the copying of pages
+ */
+void cachefiles_read_copier_work(void *_object)
+{
+       struct cachefiles_one_read *monitor;
+       struct cachefiles_object *object = _object;
+       struct fscache_cookie *cookie = object->fscache.cookie;
+       struct pagevec pagevec;
+       int error, max;
+
+       _enter("{ino=%lu}", object->backer->d_inode->i_ino);
+
+       pagevec_init(&pagevec, 0);
+
+       max = 8;
+       spin_lock_irq(&object->work_lock);
+
+       while (!list_empty(&object->read_list)) {
+               monitor = list_entry(object->read_list.next,
+                                    struct cachefiles_one_read, obj_link);
+               list_del(&monitor->obj_link);
+
+               spin_unlock_irq(&object->work_lock);
+
+               _debug("- copy {%lu}", monitor->back_page->index);
+
+               error = -EIO;
+               if (PageUptodate(monitor->back_page)) {
+                       copy_highpage(monitor->netfs_page, monitor->back_page);
+
+                       pagevec_add(&pagevec, monitor->netfs_page);
+                       cookie->def->mark_pages_cached(
+                               cookie->netfs_data,
+                               monitor->netfs_page->mapping,
+                               &pagevec);
+                       pagevec_reinit(&pagevec);
+
+                       error = 0;
+               }
+
+               if (error)
+                       cachefiles_io_error_obj(
+                               object,
+                               "readpage failed on backing file %lx",
+                               (unsigned long) monitor->back_page->flags);
+
+               page_cache_release(monitor->back_page);
+
+               monitor->end_io_func(monitor->netfs_page,
+                                    monitor->context,
+                                    error);
+
+               page_cache_release(monitor->netfs_page);
+               fscache_put_context(cookie, monitor->context);
+               kfree(monitor);
+
+               /* let keventd have some air occasionally */
+               max--;
+               if (max < 0 || need_resched()) {
+                       if (!list_empty(&object->read_list))
+                               schedule_work(&object->read_work);
+                       _leave(" [maxed out]");
+                       return;
+               }
+
+               spin_lock_irq(&object->work_lock);
+       }
+
+       spin_unlock_irq(&object->work_lock);
+
+       _leave("");
+
+}
+
+/*****************************************************************************/
+/*
+ * read the corresponding page to the given set from the backing file
+ * - an uncertain page is simply discarded, to be tried again another time
+ */
+static int cachefiles_read_backing_file_one(struct cachefiles_object *object,
+                                           fscache_rw_complete_t end_io_func,
+                                           void *context,
+                                           struct page *netpage,
+                                           struct pagevec *lru_pvec)
+{
+       struct cachefiles_one_read *monitor;
+       struct address_space *bmapping;
+       struct page *newpage, *backpage;
+       int ret;
+
+       _enter("");
+
+       ASSERTCMP(pagevec_count(lru_pvec), ==, 0);
+       pagevec_reinit(lru_pvec);
+
+       _debug("read back %p{%lu,%d}",
+              netpage, netpage->index, page_count(netpage));
+
+       monitor = kzalloc(sizeof(*monitor), GFP_KERNEL);
+       if (!monitor)
+               goto nomem;
+
+       monitor->netfs_page = netpage;
+       monitor->object = object;
+       monitor->end_io_func = end_io_func;
+       monitor->context = fscache_get_context(object->fscache.cookie,
+                                              context);
+
+       init_waitqueue_func_entry(&monitor->monitor, cachefiles_read_waiter);
+
+       /* attempt to get hold of the backing page */
+       bmapping = object->backer->d_inode->i_mapping;
+       newpage = NULL;
+
+       for (;;) {
+               backpage = find_get_page(bmapping, netpage->index);
+               if (backpage)
+                       goto backing_page_already_present;
+
+               if (!newpage) {
+                       newpage = page_cache_alloc_cold(bmapping);
+                       if (!newpage)
+                               goto nomem_monitor;
+               }
+
+               ret = add_to_page_cache(newpage, bmapping,
+                                       netpage->index, GFP_KERNEL);
+               if (ret == 0)
+                       goto installed_new_backing_page;
+               if (ret != -EEXIST)
+                       goto nomem_page;
+       }
+
+       /* we've installed a new backing page, so now we need to add it
+        * to the LRU list and start it reading */
+installed_new_backing_page:
+       _debug("- new %p", newpage);
+
+       backpage = newpage;
+       newpage = NULL;
+
+       page_cache_get(backpage);
+       pagevec_add(lru_pvec, backpage);
+       __pagevec_lru_add(lru_pvec);
+
+       ret = bmapping->a_ops->readpage(NULL, backpage);
+       if (ret < 0)
+               goto read_error;
+
+       /* set the monitor to transfer the data across */
+monitor_backing_page:
+       _debug("- monitor add");
+
+       /* install the monitor */
+       page_cache_get(monitor->netfs_page);
+       page_cache_get(backpage);
+       monitor->back_page = backpage;
+
+       spin_lock_irq(&object->work_lock);
+       list_add_tail(&monitor->obj_link, &object->read_pend_list);
+       spin_unlock_irq(&object->work_lock);
+
+       monitor->monitor.private = backpage;
+       install_page_waitqueue_monitor(backpage, &monitor->monitor);
+       monitor = NULL;
+
+       /* but the page may have been read before the monitor was
+        * installed, so the monitor may miss the event - so we have to
+        * ensure that we do get one in such a case */
+       if (!TestSetPageLocked(backpage))
+               unlock_page(backpage);
+       goto success;
+
+       /* if the backing page is already present, it can be in one of
+        * three states: read in progress, read failed or read okay */
+backing_page_already_present:
+       _debug("- present");
+
+       if (newpage) {
+               page_cache_release(newpage);
+               newpage = NULL;
+       }
+
+       if (PageError(backpage))
+               goto io_error;
+
+       if (PageUptodate(backpage))
+               goto backing_page_already_uptodate;
+
+       goto monitor_backing_page;
+
+       /* the backing page is already up to date, attach the netfs
+        * page to the pagecache and LRU and copy the data across */
+backing_page_already_uptodate:
+       _debug("- uptodate");
+
+       copy_highpage(netpage, backpage);
+       end_io_func(netpage, context, 0);
+
+success:
+       _debug("success");
+       ret = 0;
+
+out:
+       if (backpage)
+               page_cache_release(backpage);
+       if (monitor) {
+               fscache_put_context(object->fscache.cookie, monitor->context);
+               kfree(monitor);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+read_error:
+       _debug("read error %d", ret);
+       if (ret == -ENOMEM)
+               goto out;
+io_error:
+       cachefiles_io_error_obj(object, "page read error on backing file");
+       ret = -EIO;
+       goto out;
+
+nomem_page:
+       page_cache_release(newpage);
+nomem_monitor:
+       fscache_put_context(object->fscache.cookie, monitor->context);
+       kfree(monitor);
+nomem:
+       _leave(" = -ENOMEM");
+       return -ENOMEM;
+
+}
+
+/*****************************************************************************/
+/*
+ * read a page from the cache or allocate a block in which to store it
+ * - cache withdrawal is prevented by the caller
+ * - returns -EINTR if interrupted
+ * - returns -ENOMEM if ran out of memory
+ * - returns -ENOBUFS if no buffers can be made available
+ * - returns -ENOBUFS if page is beyond EOF
+ * - if the page is backed by a block in the cache:
+ *   - a read will be started which will call the callback on completion
+ *   - 0 will be returned
+ * - else if the page is unbacked:
+ *   - the metadata will be retained
+ *   - -ENODATA will be returned
+ */
+static int cachefiles_read_or_alloc_page(struct fscache_object *_object,
+                                        struct page *page,
+                                        fscache_rw_complete_t end_io_func,
+                                        void *context,
+                                        unsigned long gfp)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+       struct fscache_cookie *cookie;
+       struct pagevec pagevec;
+       struct inode *inode;
+       sector_t block0, block;
+       unsigned shift;
+       int ret;
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       cache = container_of(object->fscache.cache, struct cachefiles_cache, cache);
+
+       _enter("{%p},{%lx},,,", object, page->index);
+
+       if (!object->backer)
+               return -ENOBUFS;
+
+       inode = object->backer->d_inode;
+       ASSERT(S_ISREG(inode->i_mode));
+       ASSERT(inode->i_mapping->a_ops->bmap);
+       ASSERT(inode->i_mapping->a_ops->readpages);
+
+       /* calculate the shift required to use bmap */
+       if (inode->i_sb->s_blocksize > PAGE_SIZE)
+               return -ENOBUFS;
+
+       shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
+
+       cookie = object->fscache.cookie;
+
+       pagevec_init(&pagevec, 0);
+
+       /* we assume the absence or presence of the first block is a good
+        * enough indication for the page as a whole
+        * - TODO: don't use bmap() for this as it is _not_ actually good
+        *   enough for this as it doesn't indicate errors, but it's all we've
+        *   got for the moment
+        */
+       block0 = page->index;
+       block0 <<= shift;
+
+       block = inode->i_mapping->a_ops->bmap(inode->i_mapping, block0);
+       _debug("%llx -> %llx", block0, block);
+
+       if (block) {
+               /* submit the apparently valid page to the backing fs to be
+                * read from disk */
+               ret = cachefiles_read_backing_file_one(object,
+                                                      end_io_func,
+                                                      context,
+                                                      page,
+                                                      &pagevec);
+               ret = 0;
+       } else if (cachefiles_has_space(cache, 1) == 0) {
+               /* there's space in the cache we can use */
+               pagevec_add(&pagevec, page);
+               cookie->def->mark_pages_cached(cookie->netfs_data,
+                                              page->mapping, &pagevec);
+               ret = -ENODATA;
+       } else {
+               ret = -ENOBUFS;
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+}
+
+/*****************************************************************************/
+/*
+ * read the corresponding pages to the given set from the backing file
+ * - any uncertain pages are simply discarded, to be tried again another time
+ */
+static int cachefiles_read_backing_file(struct cachefiles_object *object,
+                                       fscache_rw_complete_t end_io_func,
+                                       void *context,
+                                       struct address_space *mapping,
+                                       struct list_head *list,
+                                       struct pagevec *lru_pvec)
+{
+       struct cachefiles_one_read *monitor = NULL;
+       struct address_space *bmapping = object->backer->d_inode->i_mapping;
+       struct page *newpage = NULL, *netpage, *_n, *backpage = NULL;
+       int ret = 0;
+
+       _enter("");
+
+       ASSERTCMP(pagevec_count(lru_pvec), ==, 0);
+       pagevec_reinit(lru_pvec);
+
+       list_for_each_entry_safe(netpage, _n, list, lru) {
+               list_del(&netpage->lru);
+
+               _debug("read back %p{%lu,%d}",
+                      netpage, netpage->index, page_count(netpage));
+
+               if (!monitor) {
+                       monitor = kzalloc(sizeof(*monitor), GFP_KERNEL);
+                       if (!monitor)
+                               goto nomem;
+
+                       monitor->object = object;
+                       monitor->end_io_func = end_io_func;
+                       monitor->context = fscache_get_context(
+                               object->fscache.cookie, context);
+
+                       init_waitqueue_func_entry(&monitor->monitor,
+                                                 cachefiles_read_waiter);
+               }
+
+               for (;;) {
+                       backpage = find_get_page(bmapping, netpage->index);
+                       if (backpage)
+                               goto backing_page_already_present;
+
+                       if (!newpage) {
+                               newpage = page_cache_alloc_cold(bmapping);
+                               if (!newpage)
+                                       goto nomem;
+                       }
+
+                       ret = add_to_page_cache(newpage, bmapping,
+                                               netpage->index, GFP_KERNEL);
+                       if (ret == 0)
+                               goto installed_new_backing_page;
+                       if (ret != -EEXIST)
+                               goto nomem;
+               }
+
+               /* we've installed a new backing page, so now we need to add it
+                * to the LRU list and start it reading */
+       installed_new_backing_page:
+               _debug("- new %p", newpage);
+
+               backpage = newpage;
+               newpage = NULL;
+
+               page_cache_get(backpage);
+               if (!pagevec_add(lru_pvec, backpage))
+                       __pagevec_lru_add(lru_pvec);
+
+       reread_backing_page:
+               ret = bmapping->a_ops->readpage(NULL, backpage);
+               if (ret < 0)
+                       goto read_error;
+
+               /* add the netfs page to the pagecache and LRU, and set the
+                * monitor to transfer the data across */
+       monitor_backing_page:
+               _debug("- monitor add");
+
+               ret = add_to_page_cache(netpage, mapping, netpage->index,
+                                       GFP_KERNEL);
+               if (ret < 0) {
+                       if (ret == -EEXIST) {
+                               page_cache_release(netpage);
+                               continue;
+                       }
+                       goto nomem;
+               }
+
+               page_cache_get(netpage);
+               if (!pagevec_add(lru_pvec, netpage))
+                       __pagevec_lru_add(lru_pvec);
+
+               /* install a monitor */
+               page_cache_get(netpage);
+               monitor->netfs_page = netpage;
+
+               page_cache_get(backpage);
+               monitor->back_page = backpage;
+
+               spin_lock_irq(&object->work_lock);
+               list_add_tail(&monitor->obj_link, &object->read_pend_list);
+               spin_unlock_irq(&object->work_lock);
+
+               monitor->monitor.private = backpage;
+               install_page_waitqueue_monitor(backpage, &monitor->monitor);
+               monitor = NULL;
+
+               /* but the page may have been read before the monitor was
+                * installed, so the monitor may miss the event - so we have to
+                * ensure that we do get one in such a case */
+               if (!TestSetPageLocked(backpage)) {
+                       _debug("2unlock %p", backpage);
+                       unlock_page(backpage);
+               }
+
+               page_cache_release(backpage);
+               backpage = NULL;
+
+               page_cache_release(netpage);
+               netpage = NULL;
+               continue;
+
+               /* if the backing page is already present, it can be in one of
+                * three states: read in progress, read failed or read okay */
+       backing_page_already_present:
+               _debug("- present %p", backpage);
+
+               if (PageError(backpage))
+                       goto io_error;
+
+               if (PageUptodate(backpage))
+                       goto backing_page_already_uptodate;
+
+               _debug("- not ready %p{%lx}", backpage, backpage->flags);
+
+               if (TestSetPageLocked(backpage))
+                       goto monitor_backing_page;
+
+               if (PageError(backpage)) {
+                       unlock_page(backpage);
+                       goto io_error;
+               }
+
+               if (PageUptodate(backpage))
+                       goto backing_page_already_uptodate_unlock;
+
+               /* we've locked a page that's neither up to date nor erroneous,
+                * so we need to attempt to read it again */
+               goto reread_backing_page;
+
+               /* the backing page is already up to date, attach the netfs
+                * page to the pagecache and LRU and copy the data across */
+       backing_page_already_uptodate_unlock:
+               unlock_page(backpage);
+       backing_page_already_uptodate:
+               _debug("- uptodate");
+
+               ret = add_to_page_cache(netpage, mapping, netpage->index,
+                                       GFP_KERNEL);
+               if (ret < 0) {
+                       if (ret == -EEXIST) {
+                               page_cache_release(netpage);
+                               continue;
+                       }
+                       goto nomem;
+               }
+
+               copy_highpage(netpage, backpage);
+
+               page_cache_release(backpage);
+               backpage = NULL;
+
+               page_cache_get(netpage);
+               if (!pagevec_add(lru_pvec, netpage))
+                       __pagevec_lru_add(lru_pvec);
+
+               end_io_func(netpage, context, 0);
+
+               page_cache_release(netpage);
+               netpage = NULL;
+               continue;
+       }
+
+       netpage = NULL;
+
+       _debug("out");
+
+out:
+       /* tidy up */
+       pagevec_lru_add(lru_pvec);
+
+       if (newpage)
+               page_cache_release(newpage);
+       if (netpage)
+               page_cache_release(netpage);
+       if (backpage)
+               page_cache_release(backpage);
+       if (monitor) {
+               fscache_put_context(object->fscache.cookie, monitor->context);
+               kfree(monitor);
+       }
+
+       list_for_each_entry_safe(netpage, _n, list, lru) {
+               list_del(&netpage->lru);
+               page_cache_release(netpage);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+
+nomem:
+       _debug("nomem");
+       ret = -ENOMEM;
+       goto out;
+
+read_error:
+       _debug("read error %d", ret);
+       if (ret == -ENOMEM)
+               goto out;
+io_error:
+       cachefiles_io_error_obj(object, "page read error on backing file");
+       ret = -EIO;
+       goto out;
+
+}
+
+/*****************************************************************************/
+/*
+ * read a list of pages from the cache or allocate blocks in which to store
+ * them
+ */
+static int cachefiles_read_or_alloc_pages(struct fscache_object *_object,
+                                         struct address_space *mapping,
+                                         struct list_head *pages,
+                                         unsigned *nr_pages,
+                                         fscache_rw_complete_t end_io_func,
+                                         void *context,
+                                         unsigned long gfp)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+       struct fscache_cookie *cookie;
+       struct list_head backpages;
+       struct pagevec pagevec;
+       struct inode *inode;
+       struct page *page, *_n;
+       unsigned shift, nrbackpages;
+       int ret, ret2, space;
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       cache = container_of(object->fscache.cache, struct cachefiles_cache, cache);
+
+       _enter("{%p},,%d,,", object, *nr_pages);
+
+       if (!object->backer)
+               return -ENOBUFS;
+
+       space = 1;
+       if (cachefiles_has_space(cache, *nr_pages) < 0)
+               space = 0;
+
+       inode = object->backer->d_inode;
+       ASSERT(S_ISREG(inode->i_mode));
+       ASSERT(inode->i_mapping->a_ops->bmap);
+       ASSERT(inode->i_mapping->a_ops->readpages);
+
+       /* calculate the shift required to use bmap */
+       if (inode->i_sb->s_blocksize > PAGE_SIZE)
+               return -ENOBUFS;
+
+       shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
+
+       pagevec_init(&pagevec, 0);
+
+       cookie = object->fscache.cookie;
+
+       INIT_LIST_HEAD(&backpages);
+       nrbackpages = 0;
+
+       ret = space ? -ENODATA : -ENOBUFS;
+       list_for_each_entry_safe(page, _n, pages, lru) {
+               sector_t block0, block;
+
+               /* we assume the absence or presence of the first block is a
+                * good enough indication for the page as a whole
+                * - TODO: don't use bmap() for this as it is _not_ actually
+                *   good enough for this as it doesn't indicate errors, but
+                *   it's all we've got for the moment
+                */
+               block0 = page->index;
+               block0 <<= shift;
+
+               block = inode->i_mapping->a_ops->bmap(inode->i_mapping,
+                                                     block0);
+               _debug("%llx -> %llx", block0, block);
+
+               if (block) {
+                       /* we have data - add it to the list to give to the
+                        * backing fs */
+                       list_move(&page->lru, &backpages);
+                       (*nr_pages)--;
+                       nrbackpages++;
+               } else if (space && pagevec_add(&pagevec, page) == 0) {
+                       cookie->def->mark_pages_cached(cookie->netfs_data,
+                                                      mapping, &pagevec);
+                       pagevec_reinit(&pagevec);
+                       ret = -ENODATA;
+               }
+       }
+
+       if (pagevec_count(&pagevec) > 0) {
+               cookie->def->mark_pages_cached(cookie->netfs_data,
+                                              mapping, &pagevec);
+               pagevec_reinit(&pagevec);
+       }
+
+       if (list_empty(pages))
+               ret = 0;
+
+       /* submit the apparently valid pages to the backing fs to be read from disk */
+       if (nrbackpages > 0) {
+               ret2 = cachefiles_read_backing_file(object,
+                                                   end_io_func,
+                                                   context,
+                                                   mapping,
+                                                   &backpages,
+                                                   &pagevec);
+
+               ASSERTCMP(pagevec_count(&pagevec), ==, 0);
+
+               if (ret2 == -ENOMEM || ret2 == -EINTR)
+                       ret = ret2;
+       }
+
+       _leave(" = %d [nr=%u%s]",
+              ret, *nr_pages, list_empty(pages) ? " empty" : "");
+       return ret;
+
+}
+
+/*****************************************************************************/
+/*
+ * read a page from the cache or allocate a block in which to store it
+ * - cache withdrawal is prevented by the caller
+ * - returns -EINTR if interrupted
+ * - returns -ENOMEM if ran out of memory
+ * - returns -ENOBUFS if no buffers can be made available
+ * - returns -ENOBUFS if page is beyond EOF
+ * - otherwise:
+ *   - the metadata will be retained
+ *   - 0 will be returned
+ */
+static int cachefiles_allocate_page(struct fscache_object *_object,
+                                   struct page *page,
+                                   unsigned long gfp)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       cache = container_of(object->fscache.cache,
+                            struct cachefiles_cache, cache);
+
+       _enter("%p,{%lx},,,", object, page->index);
+
+       return cachefiles_has_space(cache, 1);
+
+}
+
+/*****************************************************************************/
+/*
+ * page storer
+ */
+void cachefiles_write_work(void *_object)
+{
+       struct cachefiles_one_write *writer;
+       struct cachefiles_object *object = _object;
+       int ret, max;
+
+       _enter("%p", object);
+
+       ASSERT(!irqs_disabled());
+
+       spin_lock_irq(&object->work_lock);
+       max = 8;
+
+       while (!list_empty(&object->write_list)) {
+               writer = list_entry(object->write_list.next,
+                                   struct cachefiles_one_write, obj_link);
+               list_del(&writer->obj_link);
+
+               spin_unlock_irq(&object->work_lock);
+
+               _debug("- store {%lu}", writer->netfs_page->index);
+
+               ret = generic_file_buffered_write_one_kernel_page(
+                       object->backer->d_inode->i_mapping,
+                       writer->netfs_page->index,
+                       writer->netfs_page);
+
+               if (ret == -ENOSPC) {
+                       ret = -ENOBUFS;
+               } else if (ret == -EIO) {
+                       cachefiles_io_error_obj(object,
+                                               "write page to backing file"
+                                               " failed");
+                       ret = -ENOBUFS;
+               }
+
+               _debug("- callback");
+               writer->end_io_func(writer->netfs_page,
+                                   writer->context,
+                                   ret);
+
+               _debug("- put net");
+               page_cache_release(writer->netfs_page);
+               fscache_put_context(object->fscache.cookie, writer->context);
+               kfree(writer);
+
+               /* let keventd have some air occasionally */
+               max--;
+               if (max < 0 || need_resched()) {
+                       if (!list_empty(&object->write_list))
+                               schedule_work(&object->write_work);
+                       _leave(" [maxed out]");
+                       return;
+               }
+
+               _debug("- next");
+               spin_lock_irq(&object->work_lock);
+       }
+
+       spin_unlock_irq(&object->work_lock);
+       _leave("");
+
+}
+
+/*****************************************************************************/
+/*
+ * request a page be stored in the cache
+ * - cache withdrawal is prevented by the caller
+ * - this request may be ignored if there's no cache block available, in which
+ *   case -ENOBUFS will be returned
+ * - if the op is in progress, 0 will be returned
+ */
+static int cachefiles_write_page(struct fscache_object *_object,
+                                struct page *page,
+                                fscache_rw_complete_t end_io_func,
+                                void *context,
+                                unsigned long gfp)
+{
+//     struct cachefiles_one_write *writer;
+       struct cachefiles_object *object;
+       int ret;
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+
+       _enter("%p,%p{%lx},,,", object, page, page->index);
+
+       if (!object->backer)
+               return -ENOBUFS;
+
+       ASSERT(S_ISREG(object->backer->d_inode->i_mode));
+
+#if 0 // set to 1 for deferred writing
+       /* queue the operation for deferred processing by keventd */
+       writer = kzalloc(sizeof(*writer), GFP_KERNEL);
+       if (!writer)
+               return -ENOMEM;
+
+       page_cache_get(page);
+       writer->netfs_page = page;
+       writer->object = object;
+       writer->end_io_func = end_io_func;
+       writer->context = facache_get_context(object->fscache.cookie, context);
+
+       spin_lock_irq(&object->work_lock);
+       list_add_tail(&writer->obj_link, &object->write_list);
+       spin_unlock_irq(&object->work_lock);
+
+       schedule_work(&object->write_work);
+       ret = 0;
+
+#else
+       /* copy the page to ext3 and let it store it in its own time */
+       ret = generic_file_buffered_write_one_kernel_page(
+               object->backer->d_inode->i_mapping, page->index, page);
+
+       if (ret != 0) {
+               if (ret == -EIO)
+                       cachefiles_io_error_obj(object,
+                                               "write page to backing file"
+                                               " failed");
+               ret = -ENOBUFS;
+       }
+
+       end_io_func(page, context, ret);
+#endif
+
+       _leave(" = %d", ret);
+       return ret;
+
+}
+
+/*****************************************************************************/
+/*
+ * detach a backing block from a page
+ * - cache withdrawal is prevented by the caller
+ */
+static void cachefiles_uncache_pages(struct fscache_object *_object,
+                                    struct pagevec *pagevec)
+{
+       struct cachefiles_object *object;
+       struct cachefiles_cache *cache;
+
+       object = container_of(_object, struct cachefiles_object, fscache);
+       cache = container_of(object->fscache.cache,
+                            struct cachefiles_cache, cache);
+
+       _enter("%p,{%lu,%lx},,,",
+              object, pagevec->nr, pagevec->pages[0]->index);
+
+}
+
+/*****************************************************************************/
+/*
+ * dissociate a cache from all the pages it was backing
+ */
+static void cachefiles_dissociate_pages(struct fscache_cache *cache)
+{
+       _enter("");
+
+}
+
+struct fscache_cache_ops cachefiles_cache_ops = {
+       .name                   = "cachefiles",
+       .lookup_object          = cachefiles_lookup_object,
+       .grab_object            = cachefiles_grab_object,
+       .lock_object            = cachefiles_lock_object,
+       .unlock_object          = cachefiles_unlock_object,
+       .update_object          = cachefiles_update_object,
+       .put_object             = cachefiles_put_object,
+       .sync_cache             = cachefiles_sync_cache,
+       .set_i_size             = cachefiles_set_i_size,
+       .read_or_alloc_page     = cachefiles_read_or_alloc_page,
+       .read_or_alloc_pages    = cachefiles_read_or_alloc_pages,
+       .allocate_page          = cachefiles_allocate_page,
+       .write_page             = cachefiles_write_page,
+       .uncache_pages          = cachefiles_uncache_pages,
+       .dissociate_pages       = cachefiles_dissociate_pages,
+};
diff --git a/fs/cachefiles/cf-key.c b/fs/cachefiles/cf-key.c
new file mode 100644 (file)
index 0000000..cfae5a7
--- /dev/null
@@ -0,0 +1,157 @@
+/* cf-key.c: Key to pathname encoder
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include "internal.h"
+
+static const char cachefiles_charmap[64] =
+       "0123456789"                    /* 0 - 9 */
+       "abcdefghijklmnopqrstuvwxyz"    /* 10 - 35 */
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"    /* 36 - 61 */
+       "_-"                            /* 62 - 63 */
+       ;
+
+static const char cachefiles_filecharmap[256] = {
+       /* we skip space and tab and control chars */
+       [ 33 ... 46 ] = 1,              /* '!' -> '.' */
+       /* we skip '/' as it's significant to pathwalk */
+       [ 48 ... 127 ] = 1,             /* '0' -> '~' */
+};
+
+/*****************************************************************************/
+/*
+ * turn the raw key into something cooked
+ * - the raw key should include the length in the two bytes at the front
+ * - the key may be up to 514 bytes in length (including the length word)
+ *   - "base64" encode the strange keys, mapping 3 bytes of raw to four of
+ *     cooked
+ *   - need to cut the cooked key into 252 char lengths (189 raw bytes)
+ */
+char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type)
+{
+       unsigned char csum, ch;
+       unsigned int acc;
+       char *key;
+       int loop, len, max, seg, mark, print;
+
+       _enter(",%d", keylen);
+
+       BUG_ON(keylen < 2 || keylen > 514);
+
+       csum = raw[0] + raw[1];
+       print = 1;
+       for (loop = 2; loop < keylen; loop++) {
+               ch = raw[loop];
+               csum += ch;
+               print &= cachefiles_filecharmap[ch];
+       }
+
+       if (print) {
+               /* if the path is usable ASCII, then we render it directly */
+               max = keylen - 2;
+               max += 2;       /* two base64'd length chars on the front */
+               max += 5;       /* @checksum/M */
+               max += 3 * 2;   /* maximum number of segment dividers (".../M")
+                                * is ((514 + 251) / 252) = 3
+                                */
+               max += 1;       /* NUL on end */
+       } else {
+               /* calculate the maximum length of the cooked key */
+               keylen = (keylen + 2) / 3;
+
+               max = keylen * 4;
+               max += 5;       /* @checksum/M */
+               max += 3 * 2;   /* maximum number of segment dividers (".../M")
+                                * is ((514 + 188) / 189) = 3
+                                */
+               max += 1;       /* NUL on end */
+       }
+
+       _debug("max: %d", max);
+
+       key = kmalloc(max, GFP_KERNEL);
+       if (!key)
+               return NULL;
+
+       len = 0;
+
+       /* build the cooked key */
+       sprintf(key, "@%02x/+", (unsigned) csum);
+       len = 5;
+       mark = len - 1;
+
+       if (print) {
+               acc = *(uint16_t *) raw;
+               raw += 2;
+
+               key[len + 1] = cachefiles_charmap[acc & 63];
+               acc >>= 6;
+               key[len] = cachefiles_charmap[acc & 63];
+               len += 2;
+
+               seg = 250;
+               for (loop = keylen; loop > 0; loop--) {
+                       if (seg <= 0) {
+                               key[len++] = '/';
+                               mark = len;
+                               key[len++] = '+';
+                               seg = 252;
+                       }
+
+                       key[len++] = *raw++;
+                       ASSERT(len < max);
+               }
+
+               switch (type) {
+               case FSCACHE_COOKIE_TYPE_INDEX:         type = 'I';     break;
+               case FSCACHE_COOKIE_TYPE_DATAFILE:      type = 'D';     break;
+               default:                                type = 'S';     break;
+               }
+       } else {
+               seg = 252;
+               for (loop = keylen; loop > 0; loop--) {
+                       if (seg <= 0) {
+                               key[len++] = '/';
+                               mark = len;
+                               key[len++] = '+';
+                               seg = 252;
+                       }
+
+                       acc = *raw++;
+                       acc |= *raw++ << 8;
+                       acc |= *raw++ << 16;
+
+                       _debug("acc: %06x", acc);
+
+                       key[len++] = cachefiles_charmap[acc & 63];
+                       acc >>= 6;
+                       key[len++] = cachefiles_charmap[acc & 63];
+                       acc >>= 6;
+                       key[len++] = cachefiles_charmap[acc & 63];
+                       acc >>= 6;
+                       key[len++] = cachefiles_charmap[acc & 63];
+
+                       ASSERT(len < max);
+               }
+
+               switch (type) {
+               case FSCACHE_COOKIE_TYPE_INDEX:         type = 'J';     break;
+               case FSCACHE_COOKIE_TYPE_DATAFILE:      type = 'E';     break;
+               default:                                type = 'T';     break;
+               }
+       }
+
+       key[mark] = type;
+       key[len] = 0;
+
+       _leave(" = %p %d:[%s]", key, len, key);
+       return key;
+}
diff --git a/fs/cachefiles/cf-main.c b/fs/cachefiles/cf-main.c
new file mode 100644 (file)
index 0000000..da8d020
--- /dev/null
@@ -0,0 +1,129 @@
+/* cf-main.c: network filesystem caching backend to use cache files on a
+ *            premounted filesystem
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/statfs.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include "internal.h"
+
+unsigned long cachefiles_debug;
+
+static int cachefiles_init(void);
+static void cachefiles_exit(void);
+
+fs_initcall(cachefiles_init);
+module_exit(cachefiles_exit);
+
+MODULE_DESCRIPTION("Mounted-filesystem based cache");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
+kmem_cache_t *cachefiles_object_jar;
+
+static void cachefiles_object_init_once(void *_object, kmem_cache_t *cachep,
+                                       unsigned long flags)
+{
+       struct cachefiles_object *object = _object;
+
+       switch (flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) {
+       case SLAB_CTOR_CONSTRUCTOR:
+               memset(object, 0, sizeof(*object));
+               fscache_object_init(&object->fscache);
+               init_rwsem(&object->sem);
+               spin_lock_init(&object->work_lock);
+               INIT_LIST_HEAD(&object->read_list);
+               INIT_LIST_HEAD(&object->read_pend_list);
+               INIT_WORK(&object->read_work, &cachefiles_read_copier_work,
+                         object);
+               INIT_LIST_HEAD(&object->write_list);
+               INIT_WORK(&object->write_work, &cachefiles_write_work, object);
+               break;
+
+       default:
+               break;
+       }
+}
+
+/*****************************************************************************/
+/*
+ * initialise the fs caching module
+ */
+static int __init cachefiles_init(void)
+{
+       struct proc_dir_entry *pde;
+       int ret;
+
+       /* create a proc entry to use as a handle for the userspace daemon */
+       ret = -ENOMEM;
+
+       pde = create_proc_entry("cachefiles", 0600, proc_root_fs);
+       if (!pde) {
+               kerror("Unable to create /proc/fs/cachefiles");
+               goto error_proc;
+       }
+
+       if (cachefiles_sysctl_init() < 0) {
+               kerror("Unable to create sysctl parameters");
+               goto error_object_jar;
+       }
+
+       pde->owner = THIS_MODULE;
+       pde->proc_fops = &cachefiles_proc_fops;
+       cachefiles_proc = pde;
+
+       /* create an object jar */
+       cachefiles_object_jar =
+               kmem_cache_create("cachefiles_object_jar",
+                                 sizeof(struct cachefiles_object),
+                                 0,
+                                 SLAB_HWCACHE_ALIGN,
+                                 cachefiles_object_init_once,
+                                 NULL);
+       if (!cachefiles_object_jar) {
+               printk(KERN_NOTICE
+                      "CacheFiles: Failed to allocate an object jar\n");
+               goto error_sysctl;
+       }
+
+       printk(KERN_INFO "CacheFiles: Loaded\n");
+       return 0;
+
+error_sysctl:
+       cachefiles_sysctl_cleanup();
+error_object_jar:
+       remove_proc_entry("cachefiles", proc_root_fs);
+error_proc:
+       kerror("failed to register: %d", ret);
+       return ret;
+}
+
+/*****************************************************************************/
+/*
+ * clean up on module removal
+ */
+static void __exit cachefiles_exit(void)
+{
+       printk(KERN_INFO "CacheFiles: Unloading\n");
+
+       kmem_cache_destroy(cachefiles_object_jar);
+       remove_proc_entry("cachefiles", proc_root_fs);
+       cachefiles_sysctl_cleanup();
+}
diff --git a/fs/cachefiles/cf-namei.c b/fs/cachefiles/cf-namei.c
new file mode 100644 (file)
index 0000000..20db88a
--- /dev/null
@@ -0,0 +1,825 @@
+/* cf-namei.c: CacheFiles path walking and related routines
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fsnotify.h>
+#include <linux/quotaops.h>
+#include <linux/xattr.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include "internal.h"
+
+/*****************************************************************************/
+/*
+ * record the fact that an object is now active
+ */
+static void cachefiles_mark_object_active(struct cachefiles_cache *cache,
+                                         struct cachefiles_object *object)
+{
+       struct cachefiles_object *xobject;
+       struct rb_node **_p, *_parent = NULL;
+       struct dentry *dentry;
+
+       write_lock(&cache->active_lock);
+
+       dentry = object->dentry;
+       _p = &cache->active_nodes.rb_node;
+       while (*_p) {
+               _parent = *_p;
+               xobject = rb_entry(_parent,
+                                  struct cachefiles_object, active_node);
+
+               if (xobject->dentry > dentry)
+                       _p = &(*_p)->rb_left;
+               else if (xobject->dentry < dentry)
+                       _p = &(*_p)->rb_right;
+               else
+                       BUG(); /* uh oh... this dentry shouldn't be here */
+       }
+
+       rb_link_node(&object->active_node, _parent, _p);
+       rb_insert_color(&object->active_node, &cache->active_nodes);
+
+       write_unlock(&cache->active_lock);
+}
+
+/*****************************************************************************/
+/*
+ * delete an object representation from the cache
+ * - file backed objects are unlinked
+ * - directory backed objects are stuffed into the graveyard for userspace to
+ *   delete
+ * - unlocks the directory mutex
+ */
+static int cachefiles_bury_object(struct cachefiles_cache *cache,
+                                 struct dentry *dir,
+                                 struct dentry *rep)
+{
+       struct dentry *grave, *alt, *trap;
+       struct qstr name;
+       const char *old_name;
+       char nbuffer[8 + 8 + 1];
+       int ret;
+
+       _enter(",'%*.*s','%*.*s'",
+              dir->d_name.len, dir->d_name.len, dir->d_name.name,
+              rep->d_name.len, rep->d_name.len, rep->d_name.name);
+
+       /* non-directories can just be unlinked */
+       if (!S_ISDIR(rep->d_inode->i_mode)) {
+               _debug("unlink stale object");
+               ret = dir->d_inode->i_op->unlink(dir->d_inode, rep);
+
+               mutex_unlock(&dir->d_inode->i_mutex);
+
+               if (ret == 0) {
+                       _debug("d_delete");
+                       d_delete(rep);
+               } else if (ret == -EIO) {
+                       cachefiles_io_error(cache, "Unlink failed");
+               }
+
+               _leave(" = %d", ret);
+               return ret;
+       }
+
+       /* directories have to be moved to the graveyard */
+       _debug("move stale object to graveyard");
+       mutex_unlock(&dir->d_inode->i_mutex);
+
+try_again:
+       /* first step is to make up a grave dentry in the graveyard */
+       sprintf(nbuffer, "%08x%08x",
+               (uint32_t) xtime.tv_sec,
+               (uint32_t) atomic_inc_return(&cache->gravecounter));
+
+       name.name = nbuffer;
+       name.len = strlen(name.name);
+
+       /* hash the name */
+       name.hash = full_name_hash(name.name, name.len);
+
+       if (dir->d_op && dir->d_op->d_hash) {
+               ret = dir->d_op->d_hash(dir, &name);
+               if (ret < 0) {
+                       if (ret == -EIO)
+                               cachefiles_io_error(cache, "Hash failed");
+
+                       _leave(" = %d", ret);
+                       return ret;
+               }
+       }
+
+       /* do the multiway lock magic */
+       trap = lock_rename(cache->graveyard, dir);
+
+       /* do some checks before getting the grave dentry */
+       if (rep->d_parent != dir) {
+               /* the entry was probably culled when we dropped the parent dir
+                * lock */
+               unlock_rename(cache->graveyard, dir);
+               _leave(" = 0 [culled?]");
+               return 0;
+       }
+
+       if (!S_ISDIR(cache->graveyard->d_inode->i_mode)) {
+               unlock_rename(cache->graveyard, dir);
+               cachefiles_io_error(cache, "Graveyard no longer a directory");
+               return -EIO;
+       }
+
+       if (trap == rep) {
+               unlock_rename(cache->graveyard, dir);
+               cachefiles_io_error(cache, "May not make directory loop");
+               return -EIO;
+       }
+
+       if (d_mountpoint(rep)) {
+               unlock_rename(cache->graveyard, dir);
+               cachefiles_io_error(cache, "Mountpoint in cache");
+               return -EIO;
+       }
+
+       /* see if there's a dentry already there for this name */
+       grave = d_lookup(cache->graveyard, &name);
+       if (!grave) {
+               _debug("not found");
+
+               grave = d_alloc(cache->graveyard, &name);
+               if (!grave) {
+                       unlock_rename(cache->graveyard, dir);
+                       _leave(" = -ENOMEM");
+                       return -ENOMEM;
+               }
+
+               alt = cache->graveyard->d_inode->i_op->lookup(
+                       cache->graveyard->d_inode, grave, NULL);
+               if (IS_ERR(alt)) {
+                       unlock_rename(cache->graveyard, dir);
+                       dput(grave);
+
+                       if (PTR_ERR(alt) == -ENOMEM) {
+                               _leave(" = -ENOMEM");
+                               return -ENOMEM;
+                       }
+
+                       cachefiles_io_error(cache, "Lookup error %ld",
+                                           PTR_ERR(alt));
+                       return -EIO;
+               }
+
+               if (alt) {
+                       dput(grave);
+                       grave = alt;
+               }
+       }
+
+       if (grave->d_inode) {
+               unlock_rename(cache->graveyard, dir);
+               dput(grave);
+               grave = NULL;
+               cond_resched();
+               goto try_again;
+       }
+
+       if (d_mountpoint(grave)) {
+               unlock_rename(cache->graveyard, dir);
+               dput(grave);
+               cachefiles_io_error(cache, "Mountpoint in graveyard");
+               return -EIO;
+       }
+
+       /* target should not be an ancestor of source */
+       if (trap == grave) {
+               unlock_rename(cache->graveyard, dir);
+               dput(grave);
+               cachefiles_io_error(cache, "May not make directory loop");
+               return -EIO;
+       }
+
+       /* attempt the rename */
+       DQUOT_INIT(dir->d_inode);
+       DQUOT_INIT(cache->graveyard->d_inode);
+
+       old_name = fsnotify_oldname_init(rep->d_name.name);
+
+       ret = dir->d_inode->i_op->rename(dir->d_inode, rep,
+                                        cache->graveyard->d_inode, grave);
+
+       if (ret == 0) {
+               d_move(rep, grave);
+               fsnotify_move(dir->d_inode, cache->graveyard->d_inode,
+                             old_name, rep->d_name.name, 1,
+                             grave->d_inode, rep->d_inode);
+       } else if (ret != -ENOMEM) {
+               cachefiles_io_error(cache, "Rename failed with error %d", ret);
+       }
+
+       fsnotify_oldname_free(old_name);
+
+       unlock_rename(cache->graveyard, dir);
+       dput(grave);
+       _leave(" = 0");
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * delete an object representation from the cache
+ */
+int cachefiles_delete_object(struct cachefiles_cache *cache,
+                            struct cachefiles_object *object)
+{
+       struct dentry *dir;
+       int ret;
+
+       _enter(",{%p}", object->dentry);
+
+       ASSERT(object->dentry);
+       ASSERT(object->dentry->d_inode);
+       ASSERT(object->dentry->d_parent);
+
+       dir = dget_parent(object->dentry);
+
+       mutex_lock(&dir->d_inode->i_mutex);
+       ret = cachefiles_bury_object(cache, dir, object->dentry);
+
+       dput(dir);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*****************************************************************************/
+/*
+ * walk from the parent object to the child object through the backing
+ * filesystem, creating directories as we go
+ */
+int cachefiles_walk_to_object(struct cachefiles_object *parent,
+                             struct cachefiles_object *object,
+                             char *key,
+                             struct cachefiles_xattr *auxdata)
+{
+       struct cachefiles_cache *cache;
+       struct dentry *dir, *next = NULL, *new;
+       struct qstr name;
+       uid_t fsuid;
+       gid_t fsgid;
+       int ret;
+
+       _enter("{%p}", parent->dentry);
+
+       cache = container_of(parent->fscache.cache,
+                            struct cachefiles_cache, cache);
+
+       ASSERT(parent->dentry);
+       ASSERT(parent->dentry->d_inode);
+
+       if (!(S_ISDIR(parent->dentry->d_inode->i_mode))) {
+               // TODO: convert file to dir
+               _leave("looking up in none directory");
+               return -ENOBUFS;
+       }
+
+       fsuid = current->fsuid;
+       fsgid = current->fsgid;
+       current->fsuid = 0;
+       current->fsgid = 0;
+
+       dir = dget(parent->dentry);
+
+advance:
+       /* attempt to transit the first directory component */
+       name.name = key;
+       key = strchr(key, '/');
+       if (key) {
+               name.len = key - (char *) name.name;
+               *key++ = 0;
+       } else {
+               name.len = strlen(name.name);
+       }
+
+       /* hash the name */
+       name.hash = full_name_hash(name.name, name.len);
+
+       if (dir->d_op && dir->d_op->d_hash) {
+               ret = dir->d_op->d_hash(dir, &name);
+               if (ret < 0) {
+                       cachefiles_io_error(cache, "Hash failed");
+                       goto error_out2;
+               }
+       }
+
+lookup_again:
+       /* search the current directory for the element name */
+       _debug("lookup '%s' %x", name.name, name.hash);
+
+       mutex_lock(&dir->d_inode->i_mutex);
+
+       next = d_lookup(dir, &name);
+       if (!next) {
+               _debug("not found");
+
+               new = d_alloc(dir, &name);
+               if (!new)
+                       goto nomem_d_alloc;
+
+               ASSERT(dir->d_inode->i_op);
+               ASSERT(dir->d_inode->i_op->lookup);
+
+               next = dir->d_inode->i_op->lookup(dir->d_inode, new, NULL);
+               if (IS_ERR(next))
+                       goto lookup_error;
+
+               if (!next)
+                       next = new;
+               else
+                       dput(new);
+
+               if (next->d_inode) {
+                       ret = -EPERM;
+                       if (!next->d_inode->i_op ||
+                           !next->d_inode->i_op->setxattr ||
+                           !next->d_inode->i_op->getxattr ||
+                           !next->d_inode->i_op->removexattr)
+                               goto error;
+
+                       if (key && (!next->d_inode->i_op->lookup ||
+                                   !next->d_inode->i_op->mkdir ||
+                                   !next->d_inode->i_op->create ||
+                                   !next->d_inode->i_op->rename ||
+                                   !next->d_inode->i_op->rmdir ||
+                                   !next->d_inode->i_op->unlink))
+                               goto error;
+               }
+       }
+
+       _debug("next -> %p %s", next, next->d_inode ? "positive" : "negative");
+
+       if (!key)
+               object->new = !next->d_inode;
+
+       /* we need to create the object if it's negative */
+       if (key || object->type == FSCACHE_COOKIE_TYPE_INDEX) {
+               /* index objects and intervening tree levels must be subdirs */
+               if (!next->d_inode) {
+                       DQUOT_INIT(dir->d_inode);
+                       ret = dir->d_inode->i_op->mkdir(dir->d_inode, next, 0);
+                       if (ret < 0)
+                               goto create_error;
+
+                       ASSERT(next->d_inode);
+
+                       fsnotify_mkdir(dir->d_inode, next);
+
+                       _debug("mkdir -> %p{%p{ino=%lu}}",
+                              next, next->d_inode, next->d_inode->i_ino);
+
+               } else if (!S_ISDIR(next->d_inode->i_mode)) {
+                       kerror("inode %lu is not a directory",
+                              next->d_inode->i_ino);
+                       ret = -ENOBUFS;
+                       goto error;
+               }
+
+       } else {
+               /* non-index objects start out life as files */
+               if (!next->d_inode) {
+                       DQUOT_INIT(dir->d_inode);
+                       ret = dir->d_inode->i_op->create(dir->d_inode, next,
+                                                        S_IFREG, NULL);
+                       if (ret < 0)
+                               goto create_error;
+
+                       ASSERT(next->d_inode);
+
+                       fsnotify_create(dir->d_inode, next);
+
+                       _debug("create -> %p{%p{ino=%lu}}",
+                              next, next->d_inode, next->d_inode->i_ino);
+
+               } else if (!S_ISDIR(next->d_inode->i_mode) &&
+                          !S_ISREG(next->d_inode->i_mode)
+                          ) {
+                       kerror("inode %lu is not a file or directory",
+                              next->d_inode->i_ino);
+                       ret = -ENOBUFS;
+                       goto error;
+               }
+       }
+
+       /* process the next component */
+       if (key) {
+               _debug("advance");
+               mutex_unlock(&dir->d_inode->i_mutex);
+               dput(dir);
+               dir = next;
+               next = NULL;
+               goto advance;
+       }
+
+       /* we've found the object we were looking for */
+       object->dentry = next;
+
+       /* if we've found that the terminal object exists, then we need to
+        * check its attributes and delete it if it's out of date */
+       if (!object->new) {
+               _debug("validate '%*.*s'",
+                      next->d_name.len, next->d_name.len, next->d_name.name);
+
+               ret = cachefiles_check_object_xattr(object, auxdata);
+               if (ret == -ESTALE) {
+                       /* delete the object (the deleter drops the directory
+                        * mutex) */
+                       object->dentry = NULL;
+
+                       ret = cachefiles_bury_object(cache, dir, next);
+                       dput(next);
+                       next = NULL;
+
+                       if (ret < 0)
+                               goto delete_error;
+
+                       _debug("redo lookup");
+                       goto lookup_again;
+               }
+       }
+
+       /* note that we're now using this object */
+       cachefiles_mark_object_active(cache, object);
+
+       mutex_unlock(&dir->d_inode->i_mutex);
+       dput(dir);
+       dir = NULL;
+
+       if (object->new) {
+               /* attach data to a newly constructed terminal object */
+               ret = cachefiles_set_object_xattr(object, auxdata);
+               if (ret < 0)
+                       goto check_error;
+       } else {
+               /* always update the atime on an object we've just looked up
+                * (this is used to keep track of culling, and atimes are only
+                * updated by read, write and readdir but not lookup or
+                * open) */
+               touch_atime(cache->mnt, next);
+       }
+
+       /* open a file interface onto a data file */
+       if (object->type != FSCACHE_COOKIE_TYPE_INDEX) {
+               if (S_ISREG(object->dentry->d_inode->i_mode)) {
+                       const struct address_space_operations *aops;
+
+                       ret = -EPERM;
+                       aops = object->dentry->d_inode->i_mapping->a_ops;
+                       if (!aops->bmap ||
+                           !aops->prepare_write ||
+                           !aops->commit_write)
+                               goto check_error;
+
+                       object->backer = object->dentry;
+               } else {
+                       BUG(); // TODO: open file in data-class subdir
+               }
+       }
+
+       current->fsuid = fsuid;
+       current->fsgid = fsgid;
+       object->new = 0;
+
+       _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino);
+       return 0;
+
+create_error:
+       if (ret == -EIO)
+               cachefiles_io_error(cache, "create/mkdir failed");
+       goto error;
+
+check_error:
+       write_lock(&cache->active_lock);
+       rb_erase(&object->active_node, &cache->active_nodes);
+       write_unlock(&cache->active_lock);
+
+       dput(object->dentry);
+       object->dentry = NULL;
+       goto error_out;
+
+delete_error:
+       _debug("delete error %d", ret);
+       goto error_out2;
+
+lookup_error:
+       _debug("lookup error %ld", PTR_ERR(next));
+       dput(new);
+       ret = PTR_ERR(next);
+       if (ret == -EIO)
+               cachefiles_io_error(cache, "Lookup failed");
+       next = NULL;
+       goto error;
+
+nomem_d_alloc:
+       ret = -ENOMEM;
+error:
+       mutex_unlock(&dir->d_inode->i_mutex);
+       dput(next);
+error_out2:
+       dput(dir);
+error_out:
+       current->fsuid = fsuid;
+       current->fsgid = fsgid;
+
+       _leave(" = ret");
+       return ret;
+}
+
+/*****************************************************************************/
+/*
+ * get a subdirectory
+ */
+struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
+                                       struct dentry *dir,
+                                       const char *dirname)
+{
+       struct dentry *subdir, *new;
+       struct qstr name;
+       uid_t fsuid;
+       gid_t fsgid;
+       int ret;
+
+       _enter("");
+
+       /* set up the name */
+       name.name = dirname;
+       name.len = strlen(dirname);
+       name.hash = full_name_hash(name.name, name.len);
+
+       if (dir->d_op && dir->d_op->d_hash) {
+               ret = dir->d_op->d_hash(dir, &name);
+               if (ret < 0) {
+                       if (ret == -EIO)
+                               kerror("Hash failed");
+                       _leave(" = %d", ret);
+                       return ERR_PTR(ret);
+               }
+       }
+
+       /* search the current directory for the element name */
+       _debug("lookup '%s' %x", name.name, name.hash);
+
+       fsuid = current->fsuid;
+       fsgid = current->fsgid;
+       current->fsuid = 0;
+       current->fsgid = 0;
+
+       mutex_lock(&dir->d_inode->i_mutex);
+
+       subdir = d_lookup(dir, &name);
+       if (!subdir) {
+               _debug("not found");
+
+               new = d_alloc(dir, &name);
+               if (!new)
+                       goto nomem_d_alloc;
+
+               subdir = dir->d_inode->i_op->lookup(dir->d_inode, new, NULL);
+               if (IS_ERR(subdir))
+                       goto lookup_error;
+
+               if (!subdir)
+                       subdir = new;
+               else
+                       dput(new);
+       }
+
+       _debug("subdir -> %p %s",
+              subdir, subdir->d_inode ? "positive" : "negative");
+
+       /* we need to create the subdir if it doesn't exist yet */
+       if (!subdir->d_inode) {
+               DQUOT_INIT(dir->d_inode);
+               ret = dir->d_inode->i_op->mkdir(dir->d_inode, subdir, 0700);
+               if (ret < 0)
+                       goto mkdir_error;
+
+               ASSERT(subdir->d_inode);
+
+               fsnotify_mkdir(dir->d_inode, subdir);
+
+               _debug("mkdir -> %p{%p{ino=%lu}}",
+                      subdir,
+                      subdir->d_inode,
+                      subdir->d_inode->i_ino);
+       }
+
+       mutex_unlock(&dir->d_inode->i_mutex);
+
+       current->fsuid = fsuid;
+       current->fsgid = fsgid;
+
+       /* we need to make sure the subdir is a directory */
+       ASSERT(subdir->d_inode);
+
+       if (!S_ISDIR(subdir->d_inode->i_mode)) {
+               kerror("%s is not a directory", dirname);
+               ret = -EIO;
+               goto check_error;
+       }
+
+       ret = -EPERM;
+       if (!subdir->d_inode->i_op ||
+           !subdir->d_inode->i_op->setxattr ||
+           !subdir->d_inode->i_op->getxattr ||
+           !subdir->d_inode->i_op->lookup ||
+           !subdir->d_inode->i_op->mkdir ||
+           !subdir->d_inode->i_op->create ||
+           !subdir->d_inode->i_op->rename ||
+           !subdir->d_inode->i_op->rmdir ||
+           !subdir->d_inode->i_op->unlink)
+               goto check_error;
+
+       _leave(" = [%lu]", subdir->d_inode->i_ino);
+       return subdir;
+
+check_error:
+       dput(subdir);
+       _leave(" = %d [check]", ret);
+       return ERR_PTR(ret);
+
+mkdir_error:
+       mutex_unlock(&dir->d_inode->i_mutex);
+       kerror("mkdir %s failed with error %d", dirname, ret);
+       goto error_out;
+
+lookup_error:
+       mutex_unlock(&dir->d_inode->i_mutex);
+       dput(new);
+       ret = PTR_ERR(subdir);
+       kerror("Lookup %s failed with error %d", dirname, ret);
+       goto error_out;
+
+nomem_d_alloc:
+       mutex_unlock(&dir->d_inode->i_mutex);
+       ret = -ENOMEM;
+       goto error_out;
+
+error_out:
+       current->fsuid = fsuid;
+       current->fsgid = fsgid;
+       _leave(" = %d", ret);
+       return ERR_PTR(ret);
+}
+
+/*****************************************************************************/
+/*
+ * cull an object if it's not in use
+ * - called only by cache manager daemon
+ */
+int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
+                   char *filename)
+{
+       struct cachefiles_object *object;
+       struct rb_node *_n;
+       struct dentry *victim, *new;
+       struct qstr name;
+       int ret;
+
+       _enter(",%*.*s/,%s",
+              dir->d_name.len, dir->d_name.len, dir->d_name.name, filename);
+
+       /* set up the name */
+       name.name = filename;
+       name.len = strlen(filename);
+       name.hash = full_name_hash(name.name, name.len);
+
+       if (dir->d_op && dir->d_op->d_hash) {
+               ret = dir->d_op->d_hash(dir, &name);
+               if (ret < 0) {
+                       if (ret == -EIO)
+                               cachefiles_io_error(cache, "Hash failed");
+                       _leave(" = %d", ret);
+                       return ret;
+               }
+       }
+
+       /* look up the victim */
+       mutex_lock(&dir->d_inode->i_mutex);
+
+       victim = d_lookup(dir, &name);
+       if (!victim) {
+               _debug("not found");
+
+               new = d_alloc(dir, &name);
+               if (!new)
+                       goto nomem_d_alloc;
+
+               victim = dir->d_inode->i_op->lookup(dir->d_inode, new, NULL);
+               if (IS_ERR(victim))
+                       goto lookup_error;
+
+               if (!victim)
+                       victim = new;
+               else
+                       dput(new);
+       }
+
+       _debug("victim -> %p %s",
+              victim, victim->d_inode ? "positive" : "negative");
+
+       /* if the object is no longer there then we probably retired the object
+        * at the netfs's request whilst the cull was in progress
+        */
+       if (!victim->d_inode) {
+               mutex_unlock(&dir->d_inode->i_mutex);
+               dput(victim);
+               _leave(" = -ENOENT [absent]");
+               return -ENOENT;
+       }
+
+       /* check to see if we're using this object */
+       read_lock(&cache->active_lock);
+
+       _n = cache->active_nodes.rb_node;
+
+       while (_n) {
+               object = rb_entry(_n, struct cachefiles_object, active_node);
+
+               if (object->dentry > victim)
+                       _n = _n->rb_left;
+               else if (object->dentry < victim)
+                       _n = _n->rb_right;
+               else
+                       goto object_in_use;
+       }
+
+       read_unlock(&cache->active_lock);
+
+       /* okay... the victim is not being used so we can cull it
+        * - start by marking it as stale
+        */
+       _debug("victim is cullable");
+
+       ret = cachefiles_remove_object_xattr(cache, victim);
+       if (ret < 0)
+               goto error_unlock;
+
+       /*  actually remove the victim (drops the dir mutex) */
+       _debug("bury");
+
+       ret = cachefiles_bury_object(cache, dir, victim);
+       if (ret < 0)
+               goto error;
+
+       dput(victim);
+       _leave(" = 0");
+       return 0;
+
+
+object_in_use:
+       read_unlock(&cache->active_lock);
+       mutex_unlock(&dir->d_inode->i_mutex);
+       dput(victim);
+       _leave(" = -EBUSY [in use]");
+       return -EBUSY;
+
+nomem_d_alloc:
+       mutex_unlock(&dir->d_inode->i_mutex);
+       _leave(" = -ENOMEM");
+       return -ENOMEM;
+
+lookup_error:
+       mutex_unlock(&dir->d_inode->i_mutex);
+       dput(new);
+       ret = PTR_ERR(victim);
+       if (ret == -EIO)
+               cachefiles_io_error(cache, "Lookup failed");
+       goto choose_error;
+
+error_unlock:
+       mutex_unlock(&dir->d_inode->i_mutex);
+error:
+       dput(victim);
+choose_error:
+       if (ret == -ENOENT) {
+               /* file or dir now absent - probably retired by netfs */
+               _leave(" = -ESTALE [absent]");
+               return -ESTALE;
+       }
+
+       if (ret != -ENOMEM) {
+               kerror("Internal error: %d", ret);
+               ret = -EIO;
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
diff --git a/fs/cachefiles/cf-proc.c b/fs/cachefiles/cf-proc.c
new file mode 100644 (file)
index 0000000..c14320e
--- /dev/null
@@ -0,0 +1,498 @@
+/* cf-proc.c: /proc/fs/cachefiles interface
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/namespace.h>
+#include <linux/statfs.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include "internal.h"
+
+static int cachefiles_proc_open(struct inode *, struct file *);
+static int cachefiles_proc_release(struct inode *, struct file *);
+static ssize_t cachefiles_proc_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t cachefiles_proc_write(struct file *, const char __user *, size_t, loff_t *);
+static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args);
+static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args);
+static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args);
+static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args);
+static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args);
+static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args);
+static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args);
+
+struct proc_dir_entry *cachefiles_proc;
+
+static unsigned long cachefiles_open;
+
+struct file_operations cachefiles_proc_fops = {
+       .open           = cachefiles_proc_open,
+       .release        = cachefiles_proc_release,
+       .read           = cachefiles_proc_read,
+       .write          = cachefiles_proc_write,
+};
+
+struct cachefiles_proc_cmd {
+       char name[8];
+       int (*handler)(struct cachefiles_cache *cache, char *args);
+};
+
+static const struct cachefiles_proc_cmd cachefiles_proc_cmds[] = {
+       { "bind",       cachefiles_proc_bind    },
+       { "brun",       cachefiles_proc_brun    },
+       { "bcull",      cachefiles_proc_bcull   },
+       { "bstop",      cachefiles_proc_bstop   },
+       { "cull",       cachefiles_proc_cull    },
+       { "debug",      cachefiles_proc_debug   },
+       { "dir",        cachefiles_proc_dir     },
+       { "tag",        cachefiles_proc_tag     },
+       { "",           NULL                    }
+};
+
+
+/*****************************************************************************/
+/*
+ * do various checks
+ */
+static int cachefiles_proc_open(struct inode *inode, struct file *file)
+{
+       struct cachefiles_cache *cache;
+
+       _enter("");
+
+       /* only the superuser may do this */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       /* /proc/fs/cachefiles may only be open once at a time */
+       if (xchg(&cachefiles_open, 1) == 1)
+               return -EBUSY;
+
+       /* allocate a cache record */
+       cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL);
+       if (!cache) {
+               cachefiles_open = 0;
+               return -ENOMEM;
+       }
+
+       cache->active_nodes = RB_ROOT;
+       rwlock_init(&cache->active_lock);
+
+       /* set default caching limits
+        * - limit at 1% free space
+        * - cull below 5% free space
+        * - cease culling above 7% free space
+        */
+       cache->brun_percent = 7;
+       cache->bcull_percent = 5;
+       cache->bstop_percent = 1;
+
+       file->private_data = cache;
+       cache->cachefilesd = file;
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * release a cache
+ */
+static int cachefiles_proc_release(struct inode *inode, struct file *file)
+{
+       struct cachefiles_cache *cache = file->private_data;
+
+       _enter("");
+
+       ASSERT(cache);
+
+       set_bit(CACHEFILES_DEAD, &cache->flags);
+
+       cachefiles_proc_unbind(cache);
+
+       ASSERT(!cache->active_nodes.rb_node);
+
+       /* clean up the control file interface */
+       cache->cachefilesd = NULL;
+       file->private_data = NULL;
+       cachefiles_open = 0;
+
+       kfree(cache);
+
+       _leave("");
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * read the cache state
+ */
+static ssize_t cachefiles_proc_read(struct file *file, char __user *_buffer,
+                                   size_t buflen, loff_t *pos)
+{
+       struct cachefiles_cache *cache = file->private_data;
+       char buffer[256];
+       int n;
+
+       _enter(",,%zu,", buflen);
+
+       if (!test_bit(CACHEFILES_READY, &cache->flags))
+               return 0;
+
+       /* check how much space the cache has */
+       cachefiles_has_space(cache, 0);
+
+       /* summarise */
+       n = snprintf(buffer, sizeof(buffer),
+                    "cull=%c"
+                    " brun=%llx"
+                    " bcull=%llx"
+                    " bstop=%llx",
+                    test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0',
+                    cache->brun,
+                    cache->bcull,
+                    cache->bstop
+                    );
+
+       if (n > buflen)
+               return -EMSGSIZE;
+
+       if (copy_to_user(_buffer, buffer, n) != 0)
+               return -EFAULT;
+
+       return n;
+}
+
+/*****************************************************************************/
+/*
+ * command the cache
+ */
+static ssize_t cachefiles_proc_write(struct file *file,
+                                    const char __user *_data, size_t datalen,
+                                    loff_t *pos)
+{
+       const struct cachefiles_proc_cmd *cmd;
+       struct cachefiles_cache *cache = file->private_data;
+       ssize_t ret;
+       char *data, *args, *cp;
+
+       _enter(",,%zu,", datalen);
+
+       ASSERT(cache);
+
+       if (test_bit(CACHEFILES_DEAD, &cache->flags))
+               return -EIO;
+
+       if (datalen < 0 || datalen > PAGE_SIZE - 1)
+               return -EOPNOTSUPP;
+
+       /* drag the command string into the kernel so we can parse it */
+       data = kmalloc(datalen + 1, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       ret = -EFAULT;
+       if (copy_from_user(data, _data, datalen) != 0)
+               goto error;
+
+       data[datalen] = '\0';
+
+       ret = -EINVAL;
+       if (memchr(data, '\0', datalen))
+               goto error;
+
+       /* strip any newline */
+       cp = memchr(data, '\n', datalen);
+       if (cp) {
+               if (cp == data)
+                       goto error;
+
+               *cp = '\0';
+       }
+
+       /* parse the command */
+       ret = -EOPNOTSUPP;
+
+       for (args = data; *args; args++)
+               if (isspace(*args))
+                       break;
+       if (*args) {
+               if (args == data)
+                       goto error;
+               *args = '\0';
+               for (args++; isspace(*args); args++)
+                       continue;
+       }
+
+       /* run the appropriate command handler */
+       for (cmd = cachefiles_proc_cmds; cmd->name[0]; cmd++)
+               if (strcmp(cmd->name, data) == 0)
+                       goto found_command;
+
+error:
+       kfree(data);
+       _leave(" = %d", ret);
+       return ret;
+
+found_command:
+       mutex_lock(&file->f_dentry->d_inode->i_mutex);
+
+       ret = -EIO;
+       if (!test_bit(CACHEFILES_DEAD, &cache->flags))
+               ret = cmd->handler(cache, args);
+
+       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+
+       if (ret == 0)
+               ret = datalen;
+       goto error;
+}
+
+/*****************************************************************************/
+/*
+ * give a range error for cache space constraints
+ * - can be tail-called
+ */
+static int cachefiles_proc_range_error(struct cachefiles_cache *cache, char *args)
+{
+       kerror("Free space limits must be in range"
+              " 0%%<=bstop<bcull<brun<100%%");
+
+       return -EINVAL;
+}
+
+/*****************************************************************************/
+/*
+ * set the percentage of blocks at which to stop culling
+ * - command: "brun <N>%"
+ */
+static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args)
+{
+       unsigned long brun;
+
+       _enter(",%s", args);
+
+       if (!*args)
+               return -EINVAL;
+
+       brun = simple_strtoul(args, &args, 10);
+       if (args[0] != '%' || args[1] != '\0')
+               return -EINVAL;
+
+       if (brun <= cache->bcull_percent || brun >= 100)
+               return cachefiles_proc_range_error(cache, args);
+
+       cache->brun_percent = brun;
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * set the percentage of blocks at which to start culling
+ * - command: "bcull <N>%"
+ */
+static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args)
+{
+       unsigned long bcull;
+
+       _enter(",%s", args);
+
+       if (!*args)
+               return -EINVAL;
+
+       bcull = simple_strtoul(args, &args, 10);
+       if (args[0] != '%' || args[1] != '\0')
+               return -EINVAL;
+
+       if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent)
+               return cachefiles_proc_range_error(cache, args);
+
+       cache->bcull_percent = bcull;
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * set the percentage of blocks at which to stop allocating
+ * - command: "bstop <N>%"
+ */
+static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args)
+{
+       unsigned long bstop;
+
+       _enter(",%s", args);
+
+       if (!*args)
+               return -EINVAL;
+
+       bstop = simple_strtoul(args, &args, 10);
+       if (args[0] != '%' || args[1] != '\0')
+               return -EINVAL;
+
+       if (bstop < 0 || bstop >= cache->bcull_percent)
+               return cachefiles_proc_range_error(cache, args);
+
+       cache->bstop_percent = bstop;
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * set the cache directory
+ * - command: "dir <name>"
+ */
+static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args)
+{
+       char *dir;
+
+       _enter(",%s", args);
+
+       if (!*args) {
+               kerror("Empty directory specified");
+               return -EINVAL;
+       }
+
+       if (cache->rootdirname) {
+               kerror("Second cache directory specified");
+               return -EEXIST;
+       }
+
+       dir = kstrdup(args, GFP_KERNEL);
+       if (!dir)
+               return -ENOMEM;
+
+       cache->rootdirname = dir;
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * set the cache tag
+ * - command: "tag <name>"
+ */
+static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args)
+{
+       char *tag;
+
+       _enter(",%s", args);
+
+       if (!*args) {
+               kerror("Empty tag specified");
+               return -EINVAL;
+       }
+
+       if (cache->tag)
+               return -EEXIST;
+
+       tag = kstrdup(args, GFP_KERNEL);
+       if (!tag)
+               return -ENOMEM;
+
+       cache->tag = tag;
+       return 0;
+}
+
+/*****************************************************************************/
+/*
+ * request a node in the cache be culled
+ * - command: "cull <dirfd> <name>"
+ */
+static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args)
+{
+       struct dentry *dir;
+       struct file *dirfile;
+       int dirfd, fput_needed, ret;
+
+       _enter(",%s", args);
+
+       dirfd = simple_strtoul(args, &args, 0);
+
+       if (!args || !isspace(*args))
+               goto inval;
+
+       while (isspace(*args))
+               args++;
+
+       if (!*args)
+               goto inval;
+
+       if (strchr(args, '/'))
+               goto inval;
+
+       if (!test_bit(CACHEFILES_READY, &cache->flags)) {
+               kerror("cull applied to unready cache");
+               return -EIO;
+       }
+
+       if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
+               kerror("cull applied to dead cache");
+               return -EIO;
+       }
+
+       /* extract the directory dentry from the fd */
+       dirfile = fget_light(dirfd, &fput_needed);
+       if (!dirfile) {
+               kerror("cull dirfd not open");
+               return -EBADF;
+       }
+
+       dir = dget(dirfile->f_dentry);
+       fput_light(dirfile, fput_needed);
+       dirfile = NULL;
+
+       if (!S_ISDIR(dir->d_inode->i_mode))
+               goto notdir;
+
+       ret = cachefiles_cull(cache, dir, args);
+
+       dput(dir);
+       _leave(" = %d", ret);
+       return ret;
+
+notdir:
+       dput(dir);
+       kerror("cull command requires dirfd to be a directory");
+       return -ENOTDIR;
+
+inval:
+       kerror("cull command requires dirfd and filename");
+       return -EINVAL;
+}
+
+/*****************************************************************************/
+/*
+ * set debugging mode
+ * - command: "debug <mask>"
+ */
+static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args)
+{
+       unsigned long mask;
+
+       _enter(",%s", args);
+
+       mask = simple_strtoul(args, &args, 0);
+
+       if (!args || !isspace(*args))
+               goto inval;
+
+       cachefiles_debug = mask;
+       _leave(" = 0");
+       return 0;
+
+inval:
+       kerror("debug command requires mask");
+       return -EINVAL;
+}
diff --git a/fs/cachefiles/cf-sysctl.c b/fs/cachefiles/cf-sysctl.c
new file mode 100644 (file)
index 0000000..4d6fc04
--- /dev/null
@@ -0,0 +1,69 @@
+/* cf-sysctl.c: Control parameters
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include "internal.h"
+
+static struct ctl_table_header *cachefiles_sysctl;
+
+/*
+ * Something that isn't CTL_ANY, CTL_NONE or a value that may clash.
+ * Use the same values as fs/nfs/sysctl.c
+ */
+#define CTL_UNNUMBERED -2
+
+static ctl_table cachefiles_sysctl_table[] = {
+        {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "debug",
+               .data           = &cachefiles_debug,
+               .maxlen         = sizeof(unsigned long),
+               .mode           = 0644,
+               .proc_handler   = &proc_doulongvec_minmax
+       },
+       { .ctl_name = 0 }
+};
+
+static ctl_table cachefiles_sysctl_dir[] = {
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "cachefiles",
+               .maxlen         = 0,
+               .mode           = 0555,
+               .child          = cachefiles_sysctl_table
+       },
+       { .ctl_name = 0 }
+};
+
+static ctl_table cachefiles_sysctl_root[] = {
+       {
+               .ctl_name = CTL_FS,
+               .procname = "fs",
+               .mode = 0555,
+               .child = cachefiles_sysctl_dir,
+       },
+       { .ctl_name = 0 }
+};
+
+int __init cachefiles_sysctl_init(void)
+{
+       cachefiles_sysctl = register_sysctl_table(cachefiles_sysctl_root, 0);
+       if (!cachefiles_sysctl)
+               return -ENOMEM;
+       return 0;
+}
+
+void __exit cachefiles_sysctl_cleanup(void)
+{
+       unregister_sysctl_table(cachefiles_sysctl);
+}
diff --git a/fs/cachefiles/cf-xattr.c b/fs/cachefiles/cf-xattr.c
new file mode 100644 (file)
index 0000000..8952bf0
--- /dev/null
@@ -0,0 +1,295 @@
+/* cf-xattr.c: CacheFiles extended attribute management
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fsnotify.h>
+#include <linux/quotaops.h>
+#include <linux/xattr.h>
+#include "internal.h"
+
+static const char cachefiles_xattr_cache[] = XATTR_USER_PREFIX "CacheFiles.cache";
+
+/*****************************************************************************/
+/*
+ * check the type label on an object
+ * - done using xattrs
+ */
+int cachefiles_check_object_type(struct cachefiles_object *object)
+{
+       struct dentry *dentry = object->dentry;
+       char type[3], xtype[3];
+       int ret;
+
+       ASSERT(dentry);
+       ASSERT(dentry->d_inode);
+       ASSERT(dentry->d_inode->i_op);
+       ASSERT(dentry->d_inode->i_op->setxattr);
+       ASSERT(dentry->d_inode->i_op->getxattr);
+
+       if (!object->fscache.cookie)
+               strcpy(type, "C3");
+       else
+               snprintf(type, 3, "%02x", object->fscache.cookie->def->type);
+
+       _enter("%p{%s}", object, type);
+
+       mutex_lock(&dentry->d_inode->i_mutex);
+
+       /* attempt to install a type label directly */
+       ret = dentry->d_inode->i_op->setxattr(dentry, cachefiles_xattr_cache,
+                                             type, 2, XATTR_CREATE);
+       if (ret == 0) {
+               _debug("SET");
+               fsnotify_xattr(dentry);
+               mutex_unlock(&dentry->d_inode->i_mutex);
+               goto error;
+       }
+
+       if (ret != -EEXIST) {
+               kerror("Can't set xattr on %*.*s [%lu] (err %d)",
+                      dentry->d_name.len, dentry->d_name.len,
+                      dentry->d_name.name, dentry->d_inode->i_ino,
+                      -ret);
+               goto error;
+       }
+
+       /* read the current type label */
+       ret = dentry->d_inode->i_op->getxattr(dentry, cachefiles_xattr_cache,
+                                             xtype, 3);
+       if (ret < 0) {
+               if (ret == -ERANGE)
+                       goto bad_type_length;
+
+               kerror("Can't read xattr on %*.*s [%lu] (err %d)",
+                      dentry->d_name.len, dentry->d_name.len,
+                      dentry->d_name.name, dentry->d_inode->i_ino,
+                      -ret);
+               goto error;
+       }
+
+       /* check the type is what we're expecting */
+       if (ret != 2)
+               goto bad_type_length;
+
+       if (xtype[0] != type[0] || xtype[1] != type[1])
+               goto bad_type;
+
+       ret = 0;
+
+error:
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       _leave(" = %d", ret);
+       return ret;
+
+bad_type_length:
+       kerror("Cache object %lu type xattr length incorrect",
+              dentry->d_inode->i_ino);
+       ret = -EIO;
+       goto error;
+
+bad_type:
+       xtype[2] = 0;
+       kerror("Cache object %*.*s [%lu] type %s not %s",
+              dentry->d_name.len, dentry->d_name.len,
+              dentry->d_name.name, dentry->d_inode->i_ino,
+              xtype, type);
+       ret = -EIO;
+       goto error;
+}
+
+/*****************************************************************************/
+/*
+ * set the state xattr on a cache file
+ */
+int cachefiles_set_object_xattr(struct cachefiles_object *object,
+                               struct cachefiles_xattr *auxdata)
+{
+       struct dentry *dentry = object->dentry;
+       int ret;
+
+       ASSERT(object->fscache.cookie);
+       ASSERT(dentry);
+       ASSERT(dentry->d_inode->i_op->setxattr);
+
+       _enter("%p,#%d", object, auxdata->len);
+
+       /* attempt to install the cache metadata directly */
+       mutex_lock(&dentry->d_inode->i_mutex);
+
+       _debug("SET %s #%u",
+              object->fscache.cookie->def->name, auxdata->len);
+
+       ret = dentry->d_inode->i_op->setxattr(dentry, cachefiles_xattr_cache,
+                                             &auxdata->type, auxdata->len,
+                                             XATTR_CREATE);
+       if (ret == 0)
+               fsnotify_xattr(dentry);
+       else if (ret != -ENOMEM)
+               cachefiles_io_error_obj(object,
+                                       "Failed to set xattr with error %d",
+                                       ret);
+
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+/*****************************************************************************/
+/*
+ * check the state xattr on a cache file
+ * - return -ESTALE if the object should be deleted
+ */
+int cachefiles_check_object_xattr(struct cachefiles_object *object,
+                                 struct cachefiles_xattr *auxdata)
+{
+       struct cachefiles_xattr *auxbuf;
+       struct dentry *dentry = object->dentry;
+       int ret;
+
+       _enter("%p,#%d", object, auxdata->len);
+
+       ASSERT(dentry);
+       ASSERT(dentry->d_inode);
+       ASSERT(dentry->d_inode->i_op->setxattr);
+       ASSERT(dentry->d_inode->i_op->getxattr);
+
+       auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
+       if (!auxbuf) {
+               _leave(" = -ENOMEM");
+               return -ENOMEM;
+       }
+
+       mutex_lock(&dentry->d_inode->i_mutex);
+
+       /* read the current type label */
+       ret = dentry->d_inode->i_op->getxattr(dentry, cachefiles_xattr_cache,
+                                             &auxbuf->type, 512 + 1);
+       if (ret < 0) {
+               if (ret == -ENODATA)
+                       goto stale; /* no attribute - power went off
+                                    * mid-cull? */
+
+               if (ret == -ERANGE)
+                       goto bad_type_length;
+
+               cachefiles_io_error_obj(object,
+                                       "can't read xattr on %lu (err %d)",
+                                       dentry->d_inode->i_ino, -ret);
+               goto error;
+       }
+
+       /* check the on-disk object */
+       if (ret < 1)
+               goto bad_type_length;
+
+       if (auxbuf->type != auxdata->type)
+               goto stale;
+
+       auxbuf->len = ret;
+
+       /* consult the netfs */
+       if (object->fscache.cookie->def->check_aux) {
+               fscache_checkaux_t result;
+               unsigned int dlen;
+
+               dlen = auxbuf->len - 1;
+
+               _debug("checkaux %s #%u",
+                      object->fscache.cookie->def->name, dlen);
+
+               result = object->fscache.cookie->def->check_aux(
+                       object->fscache.cookie->netfs_data,
+                       &auxbuf->data, dlen);
+
+               switch (result) {
+                       /* entry okay as is */
+               case FSCACHE_CHECKAUX_OKAY:
+                       goto okay;
+
+                       /* entry requires update */
+               case FSCACHE_CHECKAUX_NEEDS_UPDATE:
+                       break;
+
+                       /* entry requires deletion */
+               case FSCACHE_CHECKAUX_OBSOLETE:
+                       goto stale;
+
+               default:
+                       BUG();
+               }
+
+               /* update the current label */
+               ret = dentry->d_inode->i_op->setxattr(dentry,
+                                                     cachefiles_xattr_cache,
+                                                     &auxdata->type,
+                                                     auxdata->len,
+                                                     XATTR_REPLACE);
+               if (ret < 0) {
+                       cachefiles_io_error_obj(object,
+                                               "Can't update xattr on %lu"
+                                               " (error %d)",
+                                               dentry->d_inode->i_ino, -ret);
+                       goto error;
+               }
+       }
+
+okay:
+       ret = 0;
+
+error:
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       kfree(auxbuf);
+       _leave(" = %d", ret);
+       return ret;
+
+bad_type_length:
+       kerror("Cache object %lu xattr length incorrect",
+              dentry->d_inode->i_ino);
+       ret = -EIO;
+       goto error;
+
+stale:
+       ret = -ESTALE;
+       goto error;
+}
+
+/*****************************************************************************/
+/*
+ * remove the object's xattr to mark it stale
+ */
+int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
+                                  struct dentry *dentry)
+{
+       int ret;
+
+       mutex_lock(&dentry->d_inode->i_mutex);
+
+       ret = dentry->d_inode->i_op->removexattr(dentry,
+                                                cachefiles_xattr_cache);
+
+       mutex_unlock(&dentry->d_inode->i_mutex);
+
+       if (ret < 0) {
+               if (ret == -ENOENT || ret == -ENODATA)
+                       ret = 0;
+               else if (ret != -ENOMEM)
+                       cachefiles_io_error(cache,
+                                           "Can't remove xattr from %lu"
+                                           " (error %d)",
+                                           dentry->d_inode->i_ino, -ret);
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
new file mode 100644 (file)
index 0000000..edda6e7
--- /dev/null
@@ -0,0 +1,308 @@
+/* internal.h: general netfs cache on cache files internal defs
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ *
+ * CacheFiles layout:
+ *
+ *     /..../CacheDir/
+ *             index
+ *             0/
+ *             1/
+ *             2/
+ *               index
+ *               0/
+ *               1/
+ *               2/
+ *                 index
+ *                 0
+ *                 1
+ *                 2
+ */
+
+#include <linux/fscache-cache.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+struct cachefiles_cache;
+struct cachefiles_object;
+
+extern unsigned long cachefiles_debug;
+#define CACHEFILES_DEBUG_KENTER        1
+#define CACHEFILES_DEBUG_KLEAVE        2
+#define CACHEFILES_DEBUG_KDEBUG        4
+
+extern struct fscache_cache_ops cachefiles_cache_ops;
+extern struct proc_dir_entry *cachefiles_proc;
+extern struct file_operations cachefiles_proc_fops;
+
+/*****************************************************************************/
+/*
+ * node records
+ */
+struct cachefiles_object {
+       struct fscache_object           fscache;        /* fscache handle */
+       struct dentry                   *dentry;        /* the file/dir representing this object */
+       struct dentry                   *backer;        /* backing file */
+       loff_t                          i_size;         /* object size */
+       atomic_t                        usage;          /* basic object usage count */
+       atomic_t                        fscache_usage;  /* FSDEF object usage count */
+       uint8_t                         type;           /* object type */
+       uint8_t                         new;            /* T if object new */
+       spinlock_t                      work_lock;
+       struct rw_semaphore             sem;
+       struct work_struct              read_work;      /* read page copier */
+       struct list_head                read_list;      /* pages to copy */
+       struct list_head                read_pend_list; /* pages to pending read from backer */
+       struct work_struct              write_work;     /* page writer */
+       struct list_head                write_list;     /* pages to store */
+       struct rb_node                  active_node;    /* link in active tree (dentry is key) */
+};
+
+extern kmem_cache_t *cachefiles_object_jar;
+
+/*****************************************************************************/
+/*
+ * Cache files cache definition
+ */
+struct cachefiles_cache {
+       struct fscache_cache            cache;          /* FS-Cache record */
+       struct vfsmount                 *mnt;           /* mountpoint holding the cache */
+       struct dentry                   *graveyard;     /* directory into which dead objects go */
+       struct file                     *cachefilesd;   /* manager daemon handle */
+       struct rb_root                  active_nodes;   /* active nodes (can't be culled) */
+       rwlock_t                        active_lock;    /* lock for active_nodes */
+       atomic_t                        gravecounter;   /* graveyard uniquifier */
+       unsigned                        brun_percent;   /* when to stop culling (%) */
+       unsigned                        bcull_percent;  /* when to start culling (%) */
+       unsigned                        bstop_percent;  /* when to stop allocating (%) */
+       unsigned                        bsize;          /* cache's block size */
+       unsigned                        bshift;         /* min(log2 (PAGE_SIZE / bsize), 0) */
+       sector_t                        brun;           /* when to stop culling */
+       sector_t                        bcull;          /* when to start culling */
+       sector_t                        bstop;          /* when to stop allocating */
+       unsigned long                   flags;
+#define CACHEFILES_READY               0       /* T if cache prepared */
+#define CACHEFILES_DEAD                        1       /* T if cache dead */
+#define CACHEFILES_CULLING             2       /* T if cull engaged */
+       char                            *rootdirname;   /* name of cache root directory */
+       char                            *tag;           /* cache binding tag */
+};
+
+/*****************************************************************************/
+/*
+ * backing file read tracking
+ */
+struct cachefiles_one_read {
+       wait_queue_t                    monitor;        /* link into monitored waitqueue */
+       struct page                     *back_page;     /* backing file page we're waiting for */
+       struct page                     *netfs_page;    /* netfs page we're going to fill */
+       struct cachefiles_object        *object;
+       struct list_head                obj_link;       /* link in object's lists */
+       fscache_rw_complete_t           end_io_func;
+       void                            *context;
+};
+
+/*****************************************************************************/
+/*
+ * backing file write tracking
+ */
+struct cachefiles_one_write {
+       struct page                     *netfs_page;    /* netfs page to copy */
+       struct cachefiles_object        *object;
+       struct list_head                obj_link;       /* link in object's lists */
+       fscache_rw_complete_t           end_io_func;
+       void                            *context;
+};
+
+/*****************************************************************************/
+/*
+ * auxiliary data xattr buffer
+ */
+struct cachefiles_xattr {
+       uint16_t                        len;
+       uint8_t                         type;
+       uint8_t                         data[];
+};
+
+
+/* cf-bind.c */
+extern int cachefiles_proc_bind(struct cachefiles_cache *cache, char *args);
+extern void cachefiles_proc_unbind(struct cachefiles_cache *cache);
+
+/* cf-interface.c */
+extern void cachefiles_read_copier_work(void *_object);
+extern void cachefiles_write_work(void *_object);
+extern int cachefiles_has_space(struct cachefiles_cache *cache, unsigned nr);
+
+/* cf-key.c */
+extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type);
+
+/* cf-namei.c */
+extern int cachefiles_delete_object(struct cachefiles_cache *cache,
+                                   struct cachefiles_object *object);
+extern int cachefiles_walk_to_object(struct cachefiles_object *parent,
+                                    struct cachefiles_object *object,
+                                    char *key,
+                                    struct cachefiles_xattr *auxdata);
+extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
+                                              struct dentry *dir,
+                                              const char *name);
+
+extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
+                          char *filename);
+
+/* cf-sysctl.c */
+extern int __init cachefiles_sysctl_init(void);
+extern void __exit cachefiles_sysctl_cleanup(void);
+
+/* cf-xattr.c */
+extern int cachefiles_check_object_type(struct cachefiles_object *object);
+extern int cachefiles_set_object_xattr(struct cachefiles_object *object,
+                                      struct cachefiles_xattr *auxdata);
+extern int cachefiles_check_object_xattr(struct cachefiles_object *object,
+                                        struct cachefiles_xattr *auxdata);
+extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
+                                         struct dentry *dentry);
+
+
+/*****************************************************************************/
+/*
+ * error handling
+ */
+#define kerror(FMT,...) printk(KERN_ERR "CacheFiles: "FMT"\n" ,##__VA_ARGS__);
+
+#define cachefiles_io_error(___cache, FMT, ...)                \
+do {                                                   \
+       kerror("I/O Error: " FMT ,##__VA_ARGS__);       \
+       fscache_io_error(&(___cache)->cache);           \
+       set_bit(CACHEFILES_DEAD, &(___cache)->flags);   \
+} while(0)
+
+#define cachefiles_io_error_obj(object, FMT, ...)                      \
+do {                                                                   \
+       struct cachefiles_cache *___cache;                              \
+                                                                       \
+       ___cache = container_of((object)->fscache.cache,                \
+                               struct cachefiles_cache, cache);        \
+       cachefiles_io_error(___cache, FMT ,##__VA_ARGS__);              \
+} while(0)
+
+
+/*****************************************************************************/
+/*
+ * debug tracing
+ */
+#define dbgprintk(FMT,...) \
+       printk("[%-6.6s] "FMT"\n",current->comm ,##__VA_ARGS__)
+
+/* make sure we maintain the format strings, even when debugging is disabled */
+static inline void _dbprintk(const char *fmt, ...)
+       __attribute__((format(printf,1,2)));
+static inline void _dbprintk(const char *fmt, ...)
+{
+}
+
+#define kenter(FMT,...)        dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+#define kleave(FMT,...)        dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
+#define kdebug(FMT,...)        dbgprintk(FMT ,##__VA_ARGS__)
+
+
+#if defined(__KDEBUG)
+#define _enter(FMT,...)        kenter(FMT,##__VA_ARGS__)
+#define _leave(FMT,...)        kleave(FMT,##__VA_ARGS__)
+#define _debug(FMT,...)        kdebug(FMT,##__VA_ARGS__)
+
+#elif defined(CONFIG_CACHEFILES_DEBUG)
+#define _enter(FMT,...)                                        \
+do {                                                   \
+       if (cachefiles_debug & CACHEFILES_DEBUG_KENTER) \
+               kenter(FMT,##__VA_ARGS__);              \
+} while (0)
+
+#define _leave(FMT,...)                                        \
+do {                                                   \
+       if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE) \
+               kleave(FMT,##__VA_ARGS__);              \
+} while (0)
+
+#define _debug(FMT,...)                                        \
+do {                                                   \
+       if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG) \
+               kdebug(FMT,##__VA_ARGS__);              \
+} while (0)
+
+#else
+#define _enter(FMT,...)        _dbprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+#define _leave(FMT,...)        _dbprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
+#define _debug(FMT,...)        _dbprintk(FMT ,##__VA_ARGS__)
+#endif
+
+#if 1 // defined(__KDEBUGALL)
+
+#define ASSERT(X)                                                      \
+do {                                                                   \
+       if (unlikely(!(X))) {                                           \
+               printk(KERN_ERR "\n");                                  \
+               printk(KERN_ERR "CacheFiles: Assertion failed\n");      \
+               BUG();                                                  \
+       }                                                               \
+} while(0)
+
+#define ASSERTCMP(X, OP, Y)                                            \
+do {                                                                   \
+       if (unlikely(!((X) OP (Y)))) {                                  \
+               printk(KERN_ERR "\n");                                  \
+               printk(KERN_ERR "CacheFiles: Assertion failed\n");      \
+               printk(KERN_ERR "%lx " #OP " %lx is false\n",           \
+                      (unsigned long)(X), (unsigned long)(Y));         \
+               BUG();                                                  \
+       }                                                               \
+} while(0)
+
+#define ASSERTIF(C, X)                                                 \
+do {                                                                   \
+       if (unlikely((C) && !(X))) {                                    \
+               printk(KERN_ERR "\n");                                  \
+               printk(KERN_ERR "CacheFiles: Assertion failed\n");      \
+               BUG();                                                  \
+       }                                                               \
+} while(0)
+
+#define ASSERTIFCMP(C, X, OP, Y)                                       \
+do {                                                                   \
+       if (unlikely((C) && !((X) OP (Y)))) {                           \
+               printk(KERN_ERR "\n");                                  \
+               printk(KERN_ERR "CacheFiles: Assertion failed\n");      \
+               printk(KERN_ERR "%lx " #OP " %lx is false\n",           \
+                      (unsigned long)(X), (unsigned long)(Y));         \
+               BUG();                                                  \
+       }                                                               \
+} while(0)
+
+#else
+
+#define ASSERT(X)                              \
+do {                                           \
+} while(0)
+
+#define ASSERTCMP(X, OP, Y)                    \
+do {                                           \
+} while(0)
+
+#define ASSERTIF(C, X)                         \
+do {                                           \
+} while(0)
+
+#define ASSERTIFCMP(C, X, OP, Y)               \
+do {                                           \
+} while(0)
+
+#endif
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
new file mode 100644 (file)
index 0000000..d1705ab
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ *   fs/cifs/sess.c
+ *
+ *   SMB/CIFS session setup handling routines
+ *
+ *   Copyright (c) International Business Machines  Corp., 2006
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This 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 Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include <linux/utsname.h>
+
+extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
+                         unsigned char *p24);
+
+static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
+{
+       __u32 capabilities = 0;
+
+       /* init fields common to all four types of SessSetup */
+       /* note that header is initialized to zero in header_assemble */
+       pSMB->req.AndXCommand = 0xFF;
+       pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+       pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+       /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
+
+       /* BB verify whether signing required on neg or just on auth frame 
+          (and NTLM case) */
+
+       capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+                       CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+
+       if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+               pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+       if (ses->capabilities & CAP_UNICODE) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
+               capabilities |= CAP_UNICODE;
+       }
+       if (ses->capabilities & CAP_STATUS32) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+               capabilities |= CAP_STATUS32;
+       }
+       if (ses->capabilities & CAP_DFS) {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
+               capabilities |= CAP_DFS;
+       }
+       if (ses->capabilities & CAP_UNIX) {
+               capabilities |= CAP_UNIX;
+       }
+
+       /* BB check whether to init vcnum BB */
+       return capabilities;
+}
+
+static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
+                           const struct nls_table * nls_cp)
+{
+       char * bcc_ptr = *pbcc_area;
+       int bytes_ret = 0;
+
+       /* BB FIXME add check that strings total less
+       than 335 or will need to send them as arrays */
+
+       /* unicode strings, must be word aligned before the call */
+/*     if ((long) bcc_ptr % 2) {
+               *bcc_ptr = 0;
+               bcc_ptr++;
+       } */
+       /* copy user */
+       if(ses->userName == NULL) {
+               /* BB what about null user mounts - check that we do this BB */
+       } else { /* 300 should be long enough for any conceivable user name */
+               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
+                                         300, nls_cp);
+       }
+       bcc_ptr += 2 * bytes_ret;
+       bcc_ptr += 2; /* account for null termination */
+       /* copy domain */
+       if(ses->domainName == NULL)
+               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
+                                         "CIFS_LINUX_DOM", 32, nls_cp);
+       else
+               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, 
+                                         256, nls_cp);
+       bcc_ptr += 2 * bytes_ret;
+       bcc_ptr += 2;  /* account for null terminator */
+
+       /* Copy OS version */
+       bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
+                                 nls_cp);
+       bcc_ptr += 2 * bytes_ret;
+       bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
+                                 32, nls_cp);
+       bcc_ptr += 2 * bytes_ret;
+       bcc_ptr += 2; /* trailing null */
+
+       bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+                                  32, nls_cp);
+       bcc_ptr += 2 * bytes_ret;
+       bcc_ptr += 2; /* trailing null */
+
+       *pbcc_area = bcc_ptr;
+}
+
+static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
+                         const struct nls_table * nls_cp)
+{
+       char * bcc_ptr = *pbcc_area;
+
+       /* copy user */
+       /* BB what about null user mounts - check that we do this BB */
+        /* copy user */
+        if(ses->userName == NULL) {
+                /* BB what about null user mounts - check that we do this BB */
+        } else { /* 300 should be long enough for any conceivable user name */
+                strncpy(bcc_ptr, ses->userName, 300);
+        }
+       /* BB improve check for overflow */
+        bcc_ptr += strnlen(ses->userName, 300);
+       *bcc_ptr = 0;
+        bcc_ptr++; /* account for null termination */
+
+        /* copy domain */
+       
+        if(ses->domainName == NULL) {
+                strcpy(bcc_ptr, "CIFS_LINUX_DOM");
+               bcc_ptr += 14;  /* strlen(CIFS_LINUX_DOM) */
+       } else {
+                strncpy(bcc_ptr, ses->domainName, 256); 
+               bcc_ptr += strnlen(ses->domainName, 256);
+       }
+       *bcc_ptr = 0;
+       bcc_ptr++;
+
+       /* BB check for overflow here */
+
+       strcpy(bcc_ptr, "Linux version ");
+       bcc_ptr += strlen("Linux version ");
+       strcpy(bcc_ptr, system_utsname.release);
+       bcc_ptr += strlen(system_utsname.release) + 1;
+
+       strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+       bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+
+        *pbcc_area = bcc_ptr;
+}
+
+static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
+                            const struct nls_table * nls_cp)
+{
+       int rc = 0;
+       int words_left, len;
+       char * data = *pbcc_area;
+
+
+
+       cFYI(1,("bleft %d",bleft));
+
+
+       /* word align, if bytes remaining is not even */
+       if(bleft % 2) {
+               bleft--;
+               data++;
+       }
+       words_left = bleft / 2;
+
+       /* save off server operating system */
+       len = UniStrnlen((wchar_t *) data, words_left);
+
+/* We look for obvious messed up bcc or strings in response so we do not go off
+   the end since (at least) WIN2K and Windows XP have a major bug in not null
+   terminating last Unicode string in response  */
+       if(len >= words_left)
+               return rc;
+
+       if(ses->serverOS)
+               kfree(ses->serverOS);
+       /* UTF-8 string will not grow more than four times as big as UCS-16 */
+       ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
+       if(ses->serverOS != NULL) {
+               cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
+                                  nls_cp);
+       }
+       data += 2 * (len + 1);
+       words_left -= len + 1;
+
+       /* save off server network operating system */
+       len = UniStrnlen((wchar_t *) data, words_left);
+
+       if(len >= words_left)
+               return rc;
+
+       if(ses->serverNOS)
+               kfree(ses->serverNOS);
+       ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
+       if(ses->serverNOS != NULL) {
+               cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
+                                  nls_cp);
+               if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
+                       cFYI(1,("NT4 server"));
+                       ses->flags |= CIFS_SES_NT4;
+               }
+       }
+       data += 2 * (len + 1);
+       words_left -= len + 1;
+
+        /* save off server domain */
+        len = UniStrnlen((wchar_t *) data, words_left);
+
+        if(len > words_left)
+                return rc;
+
+        if(ses->serverDomain)
+                kfree(ses->serverDomain);
+        ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
+        if(ses->serverDomain != NULL) {
+                cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
+                                   nls_cp);
+                ses->serverDomain[2*len] = 0;
+                ses->serverDomain[(2*len) + 1] = 0;
+        }
+        data += 2 * (len + 1);
+        words_left -= len + 1;
+       
+       cFYI(1,("words left: %d",words_left));
+
+       return rc;
+}
+
+static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
+                            const struct nls_table * nls_cp)
+{
+       int rc = 0;
+       int len;
+       char * bcc_ptr = *pbcc_area;
+
+       cFYI(1,("decode sessetup ascii. bleft %d", bleft));
+       
+       len = strnlen(bcc_ptr, bleft);
+       if(len >= bleft)
+               return rc;
+       
+       if(ses->serverOS)
+               kfree(ses->serverOS);
+
+       ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
+       if(ses->serverOS)
+               strncpy(ses->serverOS, bcc_ptr, len);
+
+       bcc_ptr += len + 1;
+       bleft -= len + 1;
+
+       len = strnlen(bcc_ptr, bleft);
+       if(len >= bleft)
+               return rc;
+
+       if(ses->serverNOS)
+               kfree(ses->serverNOS);
+
+       ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
+       if(ses->serverNOS)
+               strncpy(ses->serverNOS, bcc_ptr, len);
+
+       bcc_ptr += len + 1;
+       bleft -= len + 1;
+
+        len = strnlen(bcc_ptr, bleft);
+        if(len > bleft)
+                return rc;
+
+        if(ses->serverDomain)
+                kfree(ses->serverDomain);
+
+        ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
+        if(ses->serverOS)
+                strncpy(ses->serverOS, bcc_ptr, len);
+
+        bcc_ptr += len + 1;
+       bleft -= len + 1;
+
+       cFYI(1,("ascii: bytes left %d",bleft));
+
+       return rc;
+}
+
+int 
+CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
+               const struct nls_table *nls_cp)
+{
+       int rc = 0;
+       int wct;
+       struct smb_hdr *smb_buf;
+       char *bcc_ptr;
+       char *str_area;
+       SESSION_SETUP_ANDX *pSMB;
+       __u32 capabilities;
+       int count;
+       int resp_buf_type = 0;
+       struct kvec iov[2];
+       enum securityEnum type;
+       __u16 action;
+       int bytes_remaining;
+
+       if(ses == NULL)
+               return -EINVAL;
+
+       type = ses->server->secType;
+
+       cFYI(1,("sess setup type %d",type));
+       if(type == LANMAN) {
+#ifndef CONFIG_CIFS_WEAK_PW_HASH
+               /* LANMAN and plaintext are less secure and off by default.
+               So we make this explicitly be turned on in kconfig (in the
+               build) and turned on at runtime (changed from the default)
+               in proc/fs/cifs or via mount parm.  Unfortunately this is
+               needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
+               return -EOPNOTSUPP;
+#endif
+               wct = 10; /* lanman 2 style sessionsetup */
+       } else if((type == NTLM) || (type == NTLMv2)) { 
+               /* For NTLMv2 failures eventually may need to retry NTLM */
+               wct = 13; /* old style NTLM sessionsetup */
+       } else /* same size for negotiate or auth, NTLMSSP or extended security */
+               wct = 12;
+
+       rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
+                           (void **)&smb_buf);
+       if(rc)
+               return rc;
+
+       pSMB = (SESSION_SETUP_ANDX *)smb_buf;
+
+       capabilities = cifs_ssetup_hdr(ses, pSMB);
+
+       /* we will send the SMB in two pieces,
+       a fixed length beginning part, and a
+       second part which will include the strings
+       and rest of bcc area, in order to avoid having
+       to do a large buffer 17K allocation */
+        iov[0].iov_base = (char *)pSMB;
+        iov[0].iov_len = smb_buf->smb_buf_length + 4;
+
+       /* 2000 big enough to fit max user, domain, NOS name etc. */
+       str_area = kmalloc(2000, GFP_KERNEL);
+       bcc_ptr = str_area;
+
+       if(type == LANMAN) {
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+               char lnm_session_key[CIFS_SESS_KEY_SIZE];
+
+               /* no capabilities flags in old lanman negotiation */
+
+               pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); 
+               /* BB calculate hash with password */
+               /* and copy into bcc */
+
+               calc_lanman_hash(ses, lnm_session_key);
+
+/* #ifdef CONFIG_CIFS_DEBUG2
+               cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
+                       CIFS_SESS_KEY_SIZE);
+#endif */
+               memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
+               bcc_ptr += CIFS_SESS_KEY_SIZE;
+
+               /* can not sign if LANMAN negotiated so no need
+               to calculate signing key? but what if server
+               changed to do higher than lanman dialect and
+               we reconnected would we ever calc signing_key? */
+
+               cFYI(1,("Negotiating LANMAN setting up strings"));
+               /* Unicode not allowed for LANMAN dialects */
+               ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+#endif    
+       } else if (type == NTLM) {
+               char ntlm_session_key[CIFS_SESS_KEY_SIZE];
+
+               pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+               pSMB->req_no_secext.CaseInsensitivePasswordLength =
+                       cpu_to_le16(CIFS_SESS_KEY_SIZE);
+               pSMB->req_no_secext.CaseSensitivePasswordLength =
+                       cpu_to_le16(CIFS_SESS_KEY_SIZE);
+       
+               /* calculate session key */
+               SMBNTencrypt(ses->password, ses->server->cryptKey,
+                            ntlm_session_key);
+
+               if(first_time) /* should this be moved into common code 
+                                 with similar ntlmv2 path? */
+                       cifs_calculate_mac_key(ses->server->mac_signing_key,
+                               ntlm_session_key, ses->password);
+               /* copy session key */
+
+               memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
+               bcc_ptr += CIFS_SESS_KEY_SIZE;
+               memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
+               bcc_ptr += CIFS_SESS_KEY_SIZE;
+               if(ses->capabilities & CAP_UNICODE) {
+                       /* unicode strings must be word aligned */
+                       if (iov[0].iov_len % 2) {
+                               *bcc_ptr = 0;
+                               bcc_ptr++;              
+                       }       
+                       unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
+               } else
+                       ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+       } else if (type == NTLMv2) {
+               char * v2_sess_key = 
+                       kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
+
+               /* BB FIXME change all users of v2_sess_key to
+                  struct ntlmv2_resp */
+
+               if(v2_sess_key == NULL) {
+                       cifs_small_buf_release(smb_buf);
+                       return -ENOMEM;
+               }
+
+               pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+
+               /* LM2 password would be here if we supported it */
+               pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+               /*      cpu_to_le16(LM2_SESS_KEY_SIZE); */
+
+               pSMB->req_no_secext.CaseSensitivePasswordLength =
+                       cpu_to_le16(sizeof(struct ntlmv2_resp));
+
+               /* calculate session key */
+               setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
+               if(first_time) /* should this be moved into common code
+                                 with similar ntlmv2 path? */
+               /*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
+                               response BB FIXME, v2_sess_key); */
+
+               /* copy session key */
+
+       /*      memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
+               bcc_ptr += LM2_SESS_KEY_SIZE; */
+               memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
+               bcc_ptr += sizeof(struct ntlmv2_resp);
+               kfree(v2_sess_key);
+               if(ses->capabilities & CAP_UNICODE) {
+                       if(iov[0].iov_len % 2) {
+                               *bcc_ptr = 0;
+                       }       bcc_ptr++;
+                       unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
+               } else
+                       ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+       } else /* NTLMSSP or SPNEGO */ {
+               pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+               capabilities |= CAP_EXTENDED_SECURITY;
+               pSMB->req.Capabilities = cpu_to_le32(capabilities);
+               /* BB set password lengths */
+       }
+
+       count = (long) bcc_ptr - (long) str_area;
+       smb_buf->smb_buf_length += count;
+
+       BCC_LE(smb_buf) = cpu_to_le16(count);
+
+       iov[1].iov_base = str_area;
+       iov[1].iov_len = count; 
+       rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
+       /* SMB request buf freed in SendReceive2 */
+
+       cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
+       if(rc)
+               goto ssetup_exit;
+
+       pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
+       smb_buf = (struct smb_hdr *)iov[0].iov_base;
+
+       if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
+               rc = -EIO;
+               cERROR(1,("bad word count %d", smb_buf->WordCount));
+               goto ssetup_exit;
+       }
+       action = le16_to_cpu(pSMB->resp.Action);
+       if (action & GUEST_LOGIN)
+               cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
+       ses->Suid = smb_buf->Uid;   /* UID left in wire format (le) */
+       cFYI(1, ("UID = %d ", ses->Suid));
+       /* response can have either 3 or 4 word count - Samba sends 3 */
+       /* and lanman response is 3 */
+       bytes_remaining = BCC(smb_buf);
+       bcc_ptr = pByteArea(smb_buf);
+
+       if(smb_buf->WordCount == 4) {
+               __u16 blob_len;
+               blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
+               bcc_ptr += blob_len;
+               if(blob_len > bytes_remaining) {
+                       cERROR(1,("bad security blob length %d", blob_len));
+                       rc = -EINVAL;
+                       goto ssetup_exit;
+               }
+               bytes_remaining -= blob_len;
+       }       
+
+       /* BB check if Unicode and decode strings */
+       if(smb_buf->Flags2 & SMBFLG2_UNICODE)
+               rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
+                                                  ses, nls_cp);
+       else
+               rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
+       
+ssetup_exit:
+       kfree(str_area);
+       if(resp_buf_type == CIFS_SMALL_BUFFER) {
+               cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
+               cifs_small_buf_release(iov[0].iov_base);
+       } else if(resp_buf_type == CIFS_LARGE_BUFFER)
+               cifs_buf_release(iov[0].iov_base);
+
+       return rc;
+}
diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile
new file mode 100644 (file)
index 0000000..10f17a3
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for general filesystem caching code
+#
+
+fscache-objs := \
+       cookie.o \
+       fsdef.o \
+       main.o \
+       page.o
+
+obj-$(CONFIG_FSCACHE) := fscache.o
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
new file mode 100644 (file)
index 0000000..9a6ac8b
--- /dev/null
@@ -0,0 +1,1045 @@
+/* cookie.c: general filesystem cache cookie management
+ *
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include "fscache-int.h"
+
+static LIST_HEAD(fscache_cache_tag_list);
+static LIST_HEAD(fscache_cache_list);
+static LIST_HEAD(fscache_netfs_list);
+static DECLARE_RWSEM(fscache_addremove_sem);
+static struct fscache_cache_tag fscache_nomem_tag;
+
+kmem_cache_t *fscache_cookie_jar;
+
+static void fscache_withdraw_object(struct fscache_cache *cache,
+                                   struct fscache_object *object);
+
+static void __fscache_cookie_put(struct fscache_cookie *cookie);
+
+static inline void fscache_cookie_put(struct fscache_cookie *cookie)
+{
+       /* check to see whether the cookie has already been released by looking
+        * for the poison when slab debugging is on */
+#ifdef CONFIG_DEBUG_SLAB
+       BUG_ON((atomic_read(&cookie->usage) & 0xffff0000) == 0x6b6b0000);
+#endif
+
+       BUG_ON(atomic_read(&cookie->usage) <= 0);
+
+       if (atomic_dec_and_test(&cookie->usage))
+               __fscache_cookie_put(cookie);
+
+}
+
+/*****************************************************************************/
+/*
+ * look up a cache tag
+ */
+struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
+{
+       struct fscache_cache_tag *tag, *xtag;
+
+       /* firstly check for the existence of the tag under read lock */
+       down_read(&fscache_addremove_sem);
+
+       list_for_each_entry(tag, &fscache_cache_tag_list, link) {
+               if (strcmp(tag->name, name) == 0) {
+                       atomic_inc(&tag->usage);
+                       up_read(&fscache_addremove_sem);
+                       return tag;
+               }
+       }
+
+       up_read(&fscache_addremove_sem);
+
+       /* the tag does not exist - create a candidate */
+       xtag = kmalloc(sizeof(*xtag) + strlen(name) + 1, GFP_KERNEL);
+       if (!xtag)
+               /* return a dummy tag if out of memory */
+               return &fscache_nomem_tag;
+
+       atomic_set(&xtag->usage, 1);
+       strcpy(xtag->name, name);
+
+       /* write lock, search again and add if still not present */
+       down_write(&fscache_addremove_sem);
+
+       list_for_each_entry(tag, &fscache_cache_tag_list, link) {
+               if (strcmp(tag->name, name) == 0) {
+                       atomic_inc(&tag->usage);
+                       up_write(&fscache_addremove_sem);
+                       kfree(xtag);
+                       return tag;
+               }
+       }
+
+       list_add_tail(&xtag->link, &fscache_cache_tag_list);
+       up_write(&fscache_addremove_sem);
+       return xtag;
+}
+
+/*****************************************************************************/
+/*
+ * release a reference to a cache tag
+ */
+void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
+{
+       if (tag != &fscache_nomem_tag) {
+               down_write(&fscache_addremove_sem);
+
+               if (atomic_dec_and_test(&tag->usage))
+                       list_del_init(&tag->link);
+               else
+                       tag = NULL;
+
+               up_write(&fscache_addremove_sem);
+
+               kfree(tag);
+       }
+}
+
+/*****************************************************************************/
+/*
+ * register a network filesystem for caching
+ */
+int __fscache_register_netfs(struct fscache_netfs *netfs)
+{
+       struct fscache_netfs *ptr;
+       int ret;
+
+       _enter("{%s}", netfs->name);
+
+       INIT_LIST_HEAD(&netfs->link);
+
+       /* allocate a cookie for the primary index */
+       netfs->primary_index =
+               kmem_cache_zalloc(fscache_cookie_jar, SLAB_KERNEL);
+
+       if (!netfs->primary_index) {
+               _leave(" = -ENOMEM");
+               return -ENOMEM;
+       }
+
+       /* initialise the primary index cookie */
+       atomic_set(&netfs->primary_index->usage, 1);
+       atomic_set(&netfs->primary_index->children, 0);
+
+       netfs->primary_index->def               = &fscache_fsdef_netfs_def;
+       netfs->primary_index->parent            = &fscache_fsdef_index;
+       netfs->primary_index->netfs             = netfs;
+       netfs->primary_index->netfs_data        = netfs;
+
+       atomic_inc(&netfs->primary_index->parent->usage);
+       atomic_inc(&netfs->primary_index->parent->children);
+
+       init_rwsem(&netfs->primary_index->sem);
+       INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
+
+       /* check the netfs type is not already present */
+       down_write(&fscache_addremove_sem);
+
+       ret = -EEXIST;
+       list_for_each_entry(ptr, &fscache_netfs_list, link) {
+               if (strcmp(ptr->name, netfs->name) == 0)
+                       goto already_registered;
+       }
+
+       list_add(&netfs->link, &fscache_netfs_list);
+       ret = 0;
+
+       printk("FS-Cache: netfs '%s' registered for caching\n", netfs->name);
+
+already_registered:
+       up_write(&fscache_addremove_sem);
+
+       if (ret < 0) {
+               netfs->primary_index->parent = NULL;
+               __fscache_cookie_put(netfs->primary_index);
+               netfs->primary_index = NULL;
+       }
+
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_register_netfs);
+
+/*****************************************************************************/
+/*
+ * unregister a network filesystem from the cache
+ * - all cookies must have been released first
+ */
+void __fscache_unregister_netfs(struct fscache_netfs *netfs)
+{
+       _enter("{%s.%u}", netfs->name, netfs->version);
+
+       down_write(&fscache_addremove_sem);
+
+       list_del(&netfs->link);
+       fscache_relinquish_cookie(netfs->primary_index, 0);
+
+       up_write(&fscache_addremove_sem);
+
+       printk("FS-Cache: netfs '%s' unregistered from caching\n",
+              netfs->name);
+
+       _leave("");
+}
+
+EXPORT_SYMBOL(__fscache_unregister_netfs);
+
+/*****************************************************************************/
+/*
+ * initialise a cache record
+ */
+void fscache_init_cache(struct fscache_cache *cache,
+                       struct fscache_cache_ops *ops,
+                       const char *idfmt,
+                       ...)
+{
+       va_list va;
+
+       memset(cache, 0, sizeof(*cache));
+
+       cache->ops = ops;
+
+       va_start(va, idfmt);
+       vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va);
+       va_end(va);
+
+       INIT_LIST_HEAD(&cache->link);
+       INIT_LIST_HEAD(&cache->object_list);
+       spin_lock_init(&cache->object_list_lock);
+       init_rwsem(&cache->withdrawal_sem);
+}
+
+EXPORT_SYMBOL(fscache_init_cache);
+
+/*****************************************************************************/
+/*
+ * declare a mounted cache as being open for business
+ */
+int fscache_add_cache(struct fscache_cache *cache,
+                     struct fscache_object *ifsdef,
+                     const char *tagname)
+{
+       struct fscache_cache_tag *tag;
+
+       BUG_ON(!cache->ops);
+       BUG_ON(!ifsdef);
+
+       cache->flags = 0;
+
+       if (!tagname)
+               tagname = cache->identifier;
+
+       BUG_ON(!tagname[0]);
+
+       _enter("{%s.%s},,%s", cache->ops->name, cache->identifier, tagname);
+
+       if (!cache->ops->grab_object(ifsdef))
+               BUG();
+
+       ifsdef->cookie = &fscache_fsdef_index;
+       ifsdef->cache = cache;
+       cache->fsdef = ifsdef;
+
+       down_write(&fscache_addremove_sem);
+
+       /* instantiate or allocate a cache tag */
+       list_for_each_entry(tag, &fscache_cache_tag_list, link) {
+               if (strcmp(tag->name, tagname) == 0) {
+                       if (tag->cache) {
+                               printk(KERN_ERR
+                                      "FS-Cache: cache tag '%s' already in use\n",
+                                      tagname);
+                               up_write(&fscache_addremove_sem);
+                               return -EEXIST;
+                       }
+
+                       atomic_inc(&tag->usage);
+                       goto found_cache_tag;
+               }
+       }
+
+       tag = kmalloc(sizeof(*tag) + strlen(tagname) + 1, GFP_KERNEL);
+       if (!tag) {
+               up_write(&fscache_addremove_sem);
+               return -ENOMEM;
+       }
+
+       atomic_set(&tag->usage, 1);
+       strcpy(tag->name, tagname);
+       list_add_tail(&tag->link, &fscache_cache_tag_list);
+
+found_cache_tag:
+       tag->cache = cache;
+       cache->tag = tag;
+
+       /* add the cache to the list */
+       list_add(&cache->link, &fscache_cache_list);
+
+       /* add the cache's netfs definition index object to the cache's
+        * list */
+       spin_lock(&cache->object_list_lock);
+       list_add_tail(&ifsdef->cache_link, &cache->object_list);
+       spin_unlock(&cache->object_list_lock);
+
+       /* add the cache's netfs definition index object to the top level index
+        * cookie as a known backing object */
+       down_write(&fscache_fsdef_index.sem);
+
+       hlist_add_head(&ifsdef->cookie_link,
+                      &fscache_fsdef_index.backing_objects);
+
+       atomic_inc(&fscache_fsdef_index.usage);
+
+       /* done */
+       up_write(&fscache_fsdef_index.sem);
+       up_write(&fscache_addremove_sem);
+
+       printk(KERN_NOTICE
+              "FS-Cache: Cache \"%s\" added (type %s)\n",
+              cache->tag->name, cache->ops->name);
+
+       _leave(" = 0 [%s]", cache->identifier);
+       return 0;
+}
+
+EXPORT_SYMBOL(fscache_add_cache);
+
+/*****************************************************************************/
+/*
+ * note a cache I/O error
+ */
+void fscache_io_error(struct fscache_cache *cache)
+{
+       set_bit(FSCACHE_IOERROR, &cache->flags);
+
+       printk(KERN_ERR "FS-Cache: Cache %s stopped due to I/O error\n",
+              cache->ops->name);
+}
+
+EXPORT_SYMBOL(fscache_io_error);
+
+/*****************************************************************************/
+/*
+ * withdraw an unmounted cache from the active service
+ */
+void fscache_withdraw_cache(struct fscache_cache *cache)
+{
+       struct fscache_object *object;
+
+       _enter("");
+
+       printk(KERN_NOTICE
+              "FS-Cache: Withdrawing cache \"%s\"\n",
+              cache->tag->name);
+
+       /* make the cache unavailable for cookie acquisition */
+       down_write(&cache->withdrawal_sem);
+
+       down_write(&fscache_addremove_sem);
+       list_del_init(&cache->link);
+       cache->tag->cache = NULL;
+       up_write(&fscache_addremove_sem);
+
+       /* mark all objects as being withdrawn */
+       spin_lock(&cache->object_list_lock);
+       list_for_each_entry(object, &cache->object_list, cache_link) {
+               set_bit(FSCACHE_OBJECT_WITHDRAWN, &object->flags);
+       }
+       spin_unlock(&cache->object_list_lock);
+
+       /* make sure all pages pinned by operations on behalf of the netfs are
+        * written to disc */
+       cache->ops->sync_cache(cache);
+
+       /* dissociate all the netfs pages backed by this cache from the block
+        * mappings in the cache */
+       cache->ops->dissociate_pages(cache);
+
+       /* we now have to destroy all the active objects pertaining to this
+        * cache */
+       spin_lock(&cache->object_list_lock);
+
+       while (!list_empty(&cache->object_list)) {
+               object = list_entry(cache->object_list.next,
+                                   struct fscache_object, cache_link);
+               list_del_init(&object->cache_link);
+               spin_unlock(&cache->object_list_lock);
+
+               _debug("withdraw %p", object->cookie);
+
+               /* we've extracted an active object from the tree - now dispose
+                * of it */
+               fscache_withdraw_object(cache, object);
+
+               spin_lock(&cache->object_list_lock);
+       }
+
+       spin_unlock(&cache->object_list_lock);
+
+       fscache_release_cache_tag(cache->tag);
+       cache->tag = NULL;
+
+       _leave("");
+}
+
+EXPORT_SYMBOL(fscache_withdraw_cache);
+
+/*****************************************************************************/
+/*
+ * withdraw an object from active service at the behest of the cache
+ * - need break the links to a cached object cookie
+ * - called under two situations:
+ *   (1) recycler decides to reclaim an in-use object
+ *   (2) a cache is unmounted
+ * - have to take care as the cookie can be being relinquished by the netfs
+ *   simultaneously
+ * - the active object is pinned by the caller holding a refcount on it
+ */
+static void fscache_withdraw_object(struct fscache_cache *cache,
+                                   struct fscache_object *object)
+{
+       struct fscache_cookie *cookie, *xcookie = NULL;
+
+       _enter(",%p", object);
+
+       /* first of all we have to break the links between the object and the
+        * cookie
+        * - we have to hold both semaphores BUT we have to get the cookie sem
+        *   FIRST
+        */
+       cache->ops->lock_object(object);
+
+       cookie = object->cookie;
+       if (cookie) {
+               /* pin the cookie so that is doesn't escape */
+               atomic_inc(&cookie->usage);
+
+               /* re-order the locks to avoid deadlock */
+               cache->ops->unlock_object(object);
+               down_write(&cookie->sem);
+               cache->ops->lock_object(object);
+
+               /* erase references from the object to the cookie */
+               hlist_del_init(&object->cookie_link);
+
+               xcookie = object->cookie;
+               object->cookie = NULL;
+
+               up_write(&cookie->sem);
+       }
+
+       cache->ops->unlock_object(object);
+
+       /* we've broken the links between cookie and object */
+       if (xcookie) {
+               fscache_cookie_put(xcookie);
+               cache->ops->put_object(object);
+       }
+
+       /* unpin the cookie */
+       if (cookie) {
+               if (cookie->def && cookie->def->now_uncached)
+                       cookie->def->now_uncached(cookie->netfs_data);
+               fscache_cookie_put(cookie);
+       }
+
+       _leave("");
+}
+
+/*****************************************************************************/
+/*
+ * select a cache on which to store an object
+ * - the cache addremove semaphore must be at least read-locked by the caller
+ * - the object will never be an index
+ */
+static struct fscache_cache *fscache_select_cache_for_object(struct fscache_cookie *cookie)
+{
+       struct fscache_cache_tag *tag;
+       struct fscache_object *object;
+       struct fscache_cache *cache;
+
+       _enter("");
+
+       if (list_empty(&fscache_cache_list)) {
+               _leave(" = NULL [no cache]");
+               return NULL;
+       }
+
+       /* we check the parent to determine the cache to use */
+       down_read(&cookie->parent->sem);
+
+       /* the first in the parent's backing list should be the preferred
+        * cache */
+       if (!hlist_empty(&cookie->parent->backing_objects)) {
+               object = hlist_entry(cookie->parent->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               cache = object->cache;
+               if (test_bit(FSCACHE_IOERROR, &cache->flags))
+                       cache = NULL;
+
+               up_read(&cookie->parent->sem);
+               _leave(" = %p [parent]", cache);
+               return cache;
+       }
+
+       /* the parent is unbacked */
+       if (cookie->parent->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
+               /* parent not an index and is unbacked */
+               up_read(&cookie->parent->sem);
+               _leave(" = NULL [parent ubni]");
+               return NULL;
+       }
+
+       up_read(&cookie->parent->sem);
+
+       if (!cookie->parent->def->select_cache)
+               goto no_preference;
+
+       /* ask the netfs for its preference */
+       tag = cookie->parent->def->select_cache(
+               cookie->parent->parent->netfs_data,
+               cookie->parent->netfs_data);
+
+       if (!tag)
+               goto no_preference;
+
+       if (tag == &fscache_nomem_tag) {
+               _leave(" = NULL [nomem tag]");
+               return NULL;
+       }
+
+       if (!tag->cache) {
+               _leave(" = NULL [unbacked tag]");
+               return NULL;
+       }
+
+       if (test_bit(FSCACHE_IOERROR, &tag->cache->flags))
+               return NULL;
+
+       _leave(" = %p [specific]", tag->cache);
+       return tag->cache;
+
+no_preference:
+       /* netfs has no preference - just select first cache */
+       cache = list_entry(fscache_cache_list.next,
+                          struct fscache_cache, link);
+       _leave(" = %p [first]", cache);
+       return cache;
+}
+
+/*****************************************************************************/
+/*
+ * get a backing object for a cookie from the chosen cache
+ * - the cookie must be write-locked by the caller
+ * - all parent indexes will be obtained recursively first
+ */
+static struct fscache_object *fscache_lookup_object(struct fscache_cookie *cookie,
+                                                   struct fscache_cache *cache)
+{
+       struct fscache_cookie *parent = cookie->parent;
+       struct fscache_object *pobject, *object;
+       struct hlist_node *_p;
+
+       _enter("{%s/%s},",
+              parent && parent->def ? parent->def->name : "",
+              cookie->def ? (char *) cookie->def->name : "<file>");
+
+       if (test_bit(FSCACHE_IOERROR, &cache->flags))
+               return NULL;
+
+       /* see if we have the backing object for this cookie + cache immediately
+        * to hand
+        */
+       object = NULL;
+       hlist_for_each_entry(object, _p,
+                            &cookie->backing_objects, cookie_link
+                            ) {
+               if (object->cache == cache)
+                       break;
+       }
+
+       if (object) {
+               _leave(" = %p [old]", object);
+               return object;
+       }
+
+       BUG_ON(!parent); /* FSDEF entries don't have a parent */
+
+       /* we don't have a backing cookie, so we need to consult the object's
+        * parent index in the selected cache and maybe insert an entry
+        * therein; so the first thing to do is make sure that the parent index
+        * is represented on disc
+        */
+       down_read(&parent->sem);
+
+       pobject = NULL;
+       hlist_for_each_entry(pobject, _p,
+                            &parent->backing_objects, cookie_link
+                            ) {
+               if (pobject->cache == cache)
+                       break;
+       }
+
+       if (!pobject) {
+               /* we don't know about the parent object */
+               up_read(&parent->sem);
+               down_write(&parent->sem);
+
+               pobject = fscache_lookup_object(parent, cache);
+               if (IS_ERR(pobject)) {
+                       up_write(&parent->sem);
+                       _leave(" = %ld [no ipobj]", PTR_ERR(pobject));
+                       return pobject;
+               }
+
+               _debug("pobject=%p", pobject);
+
+               BUG_ON(pobject->cookie != parent);
+
+               downgrade_write(&parent->sem);
+       }
+
+       /* now we can attempt to look up this object in the parent, possibly
+        * creating a representation on disc when we do so
+        */
+       object = cache->ops->lookup_object(cache, pobject, cookie);
+       up_read(&parent->sem);
+
+       if (IS_ERR(object)) {
+               _leave(" = %ld [no obj]", PTR_ERR(object));
+               return object;
+       }
+
+       /* keep track of it */
+       cache->ops->lock_object(object);
+
+       BUG_ON(!hlist_unhashed(&object->cookie_link));
+
+       /* attach to the cache's object list */
+       if (list_empty(&object->cache_link)) {
+               spin_lock(&cache->object_list_lock);
+               list_add(&object->cache_link, &cache->object_list);
+               spin_unlock(&cache->object_list_lock);
+       }
+
+       /* attach to the cookie */
+       object->cookie = cookie;
+       atomic_inc(&cookie->usage);
+       hlist_add_head(&object->cookie_link, &cookie->backing_objects);
+
+       /* done */
+       cache->ops->unlock_object(object);
+       _leave(" = %p [new]", object);
+       return object;
+}
+
+/*****************************************************************************/
+/*
+ * request a cookie to represent an object (index, datafile, xattr, etc)
+ * - parent specifies the parent object
+ *   - the top level index cookie for each netfs is stored in the fscache_netfs
+ *     struct upon registration
+ * - idef points to the definition
+ * - the netfs_data will be passed to the functions pointed to in *def
+ * - all attached caches will be searched to see if they contain this object
+ * - index objects aren't stored on disk until there's a dependent file that
+ *   needs storing
+ * - other objects are stored in a selected cache immediately, and all the
+ *   indexes forming the path to it are instantiated if necessary
+ * - we never let on to the netfs about errors
+ *   - we may set a negative cookie pointer, but that's okay
+ */
+struct fscache_cookie *__fscache_acquire_cookie(struct fscache_cookie *parent,
+                                               struct fscache_cookie_def *def,
+                                               void *netfs_data)
+{
+       struct fscache_cookie *cookie;
+       struct fscache_cache *cache;
+       struct fscache_object *object;
+       int ret = 0;
+
+       BUG_ON(!def);
+
+       _enter("{%s},{%s},%p",
+              parent ? (char *) parent->def->name : "<no-parent>",
+              def->name, netfs_data);
+
+       /* if there's no parent cookie, then we don't create one here either */
+       if (!parent) {
+               _leave(" [no parent]");
+               return NULL;
+       }
+
+       /* validate the definition */
+       BUG_ON(!def->get_key);
+       BUG_ON(!def->name[0]);
+
+       BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
+              parent->def->type != FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* allocate and initialise a cookie */
+       cookie = kmem_cache_alloc(fscache_cookie_jar, SLAB_KERNEL);
+       if (!cookie) {
+               _leave(" [ENOMEM]");
+               return NULL;
+       }
+
+       atomic_set(&cookie->usage, 1);
+       atomic_set(&cookie->children, 0);
+
+       atomic_inc(&parent->usage);
+       atomic_inc(&parent->children);
+
+       cookie->def             = def;
+       cookie->parent          = parent;
+       cookie->netfs           = parent->netfs;
+       cookie->netfs_data      = netfs_data;
+
+       /* now we need to see whether the backing objects for this cookie yet
+        * exist, if not there'll be nothing to search */
+       down_read(&fscache_addremove_sem);
+
+       if (list_empty(&fscache_cache_list)) {
+               up_read(&fscache_addremove_sem);
+               _leave(" = %p [no caches]", cookie);
+               return cookie;
+       }
+
+       /* if the object is an index then we need do nothing more here - we
+        * create indexes on disk when we need them as an index may exist in
+        * multiple caches */
+       if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
+               down_write(&cookie->sem);
+
+               /* the object is a file - we need to select a cache in which to
+                * store it */
+               cache = fscache_select_cache_for_object(cookie);
+               if (!cache)
+                       goto no_cache; /* couldn't decide on a cache */
+
+               /* create a file index entry on disc, along with all the
+                * indexes required to find it again later */
+               object = fscache_lookup_object(cookie, cache);
+               if (IS_ERR(object)) {
+                       ret = PTR_ERR(object);
+                       goto error;
+               }
+
+               up_write(&cookie->sem);
+       }
+out:
+       up_read(&fscache_addremove_sem);
+       _leave(" = %p", cookie);
+       return cookie;
+
+no_cache:
+       ret = -ENOMEDIUM;
+       goto error_cleanup;
+error:
+       printk(KERN_ERR "FS-Cache: error from cache: %d\n", ret);
+error_cleanup:
+       if (cookie) {
+               up_write(&cookie->sem);
+               __fscache_cookie_put(cookie);
+               cookie = NULL;
+               atomic_dec(&parent->children);
+       }
+
+       goto out;
+}
+
+EXPORT_SYMBOL(__fscache_acquire_cookie);
+
+/*****************************************************************************/
+/*
+ * release a cookie back to the cache
+ * - the object will be marked as recyclable on disc if retire is true
+ * - all dependents of this cookie must have already been unregistered
+ *   (indexes/files/pages)
+ */
+void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
+{
+       struct fscache_cache *cache;
+       struct fscache_object *object;
+       struct hlist_node *_p;
+
+       if (!cookie) {
+               _leave(" [no cookie]");
+               return;
+       }
+
+       _enter("%p{%s},%d", cookie, cookie->def->name, retire);
+
+       if (atomic_read(&cookie->children) != 0) {
+               printk("FS-Cache: cookie still has children\n");
+               BUG();
+       }
+
+       /* detach pointers back to the netfs */
+       down_write(&cookie->sem);
+
+       cookie->netfs_data      = NULL;
+       cookie->def             = NULL;
+
+       /* mark retired objects for recycling */
+       if (retire) {
+               hlist_for_each_entry(object, _p,
+                                    &cookie->backing_objects,
+                                    cookie_link
+                                    ) {
+                       set_bit(FSCACHE_OBJECT_RECYCLING, &object->flags);
+               }
+       }
+
+       /* break links with all the active objects */
+       while (!hlist_empty(&cookie->backing_objects)) {
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object,
+                                    cookie_link);
+
+               /* detach each cache object from the object cookie */
+               set_bit(FSCACHE_OBJECT_RELEASING, &object->flags);
+
+               hlist_del_init(&object->cookie_link);
+
+               cache = object->cache;
+               cache->ops->lock_object(object);
+               object->cookie = NULL;
+               cache->ops->unlock_object(object);
+
+               if (atomic_dec_and_test(&cookie->usage))
+                       /* the cookie refcount shouldn't be reduced to 0 yet */
+                       BUG();
+
+               spin_lock(&cache->object_list_lock);
+               list_del_init(&object->cache_link);
+               spin_unlock(&cache->object_list_lock);
+
+               cache->ops->put_object(object);
+       }
+
+       up_write(&cookie->sem);
+
+       if (cookie->parent) {
+#ifdef CONFIG_DEBUG_SLAB
+               BUG_ON((atomic_read(&cookie->parent->children) & 0xffff0000) == 0x6b6b0000);
+#endif
+               atomic_dec(&cookie->parent->children);
+       }
+
+       /* finally dispose of the cookie */
+       fscache_cookie_put(cookie);
+
+       _leave("");
+}
+
+EXPORT_SYMBOL(__fscache_relinquish_cookie);
+
+/*****************************************************************************/
+/*
+ * update the index entries backing a cookie
+ */
+void __fscache_update_cookie(struct fscache_cookie *cookie)
+{
+       struct fscache_object *object;
+       struct hlist_node *_p;
+
+       if (!cookie) {
+               _leave(" [no cookie]");
+               return;
+       }
+
+       _enter("{%s}", cookie->def->name);
+
+       BUG_ON(!cookie->def->get_aux);
+
+       down_write(&cookie->sem);
+       down_read(&cookie->parent->sem);
+
+       /* update the index entry on disc in each cache backing this cookie */
+       hlist_for_each_entry(object, _p,
+                            &cookie->backing_objects, cookie_link
+                            ) {
+               if (!test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       object->cache->ops->update_object(object);
+       }
+
+       up_read(&cookie->parent->sem);
+       up_write(&cookie->sem);
+       _leave("");
+}
+
+EXPORT_SYMBOL(__fscache_update_cookie);
+
+/*****************************************************************************/
+/*
+ * destroy a cookie
+ */
+static void __fscache_cookie_put(struct fscache_cookie *cookie)
+{
+       struct fscache_cookie *parent;
+
+       _enter("%p", cookie);
+
+       for (;;) {
+               parent = cookie->parent;
+               BUG_ON(!hlist_empty(&cookie->backing_objects));
+               kmem_cache_free(fscache_cookie_jar, cookie);
+
+               if (!parent)
+                       break;
+
+               cookie = parent;
+               BUG_ON(atomic_read(&cookie->usage) <= 0);
+               if (!atomic_dec_and_test(&cookie->usage))
+                       break;
+       }
+
+       _leave("");
+}
+
+/*****************************************************************************/
+/*
+ * initialise an cookie jar slab element prior to any use
+ */
+void fscache_cookie_init_once(void *_cookie, kmem_cache_t *cachep,
+                             unsigned long flags)
+{
+       struct fscache_cookie *cookie = _cookie;
+
+       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+           SLAB_CTOR_CONSTRUCTOR) {
+               memset(cookie, 0, sizeof(*cookie));
+               init_rwsem(&cookie->sem);
+               INIT_HLIST_HEAD(&cookie->backing_objects);
+       }
+}
+
+/*****************************************************************************/
+/*
+ * pin an object into the cache
+ */
+int __fscache_pin_cookie(struct fscache_cookie *cookie)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p", cookie);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" = -ENOBUFS");
+               return -ENOBUFS;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from being uncached whilst we access it and exclude
+        * read and write attempts on pages
+        */
+       down_write(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and pin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               if (!object->cache->ops->pin_object) {
+                       ret = -EOPNOTSUPP;
+                       goto out;
+               }
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               ret = object->cache->ops->pin_object(object);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_write(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_pin_cookie);
+
+/*****************************************************************************/
+/*
+ * unpin an object into the cache
+ */
+void __fscache_unpin_cookie(struct fscache_cookie *cookie)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p", cookie);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" [no obj]");
+               return;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from being uncached whilst we access it and exclude
+        * read and write attempts on pages
+        */
+       down_write(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and unpin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               if (!object->cache->ops->unpin_object)
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               object->cache->ops->unpin_object(object);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_write(&cookie->sem);
+       _leave("");
+}
+
+EXPORT_SYMBOL(__fscache_unpin_cookie);
diff --git a/fs/fscache/fscache-int.h b/fs/fscache/fscache-int.h
new file mode 100644 (file)
index 0000000..d075660
--- /dev/null
@@ -0,0 +1,93 @@
+/* fscache-int.h: internal definitions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _FSCACHE_INT_H
+#define _FSCACHE_INT_H
+
+#include <linux/fscache-cache.h>
+#include <linux/timer.h>
+#include <linux/bio.h>
+
+extern kmem_cache_t *fscache_cookie_jar;
+
+extern struct fscache_cookie fscache_fsdef_index;
+extern struct fscache_cookie_def fscache_fsdef_netfs_def;
+
+extern void fscache_cookie_init_once(void *_cookie, kmem_cache_t *cachep, unsigned long flags);
+
+/*
+ * prevent the cache from being withdrawn whilst an operation is in progress
+ * - returns false if the cache is being withdrawn already or if the cache is
+ *   waiting to withdraw itself
+ * - returns true if the cache was not being withdrawn
+ * - fscache_withdraw_cache() will wait using down_write() until all ops are
+ *   complete
+ */
+static inline int fscache_operation_lock(struct fscache_object *object)
+{
+       return down_read_trylock(&object->cache->withdrawal_sem);
+}
+
+/*
+ * release the operation lock
+ */
+static inline void fscache_operation_unlock(struct fscache_object *object)
+{
+       up_read(&object->cache->withdrawal_sem);
+}
+
+
+/*****************************************************************************/
+/*
+ * debug tracing
+ */
+#define dbgprintk(FMT,...) \
+       printk("[%-6.6s] "FMT"\n",current->comm ,##__VA_ARGS__)
+#define _dbprintk(FMT,...) do { } while(0)
+
+#define kenter(FMT,...)        dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+#define kleave(FMT,...)        dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
+#define kdebug(FMT,...)        dbgprintk(FMT ,##__VA_ARGS__)
+
+#define kjournal(FMT,...) _dbprintk(FMT ,##__VA_ARGS__)
+
+#define dbgfree(ADDR)  _dbprintk("%p:%d: FREEING %p",__FILE__,__LINE__,ADDR)
+
+#define dbgpgalloc(PAGE)                                               \
+do {                                                                   \
+       _dbprintk("PGALLOC %s:%d: %p {%lx,%lu}\n",                      \
+                 __FILE__,__LINE__,                                    \
+                 (PAGE),(PAGE)->mapping->host->i_ino,(PAGE)->index     \
+                 );                                                    \
+} while(0)
+
+#define dbgpgfree(PAGE)                                                \
+do {                                                           \
+       if ((PAGE))                                             \
+               _dbprintk("PGFREE %s:%d: %p {%lx,%lu}\n",       \
+                         __FILE__,__LINE__,                    \
+                         (PAGE),                               \
+                         (PAGE)->mapping->host->i_ino,         \
+                         (PAGE)->index                         \
+                         );                                    \
+} while(0)
+
+#ifdef __KDEBUG
+#define _enter(FMT,...)        kenter(FMT,##__VA_ARGS__)
+#define _leave(FMT,...)        kleave(FMT,##__VA_ARGS__)
+#define _debug(FMT,...)        kdebug(FMT,##__VA_ARGS__)
+#else
+#define _enter(FMT,...)        do { } while(0)
+#define _leave(FMT,...)        do { } while(0)
+#define _debug(FMT,...)        do { } while(0)
+#endif
+
+#endif /* _FSCACHE_INT_H */
diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c
new file mode 100644 (file)
index 0000000..495f633
--- /dev/null
@@ -0,0 +1,110 @@
+/* fsdef.c: filesystem index definition
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include "fscache-int.h"
+
+static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data,
+                                           void *buffer, uint16_t bufmax);
+
+static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data,
+                                           void *buffer, uint16_t bufmax);
+
+static fscache_checkaux_t fscache_fsdef_netfs_check_aux(void *cookie_netfs_data,
+                                                       const void *data,
+                                                       uint16_t datalen);
+
+struct fscache_cookie_def fscache_fsdef_netfs_def = {
+       .name           = "FSDEF.netfs",
+       .type           = FSCACHE_COOKIE_TYPE_INDEX,
+       .get_key        = fscache_fsdef_netfs_get_key,
+       .get_aux        = fscache_fsdef_netfs_get_aux,
+       .check_aux      = fscache_fsdef_netfs_check_aux,
+};
+
+struct fscache_cookie fscache_fsdef_index = {
+       .usage          = ATOMIC_INIT(1),
+       .def            = NULL,
+       .sem            = __RWSEM_INITIALIZER(fscache_fsdef_index.sem),
+       .backing_objects = HLIST_HEAD_INIT,
+};
+
+EXPORT_SYMBOL(fscache_fsdef_index);
+
+/*****************************************************************************/
+/*
+ * get the key data for an FSDEF index record
+ */
+static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data,
+                                           void *buffer, uint16_t bufmax)
+{
+       const struct fscache_netfs *netfs = cookie_netfs_data;
+       unsigned klen;
+
+       _enter("{%s.%u},", netfs->name, netfs->version);
+
+       klen = strlen(netfs->name);
+       if (klen > bufmax)
+               return 0;
+
+       memcpy(buffer, netfs->name, klen);
+       return klen;
+}
+
+/*****************************************************************************/
+/*
+ * get the auxilliary data for an FSDEF index record
+ */
+static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data,
+                                           void *buffer, uint16_t bufmax)
+{
+       const struct fscache_netfs *netfs = cookie_netfs_data;
+       unsigned dlen;
+
+       _enter("{%s.%u},", netfs->name, netfs->version);
+
+       dlen = sizeof(uint32_t);
+       if (dlen > bufmax)
+               return 0;
+
+       memcpy(buffer, &netfs->version, dlen);
+       return dlen;
+}
+
+/*****************************************************************************/
+/*
+ * check that the version stored in the auxilliary data is correct
+ */
+static fscache_checkaux_t fscache_fsdef_netfs_check_aux(void *cookie_netfs_data,
+                                                       const void *data,
+                                                       uint16_t datalen)
+{
+       struct fscache_netfs *netfs = cookie_netfs_data;
+       uint32_t version;
+
+       _enter("{%s},,%hu", netfs->name, datalen);
+
+       if (datalen != sizeof(version)) {
+               _leave(" = OBSOLETE [dl=%d v=%d]",
+                      datalen, sizeof(version));
+               return FSCACHE_CHECKAUX_OBSOLETE;
+       }
+
+       memcpy(&version, data, sizeof(version));
+       if (version != netfs->version) {
+               _leave(" = OBSOLETE [ver=%x net=%x]",
+                      version, netfs->version);
+               return FSCACHE_CHECKAUX_OBSOLETE;
+       }
+
+       _leave(" = OKAY");
+       return FSCACHE_CHECKAUX_OKAY;
+}
diff --git a/fs/fscache/main.c b/fs/fscache/main.c
new file mode 100644 (file)
index 0000000..d73068c
--- /dev/null
@@ -0,0 +1,105 @@
+/* main.c: general filesystem caching manager
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include "fscache-int.h"
+
+int fscache_debug;
+
+static int fscache_init(void);
+static void fscache_exit(void);
+
+fs_initcall(fscache_init);
+module_exit(fscache_exit);
+
+MODULE_DESCRIPTION("FS Cache Manager");
+MODULE_AUTHOR("Red Hat, Inc.");
+MODULE_LICENSE("GPL");
+
+static void fscache_ktype_release(struct kobject *kobject);
+
+static struct sysfs_ops fscache_sysfs_ops = {
+       .show           = NULL,
+       .store          = NULL,
+};
+
+static struct kobj_type fscache_ktype = {
+       .release        = fscache_ktype_release,
+       .sysfs_ops      = &fscache_sysfs_ops,
+       .default_attrs  = NULL,
+};
+
+struct kset fscache_kset = {
+       .kobj.name      = "fscache",
+       .kobj.kset      = &fs_subsys.kset,
+       .ktype          = &fscache_ktype,
+};
+
+EXPORT_SYMBOL(fscache_kset);
+
+/*****************************************************************************/
+/*
+ * initialise the fs caching module
+ */
+static int __init fscache_init(void)
+{
+       int ret;
+
+       fscache_cookie_jar =
+               kmem_cache_create("fscache_cookie_jar",
+                                 sizeof(struct fscache_cookie),
+                                 0,
+                                 0,
+                                 fscache_cookie_init_once,
+                                 NULL);
+
+       if (!fscache_cookie_jar) {
+               printk(KERN_NOTICE
+                      "FS-Cache: Failed to allocate a cookie jar\n");
+               return -ENOMEM;
+       }
+
+       ret = kset_register(&fscache_kset);
+       if (ret < 0) {
+               kmem_cache_destroy(fscache_cookie_jar);
+               return ret;
+       }
+
+       printk(KERN_NOTICE "FS-Cache: Loaded\n");
+       return 0;
+
+}
+
+/*****************************************************************************/
+/*
+ * clean up on module removal
+ */
+static void __exit fscache_exit(void)
+{
+       _enter("");
+
+       kset_unregister(&fscache_kset);
+       kmem_cache_destroy(fscache_cookie_jar);
+       printk(KERN_NOTICE "FS-Cache: unloaded\n");
+
+}
+
+/*****************************************************************************/
+/*
+ * release the ktype
+ */
+static void fscache_ktype_release(struct kobject *kobject)
+{
+}
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
new file mode 100644 (file)
index 0000000..fbb7716
--- /dev/null
@@ -0,0 +1,537 @@
+/* page.c: general filesystem cache cookie management
+ *
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/fscache-cache.h>
+#include <linux/buffer_head.h>
+#include <linux/pagevec.h>
+#include "fscache-int.h"
+
+/*****************************************************************************/
+/*
+ * set the data file size on an object in the cache
+ */
+int __fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,%llu,", cookie, i_size);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" = -ENOBUFS");
+               return -ENOBUFS;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from being uncached whilst we access it and exclude
+        * read and write attempts on pages
+        */
+       down_write(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and pin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (object->cache->ops->set_i_size &&
+                   fscache_operation_lock(object)
+                   ) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               ret = object->cache->ops->set_i_size(object,
+                                                                    i_size);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_write(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_set_i_size);
+
+/*****************************************************************************/
+/*
+ * reserve space for an object
+ */
+int __fscache_reserve_space(struct fscache_cookie *cookie, loff_t size)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,%llu,", cookie, size);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" = -ENOBUFS");
+               return -ENOBUFS;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from being uncached whilst we access it and exclude
+        * read and write attempts on pages
+        */
+       down_write(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and pin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               if (!object->cache->ops->reserve_space) {
+                       ret = -EOPNOTSUPP;
+                       goto out;
+               }
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               ret = object->cache->ops->reserve_space(object,
+                                                                       size);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_write(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_reserve_space);
+
+/*****************************************************************************/
+/*
+ * read a page from the cache or allocate a block in which to store it
+ * - we return:
+ *   -ENOMEM   - out of memory, nothing done
+ *   -EINTR    - interrupted
+ *   -ENOBUFS  - no backing object available in which to cache the block
+ *   -ENODATA  - no data available in the backing object for this block
+ *   0         - dispatched a read - it'll call end_io_func() when finished
+ */
+int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
+                                struct page *page,
+                                fscache_rw_complete_t end_io_func,
+                                void *context,
+                                gfp_t gfp)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,{%lu},", cookie, page->index);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" -ENOBUFS [no backing objects]");
+               return -ENOBUFS;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from being uncached whilst we access it */
+       down_read(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and pin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               ret = object->cache->ops->read_or_alloc_page(
+                                       object,
+                                       page,
+                                       end_io_func,
+                                       context,
+                                       gfp);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_read(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_read_or_alloc_page);
+
+/*****************************************************************************/
+/*
+ * read a list of page from the cache or allocate a block in which to store
+ * them
+ * - we return:
+ *   -ENOMEM   - out of memory, some pages may be being read
+ *   -EINTR    - interrupted, some pages may be being read
+ *   -ENOBUFS  - no backing object or space available in which to cache any
+ *                pages not being read
+ *   -ENODATA  - no data available in the backing object for some or all of
+ *                the pages
+ *   0         - dispatched a read on all pages
+ *
+ * end_io_func() will be called for each page read from the cache as it is
+ * finishes being read
+ *
+ * any pages for which a read is dispatched will be removed from pages and
+ * nr_pages
+ */
+int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
+                                 struct address_space *mapping,
+                                 struct list_head *pages,
+                                 unsigned *nr_pages,
+                                 fscache_rw_complete_t end_io_func,
+                                 void *context,
+                                 gfp_t gfp)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,,%d,,,", cookie, *nr_pages);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" -ENOBUFS [no backing objects]");
+               return -ENOBUFS;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+       BUG_ON(list_empty(pages));
+       BUG_ON(*nr_pages <= 0);
+
+       /* prevent the file from being uncached whilst we access it */
+       down_read(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and pin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               ret = object->cache->ops->read_or_alloc_pages(
+                                       object,
+                                       mapping,
+                                       pages,
+                                       nr_pages,
+                                       end_io_func,
+                                       context,
+                                       gfp);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_read(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_read_or_alloc_pages);
+
+/*****************************************************************************/
+/*
+ * allocate a block in the cache on which to store a page
+ * - we return:
+ *   -ENOMEM   - out of memory, nothing done
+ *   -EINTR    - interrupted
+ *   -ENOBUFS  - no backing object available in which to cache the block
+ *   0         - block allocated
+ */
+int __fscache_alloc_page(struct fscache_cookie *cookie,
+                        struct page *page,
+                        gfp_t gfp)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,{%lu},", cookie, page->index);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" -ENOBUFS [no backing objects]");
+               return -ENOBUFS;
+       }
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from being uncached whilst we access it */
+       down_read(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               /* get and pin the backing object */
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       if (object->cache->ops->grab_object(object)) {
+                               /* ask the cache to honour the operation */
+                               ret = object->cache->ops->allocate_page(object,
+                                                                       page,
+                                                                       gfp);
+
+                               object->cache->ops->put_object(object);
+                       }
+
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_read(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_alloc_page);
+
+/*****************************************************************************/
+/*
+ * request a page be stored in the cache
+ * - returns:
+ *   -ENOMEM   - out of memory, nothing done
+ *   -EINTR    - interrupted
+ *   -ENOBUFS  - no backing object available in which to cache the page
+ *   0         - dispatched a write - it'll call end_io_func() when finished
+ */
+int __fscache_write_page(struct fscache_cookie *cookie,
+                        struct page *page,
+                        fscache_rw_complete_t end_io_func,
+                        void *context,
+                        gfp_t gfp)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,{%lu},", cookie, page->index);
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from been uncached whilst we deal with it */
+       down_read(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       /* ask the cache to honour the operation */
+                       ret = object->cache->ops->write_page(object,
+                                                            page,
+                                                            end_io_func,
+                                                            context,
+                                                            gfp);
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_read(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_write_page);
+
+/*****************************************************************************/
+/*
+ * request several pages be stored in the cache
+ * - returns:
+ *   -ENOMEM   - out of memory, nothing done
+ *   -EINTR    - interrupted
+ *   -ENOBUFS  - no backing object available in which to cache the page
+ *   0         - dispatched a write - it'll call end_io_func() when finished
+ */
+int __fscache_write_pages(struct fscache_cookie *cookie,
+                         struct pagevec *pagevec,
+                         fscache_rw_complete_t end_io_func,
+                         void *context,
+                         gfp_t gfp)
+{
+       struct fscache_object *object;
+       int ret;
+
+       _enter("%p,{%ld},", cookie, pagevec->nr);
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       /* prevent the file from been uncached whilst we deal with it */
+       down_read(&cookie->sem);
+
+       ret = -ENOBUFS;
+       if (!hlist_empty(&cookie->backing_objects)) {
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
+                       goto out;
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       /* ask the cache to honour the operation */
+                       ret = object->cache->ops->write_pages(object,
+                                                             pagevec,
+                                                             end_io_func,
+                                                             context,
+                                                             gfp);
+                       fscache_operation_unlock(object);
+               }
+       }
+
+out:
+       up_read(&cookie->sem);
+       _leave(" = %d", ret);
+       return ret;
+}
+
+EXPORT_SYMBOL(__fscache_write_pages);
+
+/*****************************************************************************/
+/*
+ * remove a page from the cache
+ */
+void __fscache_uncache_page(struct fscache_cookie *cookie, struct page *page)
+{
+       struct fscache_object *object;
+       struct pagevec pagevec;
+
+       _enter(",{%lu}", page->index);
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" [no backing]");
+               return;
+       }
+
+       pagevec_init(&pagevec, 0);
+       pagevec_add(&pagevec, page);
+
+       /* ask the cache to honour the operation */
+       down_read(&cookie->sem);
+
+       if (!hlist_empty(&cookie->backing_objects)) {
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       object->cache->ops->uncache_pages(object, &pagevec);
+                       fscache_operation_unlock(object);
+               }
+       }
+
+       up_read(&cookie->sem);
+
+       _leave("");
+}
+
+EXPORT_SYMBOL(__fscache_uncache_page);
+
+/*****************************************************************************/
+/*
+ * remove a bunch of pages from the cache
+ */
+void __fscache_uncache_pages(struct fscache_cookie *cookie,
+                            struct pagevec *pagevec)
+{
+       struct fscache_object *object;
+
+       _enter(",{%ld}", pagevec->nr);
+
+       BUG_ON(pagevec->nr <= 0);
+       BUG_ON(!pagevec->pages[0]);
+
+       /* not supposed to use this for indexes */
+       BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
+
+       if (hlist_empty(&cookie->backing_objects)) {
+               _leave(" [no backing]");
+               return;
+       }
+
+       /* ask the cache to honour the operation */
+       down_read(&cookie->sem);
+
+       if (!hlist_empty(&cookie->backing_objects)) {
+               object = hlist_entry(cookie->backing_objects.first,
+                                    struct fscache_object, cookie_link);
+
+               /* prevent the cache from being withdrawn */
+               if (fscache_operation_lock(object)) {
+                       object->cache->ops->uncache_pages(object, pagevec);
+                       fscache_operation_unlock(object);
+               }
+       }
+
+       up_read(&cookie->sem);
+
+       _leave("");
+}
+
+EXPORT_SYMBOL(__fscache_uncache_pages);
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
new file mode 100644 (file)
index 0000000..79ec1f2
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+#define FUSE_CTL_SUPER_MAGIC 0x65735543
+
+/*
+ * This is non-NULL when the single instance of the control filesystem
+ * exists.  Protected by fuse_mutex
+ */
+static struct super_block *fuse_control_sb;
+
+static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
+{
+       struct fuse_conn *fc;
+       mutex_lock(&fuse_mutex);
+       fc = file->f_dentry->d_inode->i_private;
+       if (fc)
+               fc = fuse_conn_get(fc);
+       mutex_unlock(&fuse_mutex);
+       return fc;
+}
+
+static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
+       if (fc) {
+               fuse_abort_conn(fc);
+               fuse_conn_put(fc);
+       }
+       return count;
+}
+
+static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf,
+                                     size_t len, loff_t *ppos)
+{
+       char tmp[32];
+       size_t size;
+
+       if (!*ppos) {
+               struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
+               if (!fc)
+                       return 0;
+
+               file->private_data=(void *)(long)atomic_read(&fc->num_waiting);
+               fuse_conn_put(fc);
+       }
+       size = sprintf(tmp, "%ld\n", (long)file->private_data);
+       return simple_read_from_buffer(buf, len, ppos, tmp, size);
+}
+
+static const struct file_operations fuse_ctl_abort_ops = {
+       .open = nonseekable_open,
+       .write = fuse_conn_abort_write,
+};
+
+static const struct file_operations fuse_ctl_waiting_ops = {
+       .open = nonseekable_open,
+       .read = fuse_conn_waiting_read,
+};
+
+static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
+                                         struct fuse_conn *fc,
+                                         const char *name,
+                                         int mode, int nlink,
+                                         struct inode_operations *iop,
+                                         const struct file_operations *fop)
+{
+       struct dentry *dentry;
+       struct inode *inode;
+
+       BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES);
+       dentry = d_alloc_name(parent, name);
+       if (!dentry)
+               return NULL;
+
+       fc->ctl_dentry[fc->ctl_ndents++] = dentry;
+       inode = new_inode(fuse_control_sb);
+       if (!inode)
+               return NULL;
+
+       inode->i_mode = mode;
+       inode->i_uid = fc->user_id;
+       inode->i_gid = fc->group_id;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       /* setting ->i_op to NULL is not allowed */
+       if (iop)
+               inode->i_op = iop;
+       inode->i_fop = fop;
+       inode->i_nlink = nlink;
+       inode->i_private = fc;
+       d_add(dentry, inode);
+       return dentry;
+}
+
+/*
+ * Add a connection to the control filesystem (if it exists).  Caller
+ * must hold fuse_mutex
+ */
+int fuse_ctl_add_conn(struct fuse_conn *fc)
+{
+       struct dentry *parent;
+       char name[32];
+
+       if (!fuse_control_sb)
+               return 0;
+
+       parent = fuse_control_sb->s_root;
+       parent->d_inode->i_nlink++;
+       sprintf(name, "%llu", (unsigned long long) fc->id);
+       parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
+                                    &simple_dir_inode_operations,
+                                    &simple_dir_operations);
+       if (!parent)
+               goto err;
+
+       if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1,
+                               NULL, &fuse_ctl_waiting_ops) ||
+           !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1,
+                                NULL, &fuse_ctl_abort_ops))
+               goto err;
+
+       return 0;
+
+ err:
+       fuse_ctl_remove_conn(fc);
+       return -ENOMEM;
+}
+
+/*
+ * Remove a connection from the control filesystem (if it exists).
+ * Caller must hold fuse_mutex
+ */
+void fuse_ctl_remove_conn(struct fuse_conn *fc)
+{
+       int i;
+
+       if (!fuse_control_sb)
+               return;
+
+       for (i = fc->ctl_ndents - 1; i >= 0; i--) {
+               struct dentry *dentry = fc->ctl_dentry[i];
+               dentry->d_inode->i_private = NULL;
+               d_drop(dentry);
+               dput(dentry);
+       }
+       fuse_control_sb->s_root->d_inode->i_nlink--;
+}
+
+static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct tree_descr empty_descr = {""};
+       struct fuse_conn *fc;
+       int err;
+
+       err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+       if (err)
+               return err;
+
+       mutex_lock(&fuse_mutex);
+       BUG_ON(fuse_control_sb);
+       fuse_control_sb = sb;
+       list_for_each_entry(fc, &fuse_conn_list, entry) {
+               err = fuse_ctl_add_conn(fc);
+               if (err) {
+                       fuse_control_sb = NULL;
+                       mutex_unlock(&fuse_mutex);
+                       return err;
+               }
+       }
+       mutex_unlock(&fuse_mutex);
+
+       return 0;
+}
+
+static int fuse_ctl_get_sb(struct file_system_type *fs_type, int flags,
+                       const char *dev_name, void *raw_data,
+                       struct vfsmount *mnt)
+{
+       return get_sb_single(fs_type, flags, raw_data,
+                               fuse_ctl_fill_super, mnt);
+}
+
+static void fuse_ctl_kill_sb(struct super_block *sb)
+{
+       mutex_lock(&fuse_mutex);
+       fuse_control_sb = NULL;
+       mutex_unlock(&fuse_mutex);
+
+       kill_litter_super(sb);
+}
+
+static struct file_system_type fuse_ctl_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "fusectl",
+       .get_sb         = fuse_ctl_get_sb,
+       .kill_sb        = fuse_ctl_kill_sb,
+};
+
+int __init fuse_ctl_init(void)
+{
+       return register_filesystem(&fuse_ctl_fs_type);
+}
+
+void fuse_ctl_cleanup(void)
+{
+       unregister_filesystem(&fuse_ctl_fs_type);
+}
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
new file mode 100644 (file)
index 0000000..017cb0f
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * fs/inotify_user.c - inotify support for userspace
+ *
+ * Authors:
+ *     John McCutchan  <ttb@tentacle.dhs.org>
+ *     Robert Love     <rml@novell.com>
+ *
+ * Copyright (C) 2005 John McCutchan
+ * Copyright 2006 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/inotify.h>
+#include <linux/syscalls.h>
+
+#include <asm/ioctls.h>
+
+static kmem_cache_t *watch_cachep __read_mostly;
+static kmem_cache_t *event_cachep __read_mostly;
+
+static struct vfsmount *inotify_mnt __read_mostly;
+
+/* these are configurable via /proc/sys/fs/inotify/ */
+int inotify_max_user_instances __read_mostly;
+int inotify_max_user_watches __read_mostly;
+int inotify_max_queued_events __read_mostly;
+
+/*
+ * Lock ordering:
+ *
+ * inotify_dev->up_mutex (ensures we don't re-add the same watch)
+ *     inode->inotify_mutex (protects inode's watch list)
+ *             inotify_handle->mutex (protects inotify_handle's watch list)
+ *                     inotify_dev->ev_mutex (protects device's event queue)
+ */
+
+/*
+ * Lifetimes of the main data structures:
+ *
+ * inotify_device: Lifetime is managed by reference count, from
+ * sys_inotify_init() until release.  Additional references can bump the count
+ * via get_inotify_dev() and drop the count via put_inotify_dev().
+ *
+ * inotify_user_watch: Lifetime is from create_watch() to the receipt of an
+ * IN_IGNORED event from inotify, or when using IN_ONESHOT, to receipt of the
+ * first event, or to inotify_destroy().
+ */
+
+/*
+ * struct inotify_device - represents an inotify instance
+ *
+ * This structure is protected by the mutex 'mutex'.
+ */
+struct inotify_device {
+       wait_queue_head_t       wq;             /* wait queue for i/o */
+       struct mutex            ev_mutex;       /* protects event queue */
+       struct mutex            up_mutex;       /* synchronizes watch updates */
+       struct list_head        events;         /* list of queued events */
+       atomic_t                count;          /* reference count */
+       struct user_struct      *user;          /* user who opened this dev */
+       struct inotify_handle   *ih;            /* inotify handle */
+       unsigned int            queue_size;     /* size of the queue (bytes) */
+       unsigned int            event_count;    /* number of pending events */
+       unsigned int            max_events;     /* maximum number of events */
+};
+
+/*
+ * struct inotify_kernel_event - An inotify event, originating from a watch and
+ * queued for user-space.  A list of these is attached to each instance of the
+ * device.  In read(), this list is walked and all events that can fit in the
+ * buffer are returned.
+ *
+ * Protected by dev->ev_mutex of the device in which we are queued.
+ */
+struct inotify_kernel_event {
+       struct inotify_event    event;  /* the user-space event */
+       struct list_head        list;   /* entry in inotify_device's list */
+       char                    *name;  /* filename, if any */
+};
+
+/*
+ * struct inotify_user_watch - our version of an inotify_watch, we add
+ * a reference to the associated inotify_device.
+ */
+struct inotify_user_watch {
+       struct inotify_device   *dev;   /* associated device */
+       struct inotify_watch    wdata;  /* inotify watch data */
+};
+
+#ifdef CONFIG_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int zero;
+
+ctl_table inotify_table[] = {
+       {
+               .ctl_name       = INOTIFY_MAX_USER_INSTANCES,
+               .procname       = "max_user_instances",
+               .data           = &inotify_max_user_instances,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+       {
+               .ctl_name       = INOTIFY_MAX_USER_WATCHES,
+               .procname       = "max_user_watches",
+               .data           = &inotify_max_user_watches,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+       {
+               .ctl_name       = INOTIFY_MAX_QUEUED_EVENTS,
+               .procname       = "max_queued_events",
+               .data           = &inotify_max_queued_events,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero
+       },
+       { .ctl_name = 0 }
+};
+#endif /* CONFIG_SYSCTL */
+
+static inline void get_inotify_dev(struct inotify_device *dev)
+{
+       atomic_inc(&dev->count);
+}
+
+static inline void put_inotify_dev(struct inotify_device *dev)
+{
+       if (atomic_dec_and_test(&dev->count)) {
+               atomic_dec(&dev->user->inotify_devs);
+               free_uid(dev->user);
+               kfree(dev);
+       }
+}
+
+/*
+ * free_inotify_user_watch - cleans up the watch and its references
+ */
+static void free_inotify_user_watch(struct inotify_watch *w)
+{
+       struct inotify_user_watch *watch;
+       struct inotify_device *dev;
+
+       watch = container_of(w, struct inotify_user_watch, wdata);
+       dev = watch->dev;
+
+       atomic_dec(&dev->user->inotify_watches);
+       put_inotify_dev(dev);
+       kmem_cache_free(watch_cachep, watch);
+}
+
+/*
+ * kernel_event - create a new kernel event with the given parameters
+ *
+ * This function can sleep.
+ */
+static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
+                                                 const char *name)
+{
+       struct inotify_kernel_event *kevent;
+
+       kevent = kmem_cache_alloc(event_cachep, GFP_NOFS);
+       if (unlikely(!kevent))
+               return NULL;
+
+       /* we hand this out to user-space, so zero it just in case */
+       memset(&kevent->event, 0, sizeof(struct inotify_event));
+
+       kevent->event.wd = wd;
+       kevent->event.mask = mask;
+       kevent->event.cookie = cookie;
+
+       INIT_LIST_HEAD(&kevent->list);
+
+       if (name) {
+               size_t len, rem, event_size = sizeof(struct inotify_event);
+
+               /*
+                * We need to pad the filename so as to properly align an
+                * array of inotify_event structures.  Because the structure is
+                * small and the common case is a small filename, we just round
+                * up to the next multiple of the structure's sizeof.  This is
+                * simple and safe for all architectures.
+                */
+               len = strlen(name) + 1;
+               rem = event_size - len;
+               if (len > event_size) {
+                       rem = event_size - (len % event_size);
+                       if (len % event_size == 0)
+                               rem = 0;
+               }
+
+               kevent->name = kmalloc(len + rem, GFP_KERNEL);
+               if (unlikely(!kevent->name)) {
+                       kmem_cache_free(event_cachep, kevent);
+                       return NULL;
+               }
+               memcpy(kevent->name, name, len);
+               if (rem)
+                       memset(kevent->name + len, 0, rem);
+               kevent->event.len = len + rem;
+       } else {
+               kevent->event.len = 0;
+               kevent->name = NULL;
+       }
+
+       return kevent;
+}
+
+/*
+ * inotify_dev_get_event - return the next event in the given dev's queue
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static inline struct inotify_kernel_event *
+inotify_dev_get_event(struct inotify_device *dev)
+{
+       return list_entry(dev->events.next, struct inotify_kernel_event, list);
+}
+
+/*
+ * inotify_dev_queue_event - event handler registered with core inotify, adds
+ * a new event to the given device
+ *
+ * Can sleep (calls kernel_event()).
+ */
+static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask,
+                                   u32 cookie, const char *name,
+                                   struct inode *ignored)
+{
+       struct inotify_user_watch *watch;
+       struct inotify_device *dev;
+       struct inotify_kernel_event *kevent, *last;
+
+       watch = container_of(w, struct inotify_user_watch, wdata);
+       dev = watch->dev;
+
+       mutex_lock(&dev->ev_mutex);
+
+       /* we can safely put the watch as we don't reference it while
+        * generating the event
+        */
+       if (mask & IN_IGNORED || mask & IN_ONESHOT)
+               put_inotify_watch(w); /* final put */
+
+       /* coalescing: drop this event if it is a dupe of the previous */
+       last = inotify_dev_get_event(dev);
+       if (last && last->event.mask == mask && last->event.wd == wd &&
+                       last->event.cookie == cookie) {
+               const char *lastname = last->name;
+
+               if (!name && !lastname)
+                       goto out;
+               if (name && lastname && !strcmp(lastname, name))
+                       goto out;
+       }
+
+       /* the queue overflowed and we already sent the Q_OVERFLOW event */
+       if (unlikely(dev->event_count > dev->max_events))
+               goto out;
+
+       /* if the queue overflows, we need to notify user space */
+       if (unlikely(dev->event_count == dev->max_events))
+               kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
+       else
+               kevent = kernel_event(wd, mask, cookie, name);
+
+       if (unlikely(!kevent))
+               goto out;
+
+       /* queue the event and wake up anyone waiting */
+       dev->event_count++;
+       dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
+       list_add_tail(&kevent->list, &dev->events);
+       wake_up_interruptible(&dev->wq);
+
+out:
+       mutex_unlock(&dev->ev_mutex);
+}
+
+/*
+ * remove_kevent - cleans up and ultimately frees the given kevent
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static void remove_kevent(struct inotify_device *dev,
+                         struct inotify_kernel_event *kevent)
+{
+       list_del(&kevent->list);
+
+       dev->event_count--;
+       dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
+
+       kfree(kevent->name);
+       kmem_cache_free(event_cachep, kevent);
+}
+
+/*
+ * inotify_dev_event_dequeue - destroy an event on the given device
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static void inotify_dev_event_dequeue(struct inotify_device *dev)
+{
+       if (!list_empty(&dev->events)) {
+               struct inotify_kernel_event *kevent;
+               kevent = inotify_dev_get_event(dev);
+               remove_kevent(dev, kevent);
+       }
+}
+
+/*
+ * find_inode - resolve a user-given path to a specific inode and return a nd
+ */
+static int find_inode(const char __user *dirname, struct nameidata *nd,
+                     unsigned flags)
+{
+       int error;
+
+       error = __user_walk(dirname, flags, nd);
+       if (error)
+               return error;
+       /* you can only watch an inode if you have read permissions on it */
+       error = vfs_permission(nd, MAY_READ);
+       if (error)
+               path_release(nd);
+       return error;
+}
+
+/*
+ * create_watch - creates a watch on the given device.
+ *
+ * Callers must hold dev->up_mutex.
+ */
+static int create_watch(struct inotify_device *dev, struct inode *inode,
+                       u32 mask)
+{
+       struct inotify_user_watch *watch;
+       int ret;
+
+       if (atomic_read(&dev->user->inotify_watches) >=
+                       inotify_max_user_watches)
+               return -ENOSPC;
+
+       watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
+       if (unlikely(!watch))
+               return -ENOMEM;
+
+       /* save a reference to device and bump the count to make it official */
+       get_inotify_dev(dev);
+       watch->dev = dev;
+
+       atomic_inc(&dev->user->inotify_watches);
+
+       inotify_init_watch(&watch->wdata);
+       ret = inotify_add_watch(dev->ih, &watch->wdata, inode, mask);
+       if (ret < 0)
+               free_inotify_user_watch(&watch->wdata);
+
+       return ret;
+}
+
+/* Device Interface */
+
+static unsigned int inotify_poll(struct file *file, poll_table *wait)
+{
+       struct inotify_device *dev = file->private_data;
+       int ret = 0;
+
+       poll_wait(file, &dev->wq, wait);
+       mutex_lock(&dev->ev_mutex);
+       if (!list_empty(&dev->events))
+               ret = POLLIN | POLLRDNORM;
+       mutex_unlock(&dev->ev_mutex);
+
+       return ret;
+}
+
+static ssize_t inotify_read(struct file *file, char __user *buf,
+                           size_t count, loff_t *pos)
+{
+       size_t event_size = sizeof (struct inotify_event);
+       struct inotify_device *dev;
+       char __user *start;
+       int ret;
+       DEFINE_WAIT(wait);
+
+       start = buf;
+       dev = file->private_data;
+
+       while (1) {
+               int events;
+
+               prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
+
+               mutex_lock(&dev->ev_mutex);
+               events = !list_empty(&dev->events);
+               mutex_unlock(&dev->ev_mutex);
+               if (events) {
+                       ret = 0;
+                       break;
+               }
+
+               if (file->f_flags & O_NONBLOCK) {
+                       ret = -EAGAIN;
+                       break;
+               }
+
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+
+               schedule();
+       }
+
+       finish_wait(&dev->wq, &wait);
+       if (ret)
+               return ret;
+
+       mutex_lock(&dev->ev_mutex);
+       while (1) {
+               struct inotify_kernel_event *kevent;
+
+               ret = buf - start;
+               if (list_empty(&dev->events))
+                       break;
+
+               kevent = inotify_dev_get_event(dev);
+               if (event_size + kevent->event.len > count)
+                       break;
+
+               if (copy_to_user(buf, &kevent->event, event_size)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               buf += event_size;
+               count -= event_size;
+
+               if (kevent->name) {
+                       if (copy_to_user(buf, kevent->name, kevent->event.len)){
+                               ret = -EFAULT;
+                               break;
+                       }
+                       buf += kevent->event.len;
+                       count -= kevent->event.len;
+               }
+
+               remove_kevent(dev, kevent);
+       }
+       mutex_unlock(&dev->ev_mutex);
+
+       return ret;
+}
+
+static int inotify_release(struct inode *ignored, struct file *file)
+{
+       struct inotify_device *dev = file->private_data;
+
+       inotify_destroy(dev->ih);
+
+       /* destroy all of the events on this device */
+       mutex_lock(&dev->ev_mutex);
+       while (!list_empty(&dev->events))
+               inotify_dev_event_dequeue(dev);
+       mutex_unlock(&dev->ev_mutex);
+
+       /* free this device: the put matching the get in inotify_init() */
+       put_inotify_dev(dev);
+
+       return 0;
+}
+
+static long inotify_ioctl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
+{
+       struct inotify_device *dev;
+       void __user *p;
+       int ret = -ENOTTY;
+
+       dev = file->private_data;
+       p = (void __user *) arg;
+
+       switch (cmd) {
+       case FIONREAD:
+               ret = put_user(dev->queue_size, (int __user *) p);
+               break;
+       }
+
+       return ret;
+}
+
+static const struct file_operations inotify_fops = {
+       .poll           = inotify_poll,
+       .read           = inotify_read,
+       .release        = inotify_release,
+       .unlocked_ioctl = inotify_ioctl,
+       .compat_ioctl   = inotify_ioctl,
+};
+
+static const struct inotify_operations inotify_user_ops = {
+       .handle_event   = inotify_dev_queue_event,
+       .destroy_watch  = free_inotify_user_watch,
+};
+
+asmlinkage long sys_inotify_init(void)
+{
+       struct inotify_device *dev;
+       struct inotify_handle *ih;
+       struct user_struct *user;
+       struct file *filp;
+       int fd, ret;
+
+       fd = get_unused_fd();
+       if (fd < 0)
+               return fd;
+
+       filp = get_empty_filp();
+       if (!filp) {
+               ret = -ENFILE;
+               goto out_put_fd;
+       }
+
+       user = get_uid(current->user);
+       if (unlikely(atomic_read(&user->inotify_devs) >=
+                       inotify_max_user_instances)) {
+               ret = -EMFILE;
+               goto out_free_uid;
+       }
+
+       dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
+       if (unlikely(!dev)) {
+               ret = -ENOMEM;
+               goto out_free_uid;
+       }
+
+       ih = inotify_init(&inotify_user_ops);
+       if (unlikely(IS_ERR(ih))) {
+               ret = PTR_ERR(ih);
+               goto out_free_dev;
+       }
+       dev->ih = ih;
+
+       filp->f_op = &inotify_fops;
+       filp->f_vfsmnt = mntget(inotify_mnt);
+       filp->f_dentry = dget(inotify_mnt->mnt_root);
+       filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+       filp->f_mode = FMODE_READ;
+       filp->f_flags = O_RDONLY;
+       filp->private_data = dev;
+
+       INIT_LIST_HEAD(&dev->events);
+       init_waitqueue_head(&dev->wq);
+       mutex_init(&dev->ev_mutex);
+       mutex_init(&dev->up_mutex);
+       dev->event_count = 0;
+       dev->queue_size = 0;
+       dev->max_events = inotify_max_queued_events;
+       dev->user = user;
+       atomic_set(&dev->count, 0);
+
+       get_inotify_dev(dev);
+       atomic_inc(&user->inotify_devs);
+       fd_install(fd, filp);
+
+       return fd;
+out_free_dev:
+       kfree(dev);
+out_free_uid:
+       free_uid(user);
+       put_filp(filp);
+out_put_fd:
+       put_unused_fd(fd);
+       return ret;
+}
+
+asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
+{
+       struct inode *inode;
+       struct inotify_device *dev;
+       struct nameidata nd;
+       struct file *filp;
+       int ret, fput_needed;
+       unsigned flags = 0;
+
+       filp = fget_light(fd, &fput_needed);
+       if (unlikely(!filp))
+               return -EBADF;
+
+       /* verify that this is indeed an inotify instance */
+       if (unlikely(filp->f_op != &inotify_fops)) {
+               ret = -EINVAL;
+               goto fput_and_out;
+       }
+
+       if (!(mask & IN_DONT_FOLLOW))
+               flags |= LOOKUP_FOLLOW;
+       if (mask & IN_ONLYDIR)
+               flags |= LOOKUP_DIRECTORY;
+
+       ret = find_inode(path, &nd, flags);
+       if (unlikely(ret))
+               goto fput_and_out;
+
+       /* inode held in place by reference to nd; dev by fget on fd */
+       inode = nd.dentry->d_inode;
+       dev = filp->private_data;
+
+       mutex_lock(&dev->up_mutex);
+       ret = inotify_find_update_watch(dev->ih, inode, mask);
+       if (ret == -ENOENT)
+               ret = create_watch(dev, inode, mask);
+       mutex_unlock(&dev->up_mutex);
+
+       path_release(&nd);
+fput_and_out:
+       fput_light(filp, fput_needed);
+       return ret;
+}
+
+asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
+{
+       struct file *filp;
+       struct inotify_device *dev;
+       int ret, fput_needed;
+
+       filp = fget_light(fd, &fput_needed);
+       if (unlikely(!filp))
+               return -EBADF;
+
+       /* verify that this is indeed an inotify instance */
+       if (unlikely(filp->f_op != &inotify_fops)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       dev = filp->private_data;
+
+       /* we free our watch data when we get IN_IGNORED */
+       ret = inotify_rm_wd(dev->ih, wd);
+
+out:
+       fput_light(filp, fput_needed);
+       return ret;
+}
+
+static int
+inotify_get_sb(struct file_system_type *fs_type, int flags,
+              const char *dev_name, void *data, struct vfsmount *mnt)
+{
+       return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt);
+}
+
+static struct file_system_type inotify_fs_type = {
+    .name           = "inotifyfs",
+    .get_sb         = inotify_get_sb,
+    .kill_sb        = kill_anon_super,
+};
+
+/*
+ * inotify_user_setup - Our initialization function.  Note that we cannnot return
+ * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
+ * must result in panic().
+ */
+static int __init inotify_user_setup(void)
+{
+       int ret;
+
+       ret = register_filesystem(&inotify_fs_type);
+       if (unlikely(ret))
+               panic("inotify: register_filesystem returned %d!\n", ret);
+
+       inotify_mnt = kern_mount(&inotify_fs_type);
+       if (IS_ERR(inotify_mnt))
+               panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
+
+       inotify_max_queued_events = 16384;
+       inotify_max_user_instances = 128;
+       inotify_max_user_watches = 8192;
+
+       watch_cachep = kmem_cache_create("inotify_watch_cache",
+                                        sizeof(struct inotify_user_watch),
+                                        0, SLAB_PANIC, NULL, NULL);
+       event_cachep = kmem_cache_create("inotify_event_cache",
+                                        sizeof(struct inotify_kernel_event),
+                                        0, SLAB_PANIC, NULL, NULL);
+
+       return 0;
+}
+
+module_init(inotify_user_setup);
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
new file mode 100644 (file)
index 0000000..0ae3cd1
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static size_t jffs2_acl_size(int count)
+{
+       if (count <= 4) {
+               return sizeof(struct jffs2_acl_header)
+                      + count * sizeof(struct jffs2_acl_entry_short);
+       } else {
+               return sizeof(struct jffs2_acl_header)
+                      + 4 * sizeof(struct jffs2_acl_entry_short)
+                      + (count - 4) * sizeof(struct jffs2_acl_entry);
+       }
+}
+
+static int jffs2_acl_count(size_t size)
+{
+       size_t s;
+
+       size -= sizeof(struct jffs2_acl_header);
+       s = size - 4 * sizeof(struct jffs2_acl_entry_short);
+       if (s < 0) {
+               if (size % sizeof(struct jffs2_acl_entry_short))
+                       return -1;
+               return size / sizeof(struct jffs2_acl_entry_short);
+       } else {
+               if (s % sizeof(struct jffs2_acl_entry))
+                       return -1;
+               return s / sizeof(struct jffs2_acl_entry) + 4;
+       }
+}
+
+static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size)
+{
+       void *end = value + size;
+       struct jffs2_acl_header *header = value;
+       struct jffs2_acl_entry *entry;
+       struct posix_acl *acl;
+       uint32_t ver;
+       int i, count;
+
+       if (!value)
+               return NULL;
+       if (size < sizeof(struct jffs2_acl_header))
+               return ERR_PTR(-EINVAL);
+       ver = je32_to_cpu(header->a_version);
+       if (ver != JFFS2_ACL_VERSION) {
+               JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver);
+               return ERR_PTR(-EINVAL);
+       }
+
+       value += sizeof(struct jffs2_acl_header);
+       count = jffs2_acl_count(size);
+       if (count < 0)
+               return ERR_PTR(-EINVAL);
+       if (count == 0)
+               return NULL;
+
+       acl = posix_acl_alloc(count, GFP_KERNEL);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+
+       for (i=0; i < count; i++) {
+               entry = value;
+               if (value + sizeof(struct jffs2_acl_entry_short) > end)
+                       goto fail;
+               acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag);
+               acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm);
+               switch (acl->a_entries[i].e_tag) {
+                       case ACL_USER_OBJ:
+                       case ACL_GROUP_OBJ:
+                       case ACL_MASK:
+                       case ACL_OTHER:
+                               value += sizeof(struct jffs2_acl_entry_short);
+                               acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
+                               break;
+
+                       case ACL_USER:
+                       case ACL_GROUP:
+                               value += sizeof(struct jffs2_acl_entry);
+                               if (value > end)
+                                       goto fail;
+                               acl->a_entries[i].e_id = je32_to_cpu(entry->e_id);
+                               break;
+
+                       default:
+                               goto fail;
+               }
+       }
+       if (value != end)
+               goto fail;
+       return acl;
+ fail:
+       posix_acl_release(acl);
+       return ERR_PTR(-EINVAL);
+}
+
+static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
+{
+       struct jffs2_acl_header *header;
+       struct jffs2_acl_entry *entry;
+       void *e;
+       size_t i;
+
+       *size = jffs2_acl_size(acl->a_count);
+       header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
+       if (!header)
+               return ERR_PTR(-ENOMEM);
+       header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
+       e = header + 1;
+       for (i=0; i < acl->a_count; i++) {
+               entry = e;
+               entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag);
+               entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm);
+               switch(acl->a_entries[i].e_tag) {
+                       case ACL_USER:
+                       case ACL_GROUP:
+                               entry->e_id = cpu_to_je32(acl->a_entries[i].e_id);
+                               e += sizeof(struct jffs2_acl_entry);
+                               break;
+
+                       case ACL_USER_OBJ:
+                       case ACL_GROUP_OBJ:
+                       case ACL_MASK:
+                       case ACL_OTHER:
+                               e += sizeof(struct jffs2_acl_entry_short);
+                               break;
+
+                       default:
+                               goto fail;
+               }
+       }
+       return header;
+ fail:
+       kfree(header);
+       return ERR_PTR(-EINVAL);
+}
+
+static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+       struct posix_acl *acl = JFFS2_ACL_NOT_CACHED;
+
+       spin_lock(&inode->i_lock);
+       if (*i_acl != JFFS2_ACL_NOT_CACHED)
+               acl = posix_acl_dup(*i_acl);
+       spin_unlock(&inode->i_lock);
+       return acl;
+}
+
+static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl)
+{
+       spin_lock(&inode->i_lock);
+       if (*i_acl != JFFS2_ACL_NOT_CACHED)
+               posix_acl_release(*i_acl);
+       *i_acl = posix_acl_dup(acl);
+       spin_unlock(&inode->i_lock);
+}
+
+static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct posix_acl *acl;
+       char *value = NULL;
+       int rc, xprefix;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               acl = jffs2_iget_acl(inode, &f->i_acl_access);
+               if (acl != JFFS2_ACL_NOT_CACHED)
+                       return acl;
+               xprefix = JFFS2_XPREFIX_ACL_ACCESS;
+               break;
+       case ACL_TYPE_DEFAULT:
+               acl = jffs2_iget_acl(inode, &f->i_acl_default);
+               if (acl != JFFS2_ACL_NOT_CACHED)
+                       return acl;
+               xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
+               break;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+       rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0);
+       if (rc > 0) {
+               value = kmalloc(rc, GFP_KERNEL);
+               if (!value)
+                       return ERR_PTR(-ENOMEM);
+               rc = do_jffs2_getxattr(inode, xprefix, "", value, rc);
+       }
+       if (rc > 0) {
+               acl = jffs2_acl_from_medium(value, rc);
+       } else if (rc == -ENODATA || rc == -ENOSYS) {
+               acl = NULL;
+       } else {
+               acl = ERR_PTR(rc);
+       }
+       if (value)
+               kfree(value);
+       if (!IS_ERR(acl)) {
+               switch (type) {
+               case ACL_TYPE_ACCESS:
+                       jffs2_iset_acl(inode, &f->i_acl_access, acl);
+                       break;
+               case ACL_TYPE_DEFAULT:
+                       jffs2_iset_acl(inode, &f->i_acl_default, acl);
+                       break;
+               }
+       }
+       return acl;
+}
+
+static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       size_t size = 0;
+       char *value = NULL;
+       int rc, xprefix;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               xprefix = JFFS2_XPREFIX_ACL_ACCESS;
+               if (acl) {
+                       mode_t mode = inode->i_mode;
+                       rc = posix_acl_equiv_mode(acl, &mode);
+                       if (rc < 0)
+                               return rc;
+                       if (inode->i_mode != mode) {
+                               inode->i_mode = mode;
+                               jffs2_dirty_inode(inode);
+                       }
+                       if (rc == 0)
+                               acl = NULL;
+               }
+               break;
+       case ACL_TYPE_DEFAULT:
+               xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
+               if (!S_ISDIR(inode->i_mode))
+                       return acl ? -EACCES : 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (acl) {
+               value = jffs2_acl_to_medium(acl, &size);
+               if (IS_ERR(value))
+                       return PTR_ERR(value);
+       }
+
+       rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
+       if (!value && rc == -ENODATA)
+               rc = 0;
+       if (value)
+               kfree(value);
+       if (!rc) {
+               switch(type) {
+               case ACL_TYPE_ACCESS:
+                       jffs2_iset_acl(inode, &f->i_acl_access, acl);
+                       break;
+               case ACL_TYPE_DEFAULT:
+                       jffs2_iset_acl(inode, &f->i_acl_default, acl);
+                       break;
+               }
+       }
+       return rc;
+}
+
+static int jffs2_check_acl(struct inode *inode, int mask)
+{
+       struct posix_acl *acl;
+       int rc;
+
+       acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (acl) {
+               rc = posix_acl_permission(inode, acl, mask);
+               posix_acl_release(acl);
+               return rc;
+       }
+       return -EAGAIN;
+}
+
+int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+       return generic_permission(inode, mask, jffs2_check_acl);
+}
+
+int jffs2_init_acl(struct inode *inode, struct inode *dir)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct posix_acl *acl = NULL, *clone;
+       mode_t mode;
+       int rc = 0;
+
+       f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+       f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+       if (!S_ISLNK(inode->i_mode)) {
+               acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (!acl)
+                       inode->i_mode &= ~current->fs->umask;
+       }
+       if (acl) {
+               if (S_ISDIR(inode->i_mode)) {
+                       rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+                       if (rc)
+                               goto cleanup;
+               }
+               clone = posix_acl_clone(acl, GFP_KERNEL);
+               rc = -ENOMEM;
+               if (!clone)
+                       goto cleanup;
+               mode = inode->i_mode;
+               rc = posix_acl_create_masq(clone, &mode);
+               if (rc >= 0) {
+                       inode->i_mode = mode;
+                       if (rc > 0)
+                               rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
+               }
+               posix_acl_release(clone);
+       }
+ cleanup:
+       posix_acl_release(acl);
+       return rc;
+}
+
+void jffs2_clear_acl(struct jffs2_inode_info *f)
+{
+       if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) {
+               posix_acl_release(f->i_acl_access);
+               f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+       }
+       if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) {
+               posix_acl_release(f->i_acl_default);
+               f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+       }
+}
+
+int jffs2_acl_chmod(struct inode *inode)
+{
+       struct posix_acl *acl, *clone;
+       int rc;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+       acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl) || !acl)
+               return PTR_ERR(acl);
+       clone = posix_acl_clone(acl, GFP_KERNEL);
+       posix_acl_release(acl);
+       if (!clone)
+               return -ENOMEM;
+       rc = posix_acl_chmod_masq(clone, inode->i_mode);
+       if (!rc)
+               rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
+       posix_acl_release(clone);
+       return rc;
+}
+
+static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
+                                        const char *name, size_t name_len)
+{
+       const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
+
+       if (list && retlen <= list_size)
+               strcpy(list, POSIX_ACL_XATTR_ACCESS);
+       return retlen;
+}
+
+static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
+                                         const char *name, size_t name_len)
+{
+       const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
+
+       if (list && retlen <= list_size)
+               strcpy(list, POSIX_ACL_XATTR_DEFAULT);
+       return retlen;
+}
+
+static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
+{
+       struct posix_acl *acl;
+       int rc;
+
+       acl = jffs2_get_acl(inode, type);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (!acl)
+               return -ENODATA;
+       rc = posix_acl_to_xattr(acl, buffer, size);
+       posix_acl_release(acl);
+
+       return rc;
+}
+
+static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
+{
+       struct posix_acl *acl;
+       int rc;
+
+       if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+               return -EPERM;
+
+       if (value) {
+               acl = posix_acl_from_xattr(value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (acl) {
+                       rc = posix_acl_valid(acl);
+                       if (rc)
+                               goto out;
+               }
+       } else {
+               acl = NULL;
+       }
+       rc = jffs2_set_acl(inode, type, acl);
+ out:
+       posix_acl_release(acl);
+       return rc;
+}
+
+static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
+                                    const void *buffer, size_t size, int flags)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
+                                     const void *buffer, size_t size, int flags)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+struct xattr_handler jffs2_acl_access_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .list   = jffs2_acl_access_listxattr,
+       .get    = jffs2_acl_access_getxattr,
+       .set    = jffs2_acl_access_setxattr,
+};
+
+struct xattr_handler jffs2_acl_default_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .list   = jffs2_acl_default_listxattr,
+       .get    = jffs2_acl_default_getxattr,
+       .set    = jffs2_acl_default_setxattr,
+};
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
new file mode 100644 (file)
index 0000000..fa327db
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+struct jffs2_acl_entry {
+       jint16_t        e_tag;
+       jint16_t        e_perm;
+       jint32_t        e_id;
+};
+
+struct jffs2_acl_entry_short {
+       jint16_t        e_tag;
+       jint16_t        e_perm;
+};
+
+struct jffs2_acl_header {
+       jint32_t        a_version;
+};
+
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+
+#define JFFS2_ACL_NOT_CACHED ((void *)-1)
+
+extern int jffs2_permission(struct inode *, int, struct nameidata *);
+extern int jffs2_acl_chmod(struct inode *);
+extern int jffs2_init_acl(struct inode *, struct inode *);
+extern void jffs2_clear_acl(struct jffs2_inode_info *);
+
+extern struct xattr_handler jffs2_acl_access_xattr_handler;
+extern struct xattr_handler jffs2_acl_default_xattr_handler;
+
+#else
+
+#define jffs2_permission NULL
+#define jffs2_acl_chmod(inode)         (0)
+#define jffs2_init_acl(inode,dir)      (0)
+#define jffs2_clear_acl(f)
+
+#endif /* CONFIG_JFFS2_FS_POSIX_ACL */
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
new file mode 100644 (file)
index 0000000..2e0cc8e
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */
+
+#ifndef _JFFS2_FS_I
+#define _JFFS2_FS_I
+
+#include <linux/version.h>
+#include <linux/rbtree.h>
+#include <linux/posix_acl.h>
+#include <asm/semaphore.h>
+
+struct jffs2_inode_info {
+       /* We need an internal mutex similar to inode->i_mutex.
+          Unfortunately, we can't used the existing one, because
+          either the GC would deadlock, or we'd have to release it
+          before letting GC proceed. Or we'd have to put ugliness
+          into the GC code so it didn't attempt to obtain the i_mutex
+          for the inode(s) which are already locked */
+       struct semaphore sem;
+
+       /* The highest (datanode) version number used for this ino */
+       uint32_t highest_version;
+
+       /* List of data fragments which make up the file */
+       struct rb_root fragtree;
+
+       /* There may be one datanode which isn't referenced by any of the
+          above fragments, if it contains a metadata update but no actual
+          data - or if this is a directory inode */
+       /* This also holds the _only_ dnode for symlinks/device nodes,
+          etc. */
+       struct jffs2_full_dnode *metadata;
+
+       /* Directory entries */
+       struct jffs2_full_dirent *dents;
+
+       /* The target path if this is the inode of a symlink */
+       unsigned char *target;
+
+       /* Some stuff we just have to keep in-core at all times, for each inode. */
+       struct jffs2_inode_cache *inocache;
+
+       uint16_t flags;
+       uint8_t usercompr;
+#if !defined (__ECOS)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)
+       struct inode vfs_inode;
+#endif
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       struct posix_acl *i_acl_access;
+       struct posix_acl *i_acl_default;
+#endif
+};
+
+#endif /* _JFFS2_FS_I */
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
new file mode 100644 (file)
index 0000000..b985949
--- /dev/null
@@ -0,0 +1,136 @@
+/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */
+
+#ifndef _JFFS2_FS_SB
+#define _JFFS2_FS_SB
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <asm/semaphore.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/rwsem.h>
+
+#define JFFS2_SB_FLAG_RO 1
+#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */
+#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */
+
+struct jffs2_inodirty;
+
+/* A struct for the overall file system control.  Pointers to
+   jffs2_sb_info structs are named `c' in the source code.
+   Nee jffs_control
+*/
+struct jffs2_sb_info {
+       struct mtd_info *mtd;
+
+       uint32_t highest_ino;
+       uint32_t checked_ino;
+
+       unsigned int flags;
+
+       struct task_struct *gc_task;    /* GC task struct */
+       struct completion gc_thread_start; /* GC thread start completion */
+       struct completion gc_thread_exit; /* GC thread exit completion port */
+
+       struct semaphore alloc_sem;     /* Used to protect all the following
+                                          fields, and also to protect against
+                                          out-of-order writing of nodes. And GC. */
+       uint32_t cleanmarker_size;      /* Size of an _inline_ CLEANMARKER
+                                        (i.e. zero for OOB CLEANMARKER */
+
+       uint32_t flash_size;
+       uint32_t used_size;
+       uint32_t dirty_size;
+       uint32_t wasted_size;
+       uint32_t free_size;
+       uint32_t erasing_size;
+       uint32_t bad_size;
+       uint32_t sector_size;
+       uint32_t unchecked_size;
+
+       uint32_t nr_free_blocks;
+       uint32_t nr_erasing_blocks;
+
+       /* Number of free blocks there must be before we... */
+       uint8_t resv_blocks_write;      /* ... allow a normal filesystem write */
+       uint8_t resv_blocks_deletion;   /* ... allow a normal filesystem deletion */
+       uint8_t resv_blocks_gctrigger;  /* ... wake up the GC thread */
+       uint8_t resv_blocks_gcbad;      /* ... pick a block from the bad_list to GC */
+       uint8_t resv_blocks_gcmerge;    /* ... merge pages when garbage collecting */
+
+       uint32_t nospc_dirty_size;
+
+       uint32_t nr_blocks;
+       struct jffs2_eraseblock *blocks;        /* The whole array of blocks. Used for getting blocks
+                                                * from the offset (blocks[ofs / sector_size]) */
+       struct jffs2_eraseblock *nextblock;     /* The block we're currently filling */
+
+       struct jffs2_eraseblock *gcblock;       /* The block we're currently garbage-collecting */
+
+       struct list_head clean_list;            /* Blocks 100% full of clean data */
+       struct list_head very_dirty_list;       /* Blocks with lots of dirty space */
+       struct list_head dirty_list;            /* Blocks with some dirty space */
+       struct list_head erasable_list;         /* Blocks which are completely dirty, and need erasing */
+       struct list_head erasable_pending_wbuf_list;    /* Blocks which need erasing but only after the current wbuf is flushed */
+       struct list_head erasing_list;          /* Blocks which are currently erasing */
+       struct list_head erase_pending_list;    /* Blocks which need erasing now */
+       struct list_head erase_complete_list;   /* Blocks which are erased and need the clean marker written to them */
+       struct list_head free_list;             /* Blocks which are free and ready to be used */
+       struct list_head bad_list;              /* Bad blocks. */
+       struct list_head bad_used_list;         /* Bad blocks with valid data in. */
+
+       spinlock_t erase_completion_lock;       /* Protect free_list and erasing_list
+                                                  against erase completion handler */
+       wait_queue_head_t erase_wait;           /* For waiting for erases to complete */
+
+       wait_queue_head_t inocache_wq;
+       struct jffs2_inode_cache **inocache_list;
+       spinlock_t inocache_lock;
+
+       /* Sem to allow jffs2_garbage_collect_deletion_dirent to
+          drop the erase_completion_lock while it's holding a pointer
+          to an obsoleted node. I don't like this. Alternatives welcomed. */
+       struct semaphore erase_free_sem;
+
+       uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
+
+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
+       /* Write-behind buffer for NAND flash */
+       unsigned char *wbuf;
+       unsigned char *oobbuf;
+       uint32_t wbuf_ofs;
+       uint32_t wbuf_len;
+       struct jffs2_inodirty *wbuf_inodes;
+
+       struct rw_semaphore wbuf_sem;   /* Protects the write buffer */
+
+       /* Information about out-of-band area usage... */
+       struct nand_ecclayout *ecclayout;
+       uint32_t badblock_pos;
+       uint32_t fsdata_pos;
+       uint32_t fsdata_len;
+#endif
+
+       struct jffs2_summary *summary;          /* Summary information */
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+#define XATTRINDEX_HASHSIZE    (57)
+       uint32_t highest_xid;
+       uint32_t highest_xseqno;
+       struct list_head xattrindex[XATTRINDEX_HASHSIZE];
+       struct list_head xattr_unchecked;
+       struct list_head xattr_dead_list;
+       struct jffs2_xattr_ref *xref_dead_list;
+       struct jffs2_xattr_ref *xref_temp;
+       struct rw_semaphore xattr_sem;
+       uint32_t xdatum_mem_usage;
+       uint32_t xdatum_mem_threshold;
+#endif
+       /* OS-private pointer for getting back to master superblock info */
+       void *os_priv;
+};
+
+#endif /* _JFFS2_FB_SB */
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
new file mode 100644 (file)
index 0000000..52a9894
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include <linux/security.h>
+#include "nodelist.h"
+
+/* ---- Initial Security Label Attachment -------------- */
+int jffs2_init_security(struct inode *inode, struct inode *dir)
+{
+       int rc;
+       size_t len;
+       void *value;
+       char *name;
+
+       rc = security_inode_init_security(inode, dir, &name, &value, &len);
+       if (rc) {
+               if (rc == -EOPNOTSUPP)
+                       return 0;
+               return rc;
+       }
+       rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
+
+        kfree(name);
+        kfree(value);
+        return rc;
+}
+
+/* ---- XATTR Handler for "security.*" ----------------- */
+static int jffs2_security_getxattr(struct inode *inode, const char *name,
+                                  void *buffer, size_t size)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+
+       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
+}
+
+static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
+                                  size_t size, int flags)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+
+       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
+}
+
+static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
+                                      const char *name, size_t name_len)
+{
+       size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
+
+       if (list && retlen <= list_size) {
+               strcpy(list, XATTR_SECURITY_PREFIX);
+               strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
+       }
+
+       return retlen;
+}
+
+struct xattr_handler jffs2_security_xattr_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .list = jffs2_security_listxattr,
+       .set = jffs2_security_setxattr,
+       .get = jffs2_security_getxattr
+};
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
new file mode 100644 (file)
index 0000000..4da09ce
--- /dev/null
@@ -0,0 +1,1324 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+/* -------- xdatum related functions ----------------
+ * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
+ *   is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
+ *   the index of the xattr name/value pair cache (c->xattrindex).
+ * is_xattr_datum_unchecked(c, xd)
+ *   returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not
+ *   unchecked, it returns 0.
+ * unload_xattr_datum(c, xd)
+ *   is used to release xattr name/value pair and detach from c->xattrindex.
+ * reclaim_xattr_datum(c)
+ *   is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
+ *   memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold 
+ *   is hard coded as 32KiB.
+ * do_verify_xattr_datum(c, xd)
+ *   is used to load the xdatum informations without name/value pair from the medium.
+ *   It's necessary once, because those informations are not collected during mounting
+ *   process when EBS is enabled.
+ *   0 will be returned, if success. An negative return value means recoverable error, and
+ *   positive return value means unrecoverable error. Thus, caller must remove this xdatum
+ *   and xref when it returned positive value.
+ * do_load_xattr_datum(c, xd)
+ *   is used to load name/value pair from the medium.
+ *   The meanings of return value is same as do_verify_xattr_datum().
+ * load_xattr_datum(c, xd)
+ *   is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum().
+ *   If xd need to call do_verify_xattr_datum() at first, it's called before calling
+ *   do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum().
+ * save_xattr_datum(c, xd)
+ *   is used to write xdatum to medium. xd->version will be incremented.
+ * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
+ *   is used to create new xdatum and write to medium.
+ * unrefer_xattr_datum(c, xd)
+ *   is used to delete a xdatum. When nobody refers this xdatum, JFFS2_XFLAGS_DEAD
+ *   is set on xd->flags and chained xattr_dead_list or release it immediately.
+ *   In the first case, the garbage collector release it later.
+ * -------------------------------------------------- */
+static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
+{
+       int name_len = strlen(xname);
+
+       return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
+}
+
+static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       struct jffs2_raw_node_ref *raw;
+       int rc = 0;
+
+       spin_lock(&c->erase_completion_lock);
+       for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
+               if (ref_flags(raw) == REF_UNCHECKED) {
+                       rc = 1;
+                       break;
+               }
+       }
+       spin_unlock(&c->erase_completion_lock);
+       return rc;
+}
+
+static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
+       if (xd->xname) {
+               c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
+               kfree(xd->xname);
+       }
+
+       list_del_init(&xd->xindex);
+       xd->hashkey = 0;
+       xd->xname = NULL;
+       xd->xvalue = NULL;
+}
+
+static void reclaim_xattr_datum(struct jffs2_sb_info *c)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_datum *xd, *_xd;
+       uint32_t target, before;
+       static int index = 0;
+       int count;
+
+       if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
+               return;
+
+       before = c->xdatum_mem_usage;
+       target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */
+       for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
+               list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
+                       if (xd->flags & JFFS2_XFLAGS_HOT) {
+                               xd->flags &= ~JFFS2_XFLAGS_HOT;
+                       } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
+                               unload_xattr_datum(c, xd);
+                       }
+                       if (c->xdatum_mem_usage <= target)
+                               goto out;
+               }
+               index = (index+1) % XATTRINDEX_HASHSIZE;
+       }
+ out:
+       JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
+                    before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
+}
+
+static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_eraseblock *jeb;
+       struct jffs2_raw_node_ref *raw;
+       struct jffs2_raw_xattr rx;
+       size_t readlen;
+       uint32_t crc, offset, totlen;
+       int rc;
+
+       spin_lock(&c->erase_completion_lock);
+       offset = ref_offset(xd->node);
+       if (ref_flags(xd->node) == REF_PRISTINE)
+               goto complete;
+       spin_unlock(&c->erase_completion_lock);
+
+       rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
+       if (rc || readlen != sizeof(rx)) {
+               JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
+                             rc, sizeof(rx), readlen, offset);
+               return rc ? rc : -EIO;
+       }
+       crc = crc32(0, &rx, sizeof(rx) - 4);
+       if (crc != je32_to_cpu(rx.node_crc)) {
+               JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                           offset, je32_to_cpu(rx.hdr_crc), crc);
+               xd->flags |= JFFS2_XFLAGS_INVALID;
+               return EIO;
+       }
+       totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
+       if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
+           || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
+           || je32_to_cpu(rx.totlen) != totlen
+           || je32_to_cpu(rx.xid) != xd->xid
+           || je32_to_cpu(rx.version) != xd->version) {
+               JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
+                           "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
+                           offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
+                           je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
+                           je32_to_cpu(rx.totlen), totlen,
+                           je32_to_cpu(rx.xid), xd->xid,
+                           je32_to_cpu(rx.version), xd->version);
+               xd->flags |= JFFS2_XFLAGS_INVALID;
+               return EIO;
+       }
+       xd->xprefix = rx.xprefix;
+       xd->name_len = rx.name_len;
+       xd->value_len = je16_to_cpu(rx.value_len);
+       xd->data_crc = je32_to_cpu(rx.data_crc);
+
+       spin_lock(&c->erase_completion_lock);
+ complete:
+       for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
+               jeb = &c->blocks[ref_offset(raw) / c->sector_size];
+               totlen = PAD(ref_totlen(c, jeb, raw));
+               if (ref_flags(raw) == REF_UNCHECKED) {
+                       c->unchecked_size -= totlen; c->used_size += totlen;
+                       jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+               }
+               raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
+       }
+       spin_unlock(&c->erase_completion_lock);
+
+       /* unchecked xdatum is chained with c->xattr_unchecked */
+       list_del_init(&xd->xindex);
+
+       dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
+                 xd->xid, xd->version);
+
+       return 0;
+}
+
+static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       char *data;
+       size_t readlen;
+       uint32_t crc, length;
+       int i, ret, retry = 0;
+
+       BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
+       BUG_ON(!list_empty(&xd->xindex));
+ retry:
+       length = xd->name_len + 1 + xd->value_len;
+       data = kmalloc(length, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
+                              length, &readlen, data);
+
+       if (ret || length!=readlen) {
+               JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n",
+                             ret, length, readlen, ref_offset(xd->node));
+               kfree(data);
+               return ret ? ret : -EIO;
+       }
+
+       data[xd->name_len] = '\0';
+       crc = crc32(0, data, length);
+       if (crc != xd->data_crc) {
+               JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)"
+                             " at %#08x, read: 0x%08x calculated: 0x%08x\n",
+                             ref_offset(xd->node), xd->data_crc, crc);
+               kfree(data);
+               xd->flags |= JFFS2_XFLAGS_INVALID;
+               return EIO;
+       }
+
+       xd->flags |= JFFS2_XFLAGS_HOT;
+       xd->xname = data;
+       xd->xvalue = data + xd->name_len+1;
+
+       c->xdatum_mem_usage += length;
+
+       xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
+       i = xd->hashkey % XATTRINDEX_HASHSIZE;
+       list_add(&xd->xindex, &c->xattrindex[i]);
+       if (!retry) {
+               retry = 1;
+               reclaim_xattr_datum(c);
+               if (!xd->xname)
+                       goto retry;
+       }
+
+       dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
+                 xd->xid, xd->xprefix, xd->xname);
+
+       return 0;
+}
+
+static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem);
+        * rc < 0 : recoverable error, try again
+        * rc = 0 : success
+        * rc > 0 : Unrecoverable error, this node should be deleted.
+        */
+       int rc = 0;
+
+       BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
+       if (xd->xname)
+               return 0;
+       if (xd->flags & JFFS2_XFLAGS_INVALID)
+               return EIO;
+       if (unlikely(is_xattr_datum_unchecked(c, xd)))
+               rc = do_verify_xattr_datum(c, xd);
+       if (!rc)
+               rc = do_load_xattr_datum(c, xd);
+       return rc;
+}
+
+static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_raw_xattr rx;
+       struct kvec vecs[2];
+       size_t length;
+       int rc, totlen;
+       uint32_t phys_ofs = write_ofs(c);
+
+       BUG_ON(!xd->xname);
+       BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
+
+       vecs[0].iov_base = &rx;
+       vecs[0].iov_len = sizeof(rx);
+       vecs[1].iov_base = xd->xname;
+       vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
+       totlen = vecs[0].iov_len + vecs[1].iov_len;
+
+       /* Setup raw-xattr */
+       memset(&rx, 0, sizeof(rx));
+       rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+       rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
+       rx.totlen = cpu_to_je32(PAD(totlen));
+       rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
+
+       rx.xid = cpu_to_je32(xd->xid);
+       rx.version = cpu_to_je32(++xd->version);
+       rx.xprefix = xd->xprefix;
+       rx.name_len = xd->name_len;
+       rx.value_len = cpu_to_je16(xd->value_len);
+       rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
+       rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
+
+       rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
+       if (rc || totlen != length) {
+               JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
+                             rc, totlen, length, phys_ofs);
+               rc = rc ? rc : -EIO;
+               if (length)
+                       jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
+
+               return rc;
+       }
+       /* success */
+       jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
+
+       dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
+                 xd->xid, xd->version, xd->xprefix, xd->xname);
+
+       return 0;
+}
+
+static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
+                                                   int xprefix, const char *xname,
+                                                   const char *xvalue, int xsize)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_datum *xd;
+       uint32_t hashkey, name_len;
+       char *data;
+       int i, rc;
+
+       /* Search xattr_datum has same xname/xvalue by index */
+       hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
+       i = hashkey % XATTRINDEX_HASHSIZE;
+       list_for_each_entry(xd, &c->xattrindex[i], xindex) {
+               if (xd->hashkey==hashkey
+                   && xd->xprefix==xprefix
+                   && xd->value_len==xsize
+                   && !strcmp(xd->xname, xname)
+                   && !memcmp(xd->xvalue, xvalue, xsize)) {
+                       atomic_inc(&xd->refcnt);
+                       return xd;
+               }
+       }
+
+       /* Not found, Create NEW XATTR-Cache */
+       name_len = strlen(xname);
+
+       xd = jffs2_alloc_xattr_datum();
+       if (!xd)
+               return ERR_PTR(-ENOMEM);
+
+       data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
+       if (!data) {
+               jffs2_free_xattr_datum(xd);
+               return ERR_PTR(-ENOMEM);
+       }
+       strcpy(data, xname);
+       memcpy(data + name_len + 1, xvalue, xsize);
+
+       atomic_set(&xd->refcnt, 1);
+       xd->xid = ++c->highest_xid;
+       xd->flags |= JFFS2_XFLAGS_HOT;
+       xd->xprefix = xprefix;
+
+       xd->hashkey = hashkey;
+       xd->xname = data;
+       xd->xvalue = data + name_len + 1;
+       xd->name_len = name_len;
+       xd->value_len = xsize;
+       xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
+
+       rc = save_xattr_datum(c, xd);
+       if (rc) {
+               kfree(xd->xname);
+               jffs2_free_xattr_datum(xd);
+               return ERR_PTR(rc);
+       }
+
+       /* Insert Hash Index */
+       i = hashkey % XATTRINDEX_HASHSIZE;
+       list_add(&xd->xindex, &c->xattrindex[i]);
+
+       c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
+       reclaim_xattr_datum(c);
+
+       return xd;
+}
+
+static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) {
+               uint32_t xid = xd->xid, version = xd->version;
+
+               unload_xattr_datum(c, xd);
+               xd->flags |= JFFS2_XFLAGS_DEAD;
+               if (xd->node == (void *)xd) {
+                       BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
+                       jffs2_free_xattr_datum(xd);
+               } else {
+                       list_add(&xd->xindex, &c->xattr_dead_list);
+               }
+               spin_unlock(&c->erase_completion_lock);
+
+               dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version);
+       }
+}
+
+/* -------- xref related functions ------------------
+ * verify_xattr_ref(c, ref)
+ *   is used to load xref information from medium. Because summary data does not
+ *   contain xid/ino, it's necessary to verify once while mounting process.
+ * save_xattr_ref(c, ref)
+ *   is used to write xref to medium. If delete marker is marked, it write
+ *   a delete marker of xref into medium.
+ * create_xattr_ref(c, ic, xd)
+ *   is used to create a new xref and write to medium.
+ * delete_xattr_ref(c, ref)
+ *   is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER,
+ *   and allows GC to reclaim those physical nodes.
+ * jffs2_xattr_delete_inode(c, ic)
+ *   is called to remove xrefs related to obsolete inode when inode is unlinked.
+ * jffs2_xattr_free_inode(c, ic)
+ *   is called to release xattr related objects when unmounting. 
+ * check_xattr_ref_inode(c, ic)
+ *   is used to confirm inode does not have duplicate xattr name/value pair.
+ * -------------------------------------------------- */
+static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       struct jffs2_eraseblock *jeb;
+       struct jffs2_raw_node_ref *raw;
+       struct jffs2_raw_xref rr;
+       size_t readlen;
+       uint32_t crc, offset, totlen;
+       int rc;
+
+       spin_lock(&c->erase_completion_lock);
+       if (ref_flags(ref->node) != REF_UNCHECKED)
+               goto complete;
+       offset = ref_offset(ref->node);
+       spin_unlock(&c->erase_completion_lock);
+
+       rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
+       if (rc || sizeof(rr) != readlen) {
+               JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
+                             rc, sizeof(rr), readlen, offset);
+               return rc ? rc : -EIO;
+       }
+       /* obsolete node */
+       crc = crc32(0, &rr, sizeof(rr) - 4);
+       if (crc != je32_to_cpu(rr.node_crc)) {
+               JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                           offset, je32_to_cpu(rr.node_crc), crc);
+               return EIO;
+       }
+       if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
+           || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
+           || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
+               JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
+                           "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
+                           offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
+                           je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
+                           je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
+               return EIO;
+       }
+       ref->ino = je32_to_cpu(rr.ino);
+       ref->xid = je32_to_cpu(rr.xid);
+       ref->xseqno = je32_to_cpu(rr.xseqno);
+       if (ref->xseqno > c->highest_xseqno)
+               c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
+
+       spin_lock(&c->erase_completion_lock);
+ complete:
+       for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
+               jeb = &c->blocks[ref_offset(raw) / c->sector_size];
+               totlen = PAD(ref_totlen(c, jeb, raw));
+               if (ref_flags(raw) == REF_UNCHECKED) {
+                       c->unchecked_size -= totlen; c->used_size += totlen;
+                       jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+               }
+               raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
+       }
+       spin_unlock(&c->erase_completion_lock);
+
+       dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
+                 ref->ino, ref->xid, ref_offset(ref->node));
+       return 0;
+}
+
+static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_raw_xref rr;
+       size_t length;
+       uint32_t xseqno, phys_ofs = write_ofs(c);
+       int ret;
+
+       rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+       rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
+       rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
+       rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
+
+       xseqno = (c->highest_xseqno += 2);
+       if (is_xattr_ref_dead(ref)) {
+               xseqno |= XREF_DELETE_MARKER;
+               rr.ino = cpu_to_je32(ref->ino);
+               rr.xid = cpu_to_je32(ref->xid);
+       } else {
+               rr.ino = cpu_to_je32(ref->ic->ino);
+               rr.xid = cpu_to_je32(ref->xd->xid);
+       }
+       rr.xseqno = cpu_to_je32(xseqno);
+       rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
+
+       ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
+       if (ret || sizeof(rr) != length) {
+               JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",
+                             ret, sizeof(rr), length, phys_ofs);
+               ret = ret ? ret : -EIO;
+               if (length)
+                       jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
+
+               return ret;
+       }
+       /* success */
+       ref->xseqno = xseqno;
+       jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
+
+       dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
+
+       return 0;
+}
+
+static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
+                                               struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_ref *ref;
+       int ret;
+
+       ref = jffs2_alloc_xattr_ref();
+       if (!ref)
+               return ERR_PTR(-ENOMEM);
+       ref->ic = ic;
+       ref->xd = xd;
+
+       ret = save_xattr_ref(c, ref);
+       if (ret) {
+               jffs2_free_xattr_ref(ref);
+               return ERR_PTR(ret);
+       }
+
+       /* Chain to inode */
+       ref->next = ic->xref;
+       ic->xref = ref;
+
+       return ref; /* success */
+}
+
+static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_datum *xd;
+
+       xd = ref->xd;
+       ref->xseqno |= XREF_DELETE_MARKER;
+       ref->ino = ref->ic->ino;
+       ref->xid = ref->xd->xid;
+       spin_lock(&c->erase_completion_lock);
+       ref->next = c->xref_dead_list;
+       c->xref_dead_list = ref;
+       spin_unlock(&c->erase_completion_lock);
+
+       dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
+                 ref->ino, ref->xid, ref->xseqno);
+
+       unrefer_xattr_datum(c, xd);
+}
+
+void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+       /* It's called from jffs2_clear_inode() on inode removing.
+          When an inode with XATTR is removed, those XATTRs must be removed. */
+       struct jffs2_xattr_ref *ref, *_ref;
+
+       if (!ic || ic->nlink > 0)
+               return;
+
+       down_write(&c->xattr_sem);
+       for (ref = ic->xref; ref; ref = _ref) {
+               _ref = ref->next;
+               delete_xattr_ref(c, ref);
+       }
+       ic->xref = NULL;
+       up_write(&c->xattr_sem);
+}
+
+void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+       /* It's called from jffs2_free_ino_caches() until unmounting FS. */
+       struct jffs2_xattr_datum *xd;
+       struct jffs2_xattr_ref *ref, *_ref;
+
+       down_write(&c->xattr_sem);
+       for (ref = ic->xref; ref; ref = _ref) {
+               _ref = ref->next;
+               xd = ref->xd;
+               if (atomic_dec_and_test(&xd->refcnt)) {
+                       unload_xattr_datum(c, xd);
+                       jffs2_free_xattr_datum(xd);
+               }
+               jffs2_free_xattr_ref(ref);
+       }
+       ic->xref = NULL;
+       up_write(&c->xattr_sem);
+}
+
+static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+       /* success of check_xattr_ref_inode() means taht inode (ic) dose not have
+        * duplicate name/value pairs. If duplicate name/value pair would be found,
+        * one will be removed.
+        */
+       struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
+       int rc = 0;
+
+       if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
+               return 0;
+       down_write(&c->xattr_sem);
+ retry:
+       rc = 0;
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               if (!ref->xd->xname) {
+                       rc = load_xattr_datum(c, ref->xd);
+                       if (unlikely(rc > 0)) {
+                               *pref = ref->next;
+                               delete_xattr_ref(c, ref);
+                               goto retry;
+                       } else if (unlikely(rc < 0))
+                               goto out;
+               }
+               for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
+                       if (!cmp->xd->xname) {
+                               ref->xd->flags |= JFFS2_XFLAGS_BIND;
+                               rc = load_xattr_datum(c, cmp->xd);
+                               ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
+                               if (unlikely(rc > 0)) {
+                                       *pcmp = cmp->next;
+                                       delete_xattr_ref(c, cmp);
+                                       goto retry;
+                               } else if (unlikely(rc < 0))
+                                       goto out;
+                       }
+                       if (ref->xd->xprefix == cmp->xd->xprefix
+                           && !strcmp(ref->xd->xname, cmp->xd->xname)) {
+                               if (ref->xseqno > cmp->xseqno) {
+                                       *pcmp = cmp->next;
+                                       delete_xattr_ref(c, cmp);
+                               } else {
+                                       *pref = ref->next;
+                                       delete_xattr_ref(c, ref);
+                               }
+                               goto retry;
+                       }
+               }
+       }
+       ic->flags |= INO_FLAGS_XATTR_CHECKED;
+ out:
+       up_write(&c->xattr_sem);
+
+       return rc;
+}
+
+/* -------- xattr subsystem functions ---------------
+ * jffs2_init_xattr_subsystem(c)
+ *   is used to initialize semaphore and list_head, and some variables.
+ * jffs2_find_xattr_datum(c, xid)
+ *   is used to lookup xdatum while scanning process.
+ * jffs2_clear_xattr_subsystem(c)
+ *   is used to release any xattr related objects.
+ * jffs2_build_xattr_subsystem(c)
+ *   is used to associate xdatum and xref while super block building process.
+ * jffs2_setup_xattr_datum(c, xid, version)
+ *   is used to insert xdatum while scanning process.
+ * -------------------------------------------------- */
+void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
+{
+       int i;
+
+       for (i=0; i < XATTRINDEX_HASHSIZE; i++)
+               INIT_LIST_HEAD(&c->xattrindex[i]);
+       INIT_LIST_HEAD(&c->xattr_unchecked);
+       INIT_LIST_HEAD(&c->xattr_dead_list);
+       c->xref_dead_list = NULL;
+       c->xref_temp = NULL;
+
+       init_rwsem(&c->xattr_sem);
+       c->highest_xid = 0;
+       c->highest_xseqno = 0;
+       c->xdatum_mem_usage = 0;
+       c->xdatum_mem_threshold = 32 * 1024;    /* Default 32KB */
+}
+
+static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
+{
+       struct jffs2_xattr_datum *xd;
+       int i = xid % XATTRINDEX_HASHSIZE;
+
+       /* It's only used in scanning/building process. */
+       BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
+
+       list_for_each_entry(xd, &c->xattrindex[i], xindex) {
+               if (xd->xid==xid)
+                       return xd;
+       }
+       return NULL;
+}
+
+void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
+{
+       struct jffs2_xattr_datum *xd, *_xd;
+       struct jffs2_xattr_ref *ref, *_ref;
+       int i;
+
+       for (ref=c->xref_temp; ref; ref = _ref) {
+               _ref = ref->next;
+               jffs2_free_xattr_ref(ref);
+       }
+
+       for (ref=c->xref_dead_list; ref; ref = _ref) {
+               _ref = ref->next;
+               jffs2_free_xattr_ref(ref);
+       }
+
+       for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
+               list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
+                       list_del(&xd->xindex);
+                       if (xd->xname)
+                               kfree(xd->xname);
+                       jffs2_free_xattr_datum(xd);
+               }
+       }
+
+       list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
+               list_del(&xd->xindex);
+               jffs2_free_xattr_datum(xd);
+       }
+}
+
+#define XREF_TMPHASH_SIZE      (128)
+void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
+{
+       struct jffs2_xattr_ref *ref, *_ref;
+       struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
+       struct jffs2_xattr_datum *xd, *_xd;
+       struct jffs2_inode_cache *ic;
+       struct jffs2_raw_node_ref *raw;
+       int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
+       int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
+
+       BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
+
+       /* Phase.1 : Merge same xref */
+       for (i=0; i < XREF_TMPHASH_SIZE; i++)
+               xref_tmphash[i] = NULL;
+       for (ref=c->xref_temp; ref; ref=_ref) {
+               struct jffs2_xattr_ref *tmp;
+
+               _ref = ref->next;
+               if (ref_flags(ref->node) != REF_PRISTINE) {
+                       if (verify_xattr_ref(c, ref)) {
+                               BUG_ON(ref->node->next_in_ino != (void *)ref);
+                               ref->node->next_in_ino = NULL;
+                               jffs2_mark_node_obsolete(c, ref->node);
+                               jffs2_free_xattr_ref(ref);
+                               continue;
+                       }
+               }
+
+               i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
+               for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
+                       if (tmp->ino == ref->ino && tmp->xid == ref->xid)
+                               break;
+               }
+               if (tmp) {
+                       raw = ref->node;
+                       if (ref->xseqno > tmp->xseqno) {
+                               tmp->xseqno = ref->xseqno;
+                               raw->next_in_ino = tmp->node;
+                               tmp->node = raw;
+                       } else {
+                               raw->next_in_ino = tmp->node->next_in_ino;
+                               tmp->node->next_in_ino = raw;
+                       }
+                       jffs2_free_xattr_ref(ref);
+                       continue;
+               } else {
+                       ref->next = xref_tmphash[i];
+                       xref_tmphash[i] = ref;
+               }
+       }
+       c->xref_temp = NULL;
+
+       /* Phase.2 : Bind xref with inode_cache and xattr_datum */
+       for (i=0; i < XREF_TMPHASH_SIZE; i++) {
+               for (ref=xref_tmphash[i]; ref; ref=_ref) {
+                       xref_count++;
+                       _ref = ref->next;
+                       if (is_xattr_ref_dead(ref)) {
+                               ref->next = c->xref_dead_list;
+                               c->xref_dead_list = ref;
+                               xref_dead_count++;
+                               continue;
+                       }
+                       /* At this point, ref->xid and ref->ino contain XID and inode number.
+                          ref->xd and ref->ic are not valid yet. */
+                       xd = jffs2_find_xattr_datum(c, ref->xid);
+                       ic = jffs2_get_ino_cache(c, ref->ino);
+                       if (!xd || !ic) {
+                               dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
+                                         ref->ino, ref->xid, ref->xseqno);
+                               ref->xseqno |= XREF_DELETE_MARKER;
+                               ref->next = c->xref_dead_list;
+                               c->xref_dead_list = ref;
+                               xref_orphan_count++;
+                               continue;
+                       }
+                       ref->xd = xd;
+                       ref->ic = ic;
+                       atomic_inc(&xd->refcnt);
+                       ref->next = ic->xref;
+                       ic->xref = ref;
+               }
+       }
+
+       /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */
+       for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
+               list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
+                       xdatum_count++;
+                       list_del_init(&xd->xindex);
+                       if (!atomic_read(&xd->refcnt)) {
+                               dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
+                                         xd->xid, xd->version);
+                               xd->flags |= JFFS2_XFLAGS_DEAD;
+                               list_add(&xd->xindex, &c->xattr_unchecked);
+                               xdatum_orphan_count++;
+                               continue;
+                       }
+                       if (is_xattr_datum_unchecked(c, xd)) {
+                               dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
+                                         xd->xid, xd->version);
+                               list_add(&xd->xindex, &c->xattr_unchecked);
+                               xdatum_unchecked_count++;
+                       }
+               }
+       }
+       /* build complete */
+       JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
+                    " (%u unchecked, %u orphan) and "
+                    "%u of xref (%u dead, %u orphan) found.\n",
+                    xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
+                    xref_count, xref_dead_count, xref_orphan_count);
+}
+
+struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+                                                 uint32_t xid, uint32_t version)
+{
+       struct jffs2_xattr_datum *xd;
+
+       xd = jffs2_find_xattr_datum(c, xid);
+       if (!xd) {
+               xd = jffs2_alloc_xattr_datum();
+               if (!xd)
+                       return ERR_PTR(-ENOMEM);
+               xd->xid = xid;
+               xd->version = version;
+               if (xd->xid > c->highest_xid)
+                       c->highest_xid = xd->xid;
+               list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
+       }
+       return xd;
+}
+
+/* -------- xattr subsystem functions ---------------
+ * xprefix_to_handler(xprefix)
+ *   is used to translate xprefix into xattr_handler.
+ * jffs2_listxattr(dentry, buffer, size)
+ *   is an implementation of listxattr handler on jffs2.
+ * do_jffs2_getxattr(inode, xprefix, xname, buffer, size)
+ *   is an implementation of getxattr handler on jffs2.
+ * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags)
+ *   is an implementation of setxattr handler on jffs2.
+ * -------------------------------------------------- */
+struct xattr_handler *jffs2_xattr_handlers[] = {
+       &jffs2_user_xattr_handler,
+#ifdef CONFIG_JFFS2_FS_SECURITY
+       &jffs2_security_xattr_handler,
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       &jffs2_acl_access_xattr_handler,
+       &jffs2_acl_default_xattr_handler,
+#endif
+       &jffs2_trusted_xattr_handler,
+       NULL
+};
+
+static struct xattr_handler *xprefix_to_handler(int xprefix) {
+       struct xattr_handler *ret;
+
+       switch (xprefix) {
+       case JFFS2_XPREFIX_USER:
+               ret = &jffs2_user_xattr_handler;
+               break;
+#ifdef CONFIG_JFFS2_FS_SECURITY
+       case JFFS2_XPREFIX_SECURITY:
+               ret = &jffs2_security_xattr_handler;
+               break;
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       case JFFS2_XPREFIX_ACL_ACCESS:
+               ret = &jffs2_acl_access_xattr_handler;
+               break;
+       case JFFS2_XPREFIX_ACL_DEFAULT:
+               ret = &jffs2_acl_default_xattr_handler;
+               break;
+#endif
+       case JFFS2_XPREFIX_TRUSTED:
+               ret = &jffs2_trusted_xattr_handler;
+               break;
+       default:
+               ret = NULL;
+               break;
+       }
+       return ret;
+}
+
+ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+       struct inode *inode = dentry->d_inode;
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_inode_cache *ic = f->inocache;
+       struct jffs2_xattr_ref *ref, **pref;
+       struct jffs2_xattr_datum *xd;
+       struct xattr_handler *xhandle;
+       ssize_t len, rc;
+       int retry = 0;
+
+       rc = check_xattr_ref_inode(c, ic);
+       if (unlikely(rc))
+               return rc;
+
+       down_read(&c->xattr_sem);
+ retry:
+       len = 0;
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               BUG_ON(ref->ic != ic);
+               xd = ref->xd;
+               if (!xd->xname) {
+                       /* xdatum is unchached */
+                       if (!retry) {
+                               retry = 1;
+                               up_read(&c->xattr_sem);
+                               down_write(&c->xattr_sem);
+                               goto retry;
+                       } else {
+                               rc = load_xattr_datum(c, xd);
+                               if (unlikely(rc > 0)) {
+                                       *pref = ref->next;
+                                       delete_xattr_ref(c, ref);
+                                       goto retry;
+                               } else if (unlikely(rc < 0))
+                                       goto out;
+                       }
+               }
+               xhandle = xprefix_to_handler(xd->xprefix);
+               if (!xhandle)
+                       continue;
+               if (buffer) {
+                       rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
+               } else {
+                       rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
+               }
+               if (rc < 0)
+                       goto out;
+               len += rc;
+       }
+       rc = len;
+ out:
+       if (!retry) {
+               up_read(&c->xattr_sem);
+       } else {
+               up_write(&c->xattr_sem);
+       }
+       return rc;
+}
+
+int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
+                     char *buffer, size_t size)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_inode_cache *ic = f->inocache;
+       struct jffs2_xattr_datum *xd;
+       struct jffs2_xattr_ref *ref, **pref;
+       int rc, retry = 0;
+
+       rc = check_xattr_ref_inode(c, ic);
+       if (unlikely(rc))
+               return rc;
+
+       down_read(&c->xattr_sem);
+ retry:
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               BUG_ON(ref->ic!=ic);
+
+               xd = ref->xd;
+               if (xd->xprefix != xprefix)
+                       continue;
+               if (!xd->xname) {
+                       /* xdatum is unchached */
+                       if (!retry) {
+                               retry = 1;
+                               up_read(&c->xattr_sem);
+                               down_write(&c->xattr_sem);
+                               goto retry;
+                       } else {
+                               rc = load_xattr_datum(c, xd);
+                               if (unlikely(rc > 0)) {
+                                       *pref = ref->next;
+                                       delete_xattr_ref(c, ref);
+                                       goto retry;
+                               } else if (unlikely(rc < 0)) {
+                                       goto out;
+                               }
+                       }
+               }
+               if (!strcmp(xname, xd->xname)) {
+                       rc = xd->value_len;
+                       if (buffer) {
+                               if (size < rc) {
+                                       rc = -ERANGE;
+                               } else {
+                                       memcpy(buffer, xd->xvalue, rc);
+                               }
+                       }
+                       goto out;
+               }
+       }
+       rc = -ENODATA;
+ out:
+       if (!retry) {
+               up_read(&c->xattr_sem);
+       } else {
+               up_write(&c->xattr_sem);
+       }
+       return rc;
+}
+
+int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+                     const char *buffer, size_t size, int flags)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_inode_cache *ic = f->inocache;
+       struct jffs2_xattr_datum *xd;
+       struct jffs2_xattr_ref *ref, *newref, **pref;
+       uint32_t length, request;
+       int rc;
+
+       rc = check_xattr_ref_inode(c, ic);
+       if (unlikely(rc))
+               return rc;
+
+       request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
+       rc = jffs2_reserve_space(c, request, &length,
+                                ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
+       if (rc) {
+               JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
+               return rc;
+       }
+
+       /* Find existing xattr */
+       down_write(&c->xattr_sem);
+ retry:
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               xd = ref->xd;
+               if (xd->xprefix != xprefix)
+                       continue;
+               if (!xd->xname) {
+                       rc = load_xattr_datum(c, xd);
+                       if (unlikely(rc > 0)) {
+                               *pref = ref->next;
+                               delete_xattr_ref(c, ref);
+                               goto retry;
+                       } else if (unlikely(rc < 0))
+                               goto out;
+               }
+               if (!strcmp(xd->xname, xname)) {
+                       if (flags & XATTR_CREATE) {
+                               rc = -EEXIST;
+                               goto out;
+                       }
+                       if (!buffer) {
+                               ref->ino = ic->ino;
+                               ref->xid = xd->xid;
+                               ref->xseqno |= XREF_DELETE_MARKER;
+                               rc = save_xattr_ref(c, ref);
+                               if (!rc) {
+                                       *pref = ref->next;
+                                       spin_lock(&c->erase_completion_lock);
+                                       ref->next = c->xref_dead_list;
+                                       c->xref_dead_list = ref;
+                                       spin_unlock(&c->erase_completion_lock);
+                                       unrefer_xattr_datum(c, xd);
+                               } else {
+                                       ref->ic = ic;
+                                       ref->xd = xd;
+                                       ref->xseqno &= ~XREF_DELETE_MARKER;
+                               }
+                               goto out;
+                       }
+                       goto found;
+               }
+       }
+       /* not found */
+       if (flags & XATTR_REPLACE) {
+               rc = -ENODATA;
+               goto out;
+       }
+       if (!buffer) {
+               rc = -ENODATA;
+               goto out;
+       }
+ found:
+       xd = create_xattr_datum(c, xprefix, xname, buffer, size);
+       if (IS_ERR(xd)) {
+               rc = PTR_ERR(xd);
+               goto out;
+       }
+       up_write(&c->xattr_sem);
+       jffs2_complete_reservation(c);
+
+       /* create xattr_ref */
+       request = PAD(sizeof(struct jffs2_raw_xref));
+       rc = jffs2_reserve_space(c, request, &length,
+                                ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
+       down_write(&c->xattr_sem);
+       if (rc) {
+               JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
+               unrefer_xattr_datum(c, xd);
+               up_write(&c->xattr_sem);
+               return rc;
+       }
+       if (ref)
+               *pref = ref->next;
+       newref = create_xattr_ref(c, ic, xd);
+       if (IS_ERR(newref)) {
+               if (ref) {
+                       ref->next = ic->xref;
+                       ic->xref = ref;
+               }
+               rc = PTR_ERR(newref);
+               unrefer_xattr_datum(c, xd);
+       } else if (ref) {
+               delete_xattr_ref(c, ref);
+       }
+ out:
+       up_write(&c->xattr_sem);
+       jffs2_complete_reservation(c);
+       return rc;
+}
+
+/* -------- garbage collector functions -------------
+ * jffs2_garbage_collect_xattr_datum(c, xd, raw)
+ *   is used to move xdatum into new node.
+ * jffs2_garbage_collect_xattr_ref(c, ref, raw)
+ *   is used to move xref into new node.
+ * jffs2_verify_xattr(c)
+ *   is used to call do_verify_xattr_datum() before garbage collecting.
+ * jffs2_release_xattr_datum(c, xd)
+ *   is used to release an in-memory object of xdatum.
+ * jffs2_release_xattr_ref(c, ref)
+ *   is used to release an in-memory object of xref.
+ * -------------------------------------------------- */
+int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
+                                     struct jffs2_raw_node_ref *raw)
+{
+       uint32_t totlen, length, old_ofs;
+       int rc = 0;
+
+       down_write(&c->xattr_sem);
+       if (xd->node != raw)
+               goto out;
+       if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
+               goto out;
+
+       rc = load_xattr_datum(c, xd);
+       if (unlikely(rc)) {
+               rc = (rc > 0) ? 0 : rc;
+               goto out;
+       }
+       old_ofs = ref_offset(xd->node);
+       totlen = PAD(sizeof(struct jffs2_raw_xattr)
+                       + xd->name_len + 1 + xd->value_len);
+       rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
+       if (rc) {
+               JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
+               goto out;
+       }
+       rc = save_xattr_datum(c, xd);
+       if (!rc)
+               dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
+                         xd->xid, xd->version, old_ofs, ref_offset(xd->node));
+ out:
+       if (!rc)
+               jffs2_mark_node_obsolete(c, raw);
+       up_write(&c->xattr_sem);
+       return rc;
+}
+
+int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
+                                   struct jffs2_raw_node_ref *raw)
+{
+       uint32_t totlen, length, old_ofs;
+       int rc = 0;
+
+       down_write(&c->xattr_sem);
+       BUG_ON(!ref->node);
+
+       if (ref->node != raw)
+               goto out;
+       if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
+               goto out;
+
+       old_ofs = ref_offset(ref->node);
+       totlen = ref_totlen(c, c->gcblock, ref->node);
+
+       rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
+       if (rc) {
+               JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
+                             __FUNCTION__, rc, totlen);
+               rc = rc ? rc : -EBADFD;
+               goto out;
+       }
+       rc = save_xattr_ref(c, ref);
+       if (!rc)
+               dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
+                         ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
+ out:
+       if (!rc)
+               jffs2_mark_node_obsolete(c, raw);
+       up_write(&c->xattr_sem);
+       return rc;
+}
+
+int jffs2_verify_xattr(struct jffs2_sb_info *c)
+{
+       struct jffs2_xattr_datum *xd, *_xd;
+       struct jffs2_eraseblock *jeb;
+       struct jffs2_raw_node_ref *raw;
+       uint32_t totlen;
+       int rc;
+
+       down_write(&c->xattr_sem);
+       list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
+               rc = do_verify_xattr_datum(c, xd);
+               if (rc < 0)
+                       continue;
+               list_del_init(&xd->xindex);
+               spin_lock(&c->erase_completion_lock);
+               for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
+                       if (ref_flags(raw) != REF_UNCHECKED)
+                               continue;
+                       jeb = &c->blocks[ref_offset(raw) / c->sector_size];
+                       totlen = PAD(ref_totlen(c, jeb, raw));
+                       c->unchecked_size -= totlen; c->used_size += totlen;
+                       jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+                       raw->flash_offset = ref_offset(raw)
+                               | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
+               }
+               if (xd->flags & JFFS2_XFLAGS_DEAD)
+                       list_add(&xd->xindex, &c->xattr_dead_list);
+               spin_unlock(&c->erase_completion_lock);
+       }
+       up_write(&c->xattr_sem);
+       return list_empty(&c->xattr_unchecked) ? 1 : 0;
+}
+
+void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under spin_lock(&c->erase_completion_lock) */
+       if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)
+               return;
+
+       list_del(&xd->xindex);
+       jffs2_free_xattr_datum(xd);
+}
+
+void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       /* must be called under spin_lock(&c->erase_completion_lock) */
+       struct jffs2_xattr_ref *tmp, **ptmp;
+
+       if (ref->node != (void *)ref)
+               return;
+
+       for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
+               if (ref == tmp) {
+                       *ptmp = tmp->next;
+                       break;
+               }
+       }
+       jffs2_free_xattr_ref(ref);
+}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
new file mode 100644 (file)
index 0000000..06a5c69
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#ifndef _JFFS2_FS_XATTR_H_
+#define _JFFS2_FS_XATTR_H_
+
+#include <linux/xattr.h>
+#include <linux/list.h>
+
+#define JFFS2_XFLAGS_HOT       (0x01)  /* This datum is HOT */
+#define JFFS2_XFLAGS_BIND      (0x02)  /* This datum is not reclaimed */
+#define JFFS2_XFLAGS_DEAD      (0x40)  /* This datum is already dead */
+#define JFFS2_XFLAGS_INVALID   (0x80)  /* This datum contains crc error */
+
+struct jffs2_xattr_datum
+{
+       void *always_null;
+       struct jffs2_raw_node_ref *node;
+       uint8_t class;
+       uint8_t flags;
+       uint16_t xprefix;               /* see JFFS2_XATTR_PREFIX_* */
+
+       struct list_head xindex;        /* chained from c->xattrindex[n] */
+       atomic_t refcnt;                /* # of xattr_ref refers this */
+       uint32_t xid;
+       uint32_t version;
+
+       uint32_t data_crc;
+       uint32_t hashkey;
+       char *xname;            /* XATTR name without prefix */
+       uint32_t name_len;      /* length of xname */
+       char *xvalue;           /* XATTR value */
+       uint32_t value_len;     /* length of xvalue */
+};
+
+struct jffs2_inode_cache;
+struct jffs2_xattr_ref
+{
+       void *always_null;
+       struct jffs2_raw_node_ref *node;
+       uint8_t class;
+       uint8_t flags;          /* Currently unused */
+       u16 unused;
+
+       uint32_t xseqno;
+       union {
+               struct jffs2_inode_cache *ic;   /* reference to jffs2_inode_cache */
+               uint32_t ino;                   /* only used in scanning/building  */
+       };
+       union {
+               struct jffs2_xattr_datum *xd;   /* reference to jffs2_xattr_datum */
+               uint32_t xid;                   /* only used in sccanning/building */
+       };
+       struct jffs2_xattr_ref *next;           /* chained from ic->xref_list */
+};
+
+#define XREF_DELETE_MARKER     (0x00000001)
+static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
+{
+       return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
+}
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+
+extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
+extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
+extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
+
+extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+                                                  uint32_t xid, uint32_t version);
+
+extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
+extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
+
+extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
+                                            struct jffs2_raw_node_ref *raw);
+extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
+                                          struct jffs2_raw_node_ref *raw);
+extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
+extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
+extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
+
+extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
+                            char *buffer, size_t size);
+extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+                            const char *buffer, size_t size, int flags);
+
+extern struct xattr_handler *jffs2_xattr_handlers[];
+extern struct xattr_handler jffs2_user_xattr_handler;
+extern struct xattr_handler jffs2_trusted_xattr_handler;
+
+extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
+#define jffs2_getxattr         generic_getxattr
+#define jffs2_setxattr         generic_setxattr
+#define jffs2_removexattr      generic_removexattr
+
+#else
+
+#define jffs2_init_xattr_subsystem(c)
+#define jffs2_build_xattr_subsystem(c)
+#define jffs2_clear_xattr_subsystem(c)
+
+#define jffs2_xattr_delete_inode(c, ic)
+#define jffs2_xattr_free_inode(c, ic)
+#define jffs2_verify_xattr(c)                  (1)
+
+#define jffs2_xattr_handlers   NULL
+#define jffs2_listxattr                NULL
+#define jffs2_getxattr         NULL
+#define jffs2_setxattr         NULL
+#define jffs2_removexattr      NULL
+
+#endif /* CONFIG_JFFS2_FS_XATTR */
+
+#ifdef CONFIG_JFFS2_FS_SECURITY
+extern int jffs2_init_security(struct inode *inode, struct inode *dir);
+extern struct xattr_handler jffs2_security_xattr_handler;
+#else
+#define jffs2_init_security(inode,dir) (0)
+#endif /* CONFIG_JFFS2_FS_SECURITY */
+
+#endif /* _JFFS2_FS_XATTR_H_ */
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
new file mode 100644 (file)
index 0000000..ed046e1
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
+                                 void *buffer, size_t size)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
+}
+
+static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
+                                 size_t size, int flags)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
+}
+
+static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
+                                     const char *name, size_t name_len)
+{
+       size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
+
+       if (list && retlen<=list_size) {
+               strcpy(list, XATTR_TRUSTED_PREFIX);
+               strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
+       }
+
+       return retlen;
+}
+
+struct xattr_handler jffs2_trusted_xattr_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .list = jffs2_trusted_listxattr,
+       .set = jffs2_trusted_setxattr,
+       .get = jffs2_trusted_getxattr
+};
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
new file mode 100644 (file)
index 0000000..2f8e9aa
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static int jffs2_user_getxattr(struct inode *inode, const char *name,
+                               void *buffer, size_t size)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
+}
+
+static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
+                               size_t size, int flags)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
+}
+
+static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
+                                  const char *name, size_t name_len)
+{
+       size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
+
+       if (list && retlen <= list_size) {
+               strcpy(list, XATTR_USER_PREFIX);
+               strcpy(list + XATTR_USER_PREFIX_LEN, name);
+       }
+
+       return retlen;
+}
+
+struct xattr_handler jffs2_user_xattr_handler = {
+       .prefix = XATTR_USER_PREFIX,
+       .list = jffs2_user_listxattr,
+       .set = jffs2_user_setxattr,
+       .get = jffs2_user_getxattr
+};
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
new file mode 100644 (file)
index 0000000..aa9e412
--- /dev/null
@@ -0,0 +1,1436 @@
+/* client.c: NFS client sharing and management code
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/stats.h>
+#include <linux/sunrpc/metrics.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include <linux/nfs4_mount.h>
+#include <linux/lockd/bind.h>
+#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/nfs_idmap.h>
+#include <linux/vfs.h>
+#include <linux/inet.h>
+#include <linux/nfs_xdr.h>
+
+#include <asm/system.h>
+
+#include "nfs4_fs.h"
+#include "callback.h"
+#include "delegation.h"
+#include "iostat.h"
+#include "internal.h"
+
+#define NFSDBG_FACILITY                NFSDBG_CLIENT
+
+static DEFINE_SPINLOCK(nfs_client_lock);
+static LIST_HEAD(nfs_client_list);
+static LIST_HEAD(nfs_volume_list);
+static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
+
+/*
+ * RPC cruft for NFS
+ */
+static struct rpc_version *nfs_version[5] = {
+       [2]                     = &nfs_version2,
+#ifdef CONFIG_NFS_V3
+       [3]                     = &nfs_version3,
+#endif
+#ifdef CONFIG_NFS_V4
+       [4]                     = &nfs_version4,
+#endif
+};
+
+struct rpc_program nfs_program = {
+       .name                   = "nfs",
+       .number                 = NFS_PROGRAM,
+       .nrvers                 = ARRAY_SIZE(nfs_version),
+       .version                = nfs_version,
+       .stats                  = &nfs_rpcstat,
+       .pipe_dir_name          = "/nfs",
+};
+
+struct rpc_stat nfs_rpcstat = {
+       .program                = &nfs_program
+};
+
+
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat         nfsacl_rpcstat = { &nfsacl_program };
+static struct rpc_version *    nfsacl_version[] = {
+       [3]                     = &nfsacl_version3,
+};
+
+struct rpc_program             nfsacl_program = {
+       .name                   = "nfsacl",
+       .number                 = NFS_ACL_PROGRAM,
+       .nrvers                 = ARRAY_SIZE(nfsacl_version),
+       .version                = nfsacl_version,
+       .stats                  = &nfsacl_rpcstat,
+};
+#endif  /* CONFIG_NFS_V3_ACL */
+
+/*
+ * Allocate a shared client record
+ *
+ * Since these are allocated/deallocated very rarely, we don't
+ * bother putting them in a slab cache...
+ */
+static struct nfs_client *nfs_alloc_client(const char *hostname,
+                                          const struct sockaddr_in *addr,
+                                          int nfsversion)
+{
+       struct nfs_client *clp;
+       int error;
+
+       if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
+               goto error_0;
+
+       error = rpciod_up();
+       if (error < 0) {
+               dprintk("%s: couldn't start rpciod! Error = %d\n",
+                               __FUNCTION__, error);
+               goto error_1;
+       }
+       __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
+
+       if (nfsversion == 4) {
+               if (nfs_callback_up() < 0)
+                       goto error_2;
+               __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+       }
+
+       atomic_set(&clp->cl_count, 1);
+       clp->cl_cons_state = NFS_CS_INITING;
+
+       clp->cl_nfsversion = nfsversion;
+       memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+
+       if (hostname) {
+               clp->cl_hostname = kstrdup(hostname, GFP_KERNEL);
+               if (!clp->cl_hostname)
+                       goto error_3;
+       }
+
+       INIT_LIST_HEAD(&clp->cl_superblocks);
+       clp->cl_rpcclient = ERR_PTR(-EINVAL);
+
+#ifdef CONFIG_NFS_V4
+       init_rwsem(&clp->cl_sem);
+       INIT_LIST_HEAD(&clp->cl_delegations);
+       INIT_LIST_HEAD(&clp->cl_state_owners);
+       INIT_LIST_HEAD(&clp->cl_unused);
+       spin_lock_init(&clp->cl_lock);
+       INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
+       rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
+       clp->cl_boot_time = CURRENT_TIME;
+       clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+#endif
+
+       nfs_fscache_get_client_cookie(clp);
+
+       return clp;
+
+error_3:
+       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+               nfs_callback_down();
+error_2:
+       rpciod_down();
+       __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
+error_1:
+       kfree(clp);
+error_0:
+       return NULL;
+}
+
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4
+       if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+               nfs4_kill_renewd(clp);
+       while (!list_empty(&clp->cl_unused)) {
+               struct nfs4_state_owner *sp;
+
+               sp = list_entry(clp->cl_unused.next,
+                               struct nfs4_state_owner,
+                               so_list);
+               list_del(&sp->so_list);
+               kfree(sp);
+       }
+       BUG_ON(!list_empty(&clp->cl_state_owners));
+       if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+               nfs_idmap_delete(clp);
+#endif
+}
+
+/*
+ * Destroy a shared client record
+ */
+static void nfs_free_client(struct nfs_client *clp)
+{
+       dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion);
+
+       nfs4_shutdown_client(clp);
+
+       nfs_fscache_release_client_cookie(clp);
+
+       /* -EIO all pending I/O */
+       if (!IS_ERR(clp->cl_rpcclient))
+               rpc_shutdown_client(clp->cl_rpcclient);
+
+       if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+               nfs_callback_down();
+
+       if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
+               rpciod_down();
+
+       kfree(clp->cl_hostname);
+       kfree(clp);
+
+       dprintk("<-- nfs_free_client()\n");
+}
+
+/*
+ * Release a reference to a shared client record
+ */
+void nfs_put_client(struct nfs_client *clp)
+{
+       if (!clp)
+               return;
+
+       dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count));
+
+       if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) {
+               list_del(&clp->cl_share_link);
+               spin_unlock(&nfs_client_lock);
+
+               BUG_ON(!list_empty(&clp->cl_superblocks));
+
+               nfs_free_client(clp);
+       }
+}
+
+/*
+ * Find a client by address
+ * - caller must hold nfs_client_lock
+ */
+static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
+{
+       struct nfs_client *clp;
+
+       list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+               /* Different NFS versions cannot share the same nfs_client */
+               if (clp->cl_nfsversion != nfsversion)
+                       continue;
+
+               if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr,
+                          sizeof(clp->cl_addr.sin_addr)) != 0)
+                       continue;
+
+               if (clp->cl_addr.sin_port == addr->sin_port)
+                       goto found;
+       }
+
+       return NULL;
+
+found:
+       atomic_inc(&clp->cl_count);
+       return clp;
+}
+
+/*
+ * Find a client by IP address and protocol version
+ * - returns NULL if no such client
+ */
+struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion)
+{
+       struct nfs_client *clp;
+
+       spin_lock(&nfs_client_lock);
+       clp = __nfs_find_client(addr, nfsversion);
+       spin_unlock(&nfs_client_lock);
+
+       BUG_ON(clp->cl_cons_state == 0);
+
+       return clp;
+}
+
+/*
+ * Look up a client by IP address and protocol version
+ * - creates a new record if one doesn't yet exist
+ */
+static struct nfs_client *nfs_get_client(const char *hostname,
+                                        const struct sockaddr_in *addr,
+                                        int nfsversion)
+{
+       struct nfs_client *clp, *new = NULL;
+       int error;
+
+       dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n",
+               hostname ?: "", NIPQUAD(addr->sin_addr),
+               addr->sin_port, nfsversion);
+
+       /* see if the client already exists */
+       do {
+               spin_lock(&nfs_client_lock);
+
+               clp = __nfs_find_client(addr, nfsversion);
+               if (clp)
+                       goto found_client;
+               if (new)
+                       goto install_client;
+
+               spin_unlock(&nfs_client_lock);
+
+               new = nfs_alloc_client(hostname, addr, nfsversion);
+       } while (new);
+
+       return ERR_PTR(-ENOMEM);
+
+       /* install a new client and return with it unready */
+install_client:
+       clp = new;
+       list_add(&clp->cl_share_link, &nfs_client_list);
+       spin_unlock(&nfs_client_lock);
+       dprintk("--> nfs_get_client() = %p [new]\n", clp);
+       return clp;
+
+       /* found an existing client
+        * - make sure it's ready before returning
+        */
+found_client:
+       spin_unlock(&nfs_client_lock);
+
+       if (new)
+               nfs_free_client(new);
+
+       error = wait_event_interruptible(nfs_client_active_wq,
+               clp->cl_cons_state != NFS_CS_INITING);
+       if (error < 0) {
+               nfs_put_client(clp);
+               return ERR_PTR(-ERESTARTSYS);
+       }
+
+       if (clp->cl_cons_state < NFS_CS_READY) {
+               error = clp->cl_cons_state;
+               nfs_put_client(clp);
+               return ERR_PTR(error);
+       }
+
+       BUG_ON(clp->cl_cons_state != NFS_CS_READY);
+
+       dprintk("--> nfs_get_client() = %p [share]\n", clp);
+       return clp;
+}
+
+/*
+ * Mark a server as ready or failed
+ */
+static void nfs_mark_client_ready(struct nfs_client *clp, int state)
+{
+       clp->cl_cons_state = state;
+       wake_up_all(&nfs_client_active_wq);
+}
+
+/*
+ * Initialise the timeout values for a connection
+ */
+static void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
+                                   unsigned int timeo, unsigned int retrans)
+{
+       to->to_initval = timeo * HZ / 10;
+       to->to_retries = retrans;
+       if (!to->to_retries)
+               to->to_retries = 2;
+
+       switch (proto) {
+       case IPPROTO_TCP:
+               if (!to->to_initval)
+                       to->to_initval = 60 * HZ;
+               if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
+                       to->to_initval = NFS_MAX_TCP_TIMEOUT;
+               to->to_increment = to->to_initval;
+               to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
+               to->to_exponential = 0;
+               break;
+       case IPPROTO_UDP:
+       default:
+               if (!to->to_initval)
+                       to->to_initval = 11 * HZ / 10;
+               if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
+                       to->to_initval = NFS_MAX_UDP_TIMEOUT;
+               to->to_maxval = NFS_MAX_UDP_TIMEOUT;
+               to->to_exponential = 1;
+               break;
+       }
+}
+
+/*
+ * Create an RPC client handle
+ */
+static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
+                                               unsigned int timeo,
+                                               unsigned int retrans,
+                                               rpc_authflavor_t flavor)
+{
+       struct rpc_timeout      timeparms;
+       struct rpc_xprt         *xprt = NULL;
+       struct rpc_clnt         *clnt = NULL;
+
+       if (!IS_ERR(clp->cl_rpcclient))
+               return 0;
+
+       nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
+       clp->retrans_timeo = timeparms.to_initval;
+       clp->retrans_count = timeparms.to_retries;
+
+       /* create transport and client */
+       xprt = xprt_create_proto(proto, &clp->cl_addr, &timeparms);
+       if (IS_ERR(xprt)) {
+               dprintk("%s: cannot create RPC transport. Error = %ld\n",
+                               __FUNCTION__, PTR_ERR(xprt));
+               return PTR_ERR(xprt);
+       }
+
+       /* Bind to a reserved port! */
+       xprt->resvport = 1;
+       /* Create the client RPC handle */
+       clnt = rpc_create_client(xprt, clp->cl_hostname, &nfs_program,
+                                clp->rpc_ops->version, RPC_AUTH_UNIX);
+       if (IS_ERR(clnt)) {
+               dprintk("%s: cannot create RPC client. Error = %ld\n",
+                               __FUNCTION__, PTR_ERR(clnt));
+               return PTR_ERR(clnt);
+       }
+
+       clnt->cl_intr     = 1;
+       clnt->cl_softrtry = 1;
+       clnt->cl_tagxid   = 1;
+       clp->cl_rpcclient = clnt;
+       return 0;
+}
+
+/*
+ * Version 2 or 3 client destruction
+ */
+static void nfs_destroy_server(struct nfs_server *server)
+{
+       if (!IS_ERR(server->client_acl))
+               rpc_shutdown_client(server->client_acl);
+
+       if (!(server->flags & NFS_MOUNT_NONLM))
+               lockd_down();   /* release rpc.lockd */
+}
+
+/*
+ * Version 2 or 3 lockd setup
+ */
+static int nfs_start_lockd(struct nfs_server *server)
+{
+       int error = 0;
+
+       if (server->nfs_client->cl_nfsversion > 3)
+               goto out;
+       if (server->flags & NFS_MOUNT_NONLM)
+               goto out;
+       error = lockd_up();
+       if (error < 0)
+               server->flags |= NFS_MOUNT_NONLM;
+       else
+               server->destroy = nfs_destroy_server;
+out:
+       return error;
+}
+
+/*
+ * Initialise an NFSv3 ACL client connection
+ */
+#ifdef CONFIG_NFS_V3_ACL
+static void nfs_init_server_aclclient(struct nfs_server *server)
+{
+       if (server->nfs_client->cl_nfsversion != 3)
+               goto out_noacl;
+       if (server->flags & NFS_MOUNT_NOACL)
+               goto out_noacl;
+
+       server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+       if (IS_ERR(server->client_acl))
+               goto out_noacl;
+
+       /* No errors! Assume that Sun nfsacls are supported */
+       server->caps |= NFS_CAP_ACLS;
+       return;
+
+out_noacl:
+       server->caps &= ~NFS_CAP_ACLS;
+}
+#else
+static inline void nfs_init_server_aclclient(struct nfs_server *server)
+{
+       server->flags &= ~NFS_MOUNT_NOACL;
+       server->caps &= ~NFS_CAP_ACLS;
+}
+#endif
+
+/*
+ * Create a general RPC client
+ */
+static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour)
+{
+       struct nfs_client *clp = server->nfs_client;
+
+       server->client = rpc_clone_client(clp->cl_rpcclient);
+       if (IS_ERR(server->client)) {
+               dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__);
+               return PTR_ERR(server->client);
+       }
+
+       if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) {
+               struct rpc_auth *auth;
+
+               auth = rpcauth_create(pseudoflavour, server->client);
+               if (IS_ERR(auth)) {
+                       dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
+                       return PTR_ERR(auth);
+               }
+       }
+       server->client->cl_softrtry = 0;
+       if (server->flags & NFS_MOUNT_SOFT)
+               server->client->cl_softrtry = 1;
+
+       server->client->cl_intr = 0;
+       if (server->flags & NFS4_MOUNT_INTR)
+               server->client->cl_intr = 1;
+
+       server->client->cl_tagxid = (server->flags & NFS_MOUNT_TAGXID) ? 1 : 0;
+
+       return 0;
+}
+
+/*
+ * Initialise an NFS2 or NFS3 client
+ */
+static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data)
+{
+       int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
+       int error;
+
+       if (clp->cl_cons_state == NFS_CS_READY) {
+               /* the client is already initialised */
+               dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp);
+               return 0;
+       }
+
+       /* Check NFS protocol revision and initialize RPC op vector */
+       clp->rpc_ops = &nfs_v2_clientops;
+#ifdef CONFIG_NFS_V3
+       if (clp->cl_nfsversion == 3)
+               clp->rpc_ops = &nfs_v3_clientops;
+#endif
+       /*
+        * Create a client RPC handle for doing FSSTAT with UNIX auth only
+        * - RFC 2623, sec 2.3.2
+        */
+       error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans,
+                       RPC_AUTH_UNIX);
+       if (error < 0)
+               goto error;
+       nfs_mark_client_ready(clp, NFS_CS_READY);
+       return 0;
+
+error:
+       nfs_mark_client_ready(clp, error);
+       dprintk("<-- nfs_init_client() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Create a version 2 or 3 client
+ */
+static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data)
+{
+       struct nfs_client *clp;
+       int error, nfsvers = 2;
+
+       dprintk("--> nfs_init_server()\n");
+
+#ifdef CONFIG_NFS_V3
+       if (data->flags & NFS_MOUNT_VER3)
+               nfsvers = 3;
+#endif
+
+       /* Allocate or find a client reference we can use */
+       clp = nfs_get_client(data->hostname, &data->addr, nfsvers);
+       if (IS_ERR(clp)) {
+               dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
+               return PTR_ERR(clp);
+       }
+
+       error = nfs_init_client(clp, data);
+       if (error < 0)
+               goto error;
+
+       server->nfs_client = clp;
+
+       /* Initialise the client representation from the mount data */
+       server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+
+       if (data->rsize)
+               server->rsize = nfs_block_size(data->rsize, NULL);
+       if (data->wsize)
+               server->wsize = nfs_block_size(data->wsize, NULL);
+
+       server->acregmin = data->acregmin * HZ;
+       server->acregmax = data->acregmax * HZ;
+       server->acdirmin = data->acdirmin * HZ;
+       server->acdirmax = data->acdirmax * HZ;
+
+       /* Start lockd here, before we might error out */
+       error = nfs_start_lockd(server);
+       if (error < 0)
+               goto error;
+
+       error = nfs_init_server_rpcclient(server, data->pseudoflavor);
+       if (error < 0)
+               goto error;
+
+       server->namelen  = data->namlen;
+       /* Create a client RPC handle for the NFSv3 ACL management interface */
+       nfs_init_server_aclclient(server);
+       if (clp->cl_nfsversion == 3) {
+               if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
+                       server->namelen = NFS3_MAXNAMLEN;
+               server->caps |= NFS_CAP_READDIRPLUS;
+       } else {
+               if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
+                       server->namelen = NFS2_MAXNAMLEN;
+       }
+
+       dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
+       return 0;
+
+error:
+       server->nfs_client = NULL;
+       nfs_put_client(clp);
+       dprintk("<-- nfs_init_server() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Load up the server record from information gained in an fsinfo record
+ */
+static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo)
+{
+       unsigned long max_rpc_payload;
+
+       /* Work out a lot of parameters */
+       if (server->rsize == 0)
+               server->rsize = nfs_block_size(fsinfo->rtpref, NULL);
+       if (server->wsize == 0)
+               server->wsize = nfs_block_size(fsinfo->wtpref, NULL);
+
+       if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax)
+               server->rsize = nfs_block_size(fsinfo->rtmax, NULL);
+       if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax)
+               server->wsize = nfs_block_size(fsinfo->wtmax, NULL);
+
+       max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
+       if (server->rsize > max_rpc_payload)
+               server->rsize = max_rpc_payload;
+       if (server->rsize > NFS_MAX_FILE_IO_SIZE)
+               server->rsize = NFS_MAX_FILE_IO_SIZE;
+       server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
+
+       if (server->wsize > max_rpc_payload)
+               server->wsize = max_rpc_payload;
+       if (server->wsize > NFS_MAX_FILE_IO_SIZE)
+               server->wsize = NFS_MAX_FILE_IO_SIZE;
+       server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
+
+       server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
+       if (server->dtsize > PAGE_CACHE_SIZE)
+               server->dtsize = PAGE_CACHE_SIZE;
+       if (server->dtsize > server->rsize)
+               server->dtsize = server->rsize;
+
+       if (server->flags & NFS_MOUNT_NOAC) {
+               server->acregmin = server->acregmax = 0;
+               server->acdirmin = server->acdirmax = 0;
+       }
+
+       server->maxfilesize = fsinfo->maxfilesize;
+
+       /* We're airborne Set socket buffersize */
+       rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
+}
+
+/*
+ * Probe filesystem information, including the FSID on v2/v3
+ */
+static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
+{
+       struct nfs_fsinfo fsinfo;
+       struct nfs_client *clp = server->nfs_client;
+       int error;
+
+       dprintk("--> nfs_probe_fsinfo()\n");
+
+       if (clp->rpc_ops->set_capabilities != NULL) {
+               error = clp->rpc_ops->set_capabilities(server, mntfh);
+               if (error < 0)
+                       goto out_error;
+       }
+
+       fsinfo.fattr = fattr;
+       nfs_fattr_init(fattr);
+       error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
+       if (error < 0)
+               goto out_error;
+
+       nfs_server_set_fsinfo(server, &fsinfo);
+
+       /* Get some general file system info */
+       if (server->namelen == 0) {
+               struct nfs_pathconf pathinfo;
+
+               pathinfo.fattr = fattr;
+               nfs_fattr_init(fattr);
+
+               if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
+                       server->namelen = pathinfo.max_namelen;
+       }
+
+       dprintk("<-- nfs_probe_fsinfo() = 0\n");
+       return 0;
+
+out_error:
+       dprintk("nfs_probe_fsinfo: error = %d\n", -error);
+       return error;
+}
+
+/*
+ * Copy useful information when duplicating a server record
+ */
+static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
+{
+       target->flags = source->flags;
+       target->acregmin = source->acregmin;
+       target->acregmax = source->acregmax;
+       target->acdirmin = source->acdirmin;
+       target->acdirmax = source->acdirmax;
+       target->caps = source->caps;
+}
+
+/*
+ * Allocate and initialise a server record
+ */
+static struct nfs_server *nfs_alloc_server(void)
+{
+       struct nfs_server *server;
+
+       server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
+       if (!server)
+               return NULL;
+
+       server->client = server->client_acl = ERR_PTR(-EINVAL);
+
+       /* Zero out the NFS state stuff */
+       INIT_LIST_HEAD(&server->client_link);
+       INIT_LIST_HEAD(&server->master_link);
+
+       server->io_stats = nfs_alloc_iostats();
+       if (!server->io_stats) {
+               kfree(server);
+               return NULL;
+       }
+
+       return server;
+}
+
+/*
+ * Free up a server record
+ */
+void nfs_free_server(struct nfs_server *server)
+{
+       dprintk("--> nfs_free_server()\n");
+
+       spin_lock(&nfs_client_lock);
+       list_del(&server->client_link);
+       list_del(&server->master_link);
+       spin_unlock(&nfs_client_lock);
+
+       if (server->destroy != NULL)
+               server->destroy(server);
+       if (!IS_ERR(server->client))
+               rpc_shutdown_client(server->client);
+
+       nfs_put_client(server->nfs_client);
+
+       nfs_free_iostats(server->io_stats);
+       kfree(server);
+       nfs_release_automount_timer();
+       dprintk("<-- nfs_free_server()\n");
+}
+
+/*
+ * Create a version 2 or 3 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs_create_server(const struct nfs_mount_data *data,
+                                    struct nfs_fh *mntfh)
+{
+       struct nfs_server *server;
+       struct nfs_fattr fattr;
+       int error;
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       /* Get a client representation */
+       error = nfs_init_server(server, data);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       /* Probe the root fh to retrieve its FSID */
+       error = nfs_probe_fsinfo(server, mntfh, &fattr);
+       if (error < 0)
+               goto error;
+       if (!(fattr.valid & NFS_ATTR_FATTR)) {
+               error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+               if (error < 0) {
+                       dprintk("nfs_create_server: getattr error = %d\n", -error);
+                       goto error;
+               }
+       }
+       memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
+
+       dprintk("Server FSID: %llx:%llx\n", server->fsid.major, server->fsid.minor);
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+       return server;
+
+error:
+       nfs_free_server(server);
+       return ERR_PTR(error);
+}
+
+#ifdef CONFIG_NFS_V4
+/*
+ * Initialise an NFS4 client record
+ */
+static int nfs4_init_client(struct nfs_client *clp,
+               int proto, int timeo, int retrans,
+               rpc_authflavor_t authflavour)
+{
+       int error;
+
+       if (clp->cl_cons_state == NFS_CS_READY) {
+               /* the client is initialised already */
+               dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
+               return 0;
+       }
+
+       /* Check NFS protocol revision and initialize RPC op vector */
+       clp->rpc_ops = &nfs_v4_clientops;
+
+       error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour);
+       if (error < 0)
+               goto error;
+
+       error = nfs_idmap_new(clp);
+       if (error < 0) {
+               dprintk("%s: failed to create idmapper. Error = %d\n",
+                       __FUNCTION__, error);
+               goto error;
+       }
+       __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
+
+       nfs_mark_client_ready(clp, NFS_CS_READY);
+       return 0;
+
+error:
+       nfs_mark_client_ready(clp, error);
+       dprintk("<-- nfs4_init_client() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Set up an NFS4 client
+ */
+static int nfs4_set_client(struct nfs_server *server,
+               const char *hostname, const struct sockaddr_in *addr,
+               rpc_authflavor_t authflavour,
+               int proto, int timeo, int retrans)
+{
+       struct nfs_client *clp;
+       int error;
+
+       dprintk("--> nfs4_set_client()\n");
+
+       /* Allocate or find a client reference we can use */
+       clp = nfs_get_client(hostname, addr, 4);
+       if (IS_ERR(clp)) {
+               error = PTR_ERR(clp);
+               goto error;
+       }
+       error = nfs4_init_client(clp, proto, timeo, retrans, authflavour);
+       if (error < 0)
+               goto error_put;
+
+       server->nfs_client = clp;
+       dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
+       return 0;
+
+error_put:
+       nfs_put_client(clp);
+error:
+       dprintk("<-- nfs4_set_client() = xerror %d\n", error);
+       return error;
+}
+
+/*
+ * Create a version 4 volume record
+ */
+static int nfs4_init_server(struct nfs_server *server,
+               const struct nfs4_mount_data *data, rpc_authflavor_t authflavour)
+{
+       int error;
+
+       dprintk("--> nfs4_init_server()\n");
+
+       /* Initialise the client representation from the mount data */
+       server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+       server->caps |= NFS_CAP_ATOMIC_OPEN;
+
+       if (data->rsize)
+               server->rsize = nfs_block_size(data->rsize, NULL);
+       if (data->wsize)
+               server->wsize = nfs_block_size(data->wsize, NULL);
+
+       server->acregmin = data->acregmin * HZ;
+       server->acregmax = data->acregmax * HZ;
+       server->acdirmin = data->acdirmin * HZ;
+       server->acdirmax = data->acdirmax * HZ;
+
+       error = nfs_init_server_rpcclient(server, authflavour);
+
+       /* Done */
+       dprintk("<-- nfs4_init_server() = %d\n", error);
+       return error;
+}
+
+/*
+ * Create a version 4 volume record
+ * - keyed on server and FSID
+ */
+struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data,
+                                     const char *hostname,
+                                     const struct sockaddr_in *addr,
+                                     const char *mntpath,
+                                     const char *ip_addr,
+                                     rpc_authflavor_t authflavour,
+                                     struct nfs_fh *mntfh)
+{
+       struct nfs_fattr fattr;
+       struct nfs_server *server;
+       int error;
+
+       dprintk("--> nfs4_create_server()\n");
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       /* Get a client record */
+       error = nfs4_set_client(server, hostname, addr, authflavour,
+                       data->proto, data->timeo, data->retrans);
+       if (error < 0)
+               goto error;
+
+       /* set up the general RPC client */
+       error = nfs4_init_server(server, data, authflavour);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       /* Probe the root fh to retrieve its FSID */
+       error = nfs4_path_walk(server, mntfh, mntpath);
+       if (error < 0)
+               goto error;
+
+       dprintk("Server FSID: %llx:%llx\n", server->fsid.major, server->fsid.minor);
+       dprintk("Mount FH: %d\n", mntfh->size);
+
+       error = nfs_probe_fsinfo(server, mntfh, &fattr);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+       dprintk("<-- nfs4_create_server() = %p\n", server);
+       return server;
+
+error:
+       nfs_free_server(server);
+       dprintk("<-- nfs4_create_server() = error %d\n", error);
+       return ERR_PTR(error);
+}
+
+/*
+ * Create an NFS4 referral server record
+ */
+struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
+                                              struct nfs_fh *fh)
+{
+       struct nfs_client *parent_client;
+       struct nfs_server *server, *parent_server;
+       struct nfs_fattr fattr;
+       int error;
+
+       dprintk("--> nfs4_create_referral_server()\n");
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       parent_server = NFS_SB(data->sb);
+       parent_client = parent_server->nfs_client;
+
+       /* Get a client representation.
+        * Note: NFSv4 always uses TCP, */
+       error = nfs4_set_client(server, data->hostname, data->addr,
+                       data->authflavor,
+                       parent_server->client->cl_xprt->prot,
+                       parent_client->retrans_timeo,
+                       parent_client->retrans_count);
+
+       /* Initialise the client representation from the parent server */
+       nfs_server_copy_userdata(server, parent_server);
+       server->caps |= NFS_CAP_ATOMIC_OPEN;
+
+       error = nfs_init_server_rpcclient(server, data->authflavor);
+       if (error < 0)
+               goto error;
+
+       BUG_ON(!server->nfs_client);
+       BUG_ON(!server->nfs_client->rpc_ops);
+       BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+
+       /* probe the filesystem info for this server filesystem */
+       error = nfs_probe_fsinfo(server, fh, &fattr);
+       if (error < 0)
+               goto error;
+
+       dprintk("Referral FSID: %llx:%llx\n",
+               server->fsid.major, server->fsid.minor);
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+
+       dprintk("<-- nfs_create_referral_server() = %p\n", server);
+       return server;
+
+error:
+       nfs_free_server(server);
+       dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
+       return ERR_PTR(error);
+}
+
+#endif /* CONFIG_NFS_V4 */
+
+/*
+ * Clone an NFS2, NFS3 or NFS4 server record
+ */
+struct nfs_server *nfs_clone_server(struct nfs_server *source,
+                                   struct nfs_fh *fh,
+                                   struct nfs_fattr *fattr)
+{
+       struct nfs_server *server;
+       struct nfs_fattr fattr_fsinfo;
+       int error;
+
+       dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
+               fattr->fsid.major, fattr->fsid.minor);
+
+       server = nfs_alloc_server();
+       if (!server)
+               return ERR_PTR(-ENOMEM);
+
+       /* Copy data from the source */
+       server->nfs_client = source->nfs_client;
+       atomic_inc(&server->nfs_client->cl_count);
+       nfs_server_copy_userdata(server, source);
+
+       server->fsid = fattr->fsid;
+
+       error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor);
+       if (error < 0)
+               goto out_free_server;
+       if (!IS_ERR(source->client_acl))
+               nfs_init_server_aclclient(server);
+
+       /* probe the filesystem info for this server filesystem */
+       error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
+       if (error < 0)
+               goto out_free_server;
+
+       dprintk("Cloned FSID: %llx:%llx\n",
+               server->fsid.major, server->fsid.minor);
+
+       error = nfs_start_lockd(server);
+       if (error < 0)
+               goto out_free_server;
+
+       spin_lock(&nfs_client_lock);
+       list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
+       list_add_tail(&server->master_link, &nfs_volume_list);
+       spin_unlock(&nfs_client_lock);
+
+       server->mount_time = jiffies;
+
+       dprintk("<-- nfs_clone_server() = %p\n", server);
+       return server;
+
+out_free_server:
+       nfs_free_server(server);
+       dprintk("<-- nfs_clone_server() = error %d\n", error);
+       return ERR_PTR(error);
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_fs_nfs;
+
+static int nfs_server_list_open(struct inode *inode, struct file *file);
+static void *nfs_server_list_start(struct seq_file *p, loff_t *pos);
+static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos);
+static void nfs_server_list_stop(struct seq_file *p, void *v);
+static int nfs_server_list_show(struct seq_file *m, void *v);
+
+static struct seq_operations nfs_server_list_ops = {
+       .start  = nfs_server_list_start,
+       .next   = nfs_server_list_next,
+       .stop   = nfs_server_list_stop,
+       .show   = nfs_server_list_show,
+};
+
+static struct file_operations nfs_server_list_fops = {
+       .open           = nfs_server_list_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int nfs_volume_list_open(struct inode *inode, struct file *file);
+static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos);
+static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos);
+static void nfs_volume_list_stop(struct seq_file *p, void *v);
+static int nfs_volume_list_show(struct seq_file *m, void *v);
+
+static struct seq_operations nfs_volume_list_ops = {
+       .start  = nfs_volume_list_start,
+       .next   = nfs_volume_list_next,
+       .stop   = nfs_volume_list_stop,
+       .show   = nfs_volume_list_show,
+};
+
+static struct file_operations nfs_volume_list_fops = {
+       .open           = nfs_volume_list_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+/*
+ * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which
+ * we're dealing
+ */
+static int nfs_server_list_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *m;
+       int ret;
+
+       ret = seq_open(file, &nfs_server_list_ops);
+       if (ret < 0)
+               return ret;
+
+       m = file->private_data;
+       m->private = PDE(inode)->data;
+
+       return 0;
+}
+
+/*
+ * set up the iterator to start reading from the server list and return the first item
+ */
+static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
+{
+       struct list_head *_p;
+       loff_t pos = *_pos;
+
+       /* lock the list against modification */
+       spin_lock(&nfs_client_lock);
+
+       /* allow for the header line */
+       if (!pos)
+               return SEQ_START_TOKEN;
+       pos--;
+
+       /* find the n'th element in the list */
+       list_for_each(_p, &nfs_client_list)
+               if (!pos--)
+                       break;
+
+       return _p != &nfs_client_list ? _p : NULL;
+}
+
+/*
+ * move to next server
+ */
+static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
+{
+       struct list_head *_p;
+
+       (*pos)++;
+
+       _p = v;
+       _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next;
+
+       return _p != &nfs_client_list ? _p : NULL;
+}
+
+/*
+ * clean up after reading from the transports list
+ */
+static void nfs_server_list_stop(struct seq_file *p, void *v)
+{
+       spin_unlock(&nfs_client_lock);
+}
+
+/*
+ * display a header line followed by a load of call lines
+ */
+static int nfs_server_list_show(struct seq_file *m, void *v)
+{
+       struct nfs_client *clp;
+
+       /* display header on line 1 */
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(m, "NV SERVER   PORT USE HOSTNAME\n");
+               return 0;
+       }
+
+       /* display one transport per line on subsequent lines */
+       clp = list_entry(v, struct nfs_client, cl_share_link);
+
+       seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n",
+                  clp->cl_nfsversion,
+                  NIPQUAD(clp->cl_addr.sin_addr),
+                  ntohs(clp->cl_addr.sin_port),
+                  atomic_read(&clp->cl_count),
+                  clp->cl_hostname);
+
+       return 0;
+}
+
+/*
+ * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes
+ */
+static int nfs_volume_list_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *m;
+       int ret;
+
+       ret = seq_open(file, &nfs_volume_list_ops);
+       if (ret < 0)
+               return ret;
+
+       m = file->private_data;
+       m->private = PDE(inode)->data;
+
+       return 0;
+}
+
+/*
+ * set up the iterator to start reading from the volume list and return the first item
+ */
+static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
+{
+       struct list_head *_p;
+       loff_t pos = *_pos;
+
+       /* lock the list against modification */
+       spin_lock(&nfs_client_lock);
+
+       /* allow for the header line */
+       if (!pos)
+               return SEQ_START_TOKEN;
+       pos--;
+
+       /* find the n'th element in the list */
+       list_for_each(_p, &nfs_volume_list)
+               if (!pos--)
+                       break;
+
+       return _p != &nfs_volume_list ? _p : NULL;
+}
+
+/*
+ * move to next volume
+ */
+static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
+{
+       struct list_head *_p;
+
+       (*pos)++;
+
+       _p = v;
+       _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next;
+
+       return _p != &nfs_volume_list ? _p : NULL;
+}
+
+/*
+ * clean up after reading from the transports list
+ */
+static void nfs_volume_list_stop(struct seq_file *p, void *v)
+{
+       spin_unlock(&nfs_client_lock);
+}
+
+/*
+ * display a header line followed by a load of call lines
+ */
+static int nfs_volume_list_show(struct seq_file *m, void *v)
+{
+       struct nfs_server *server;
+       struct nfs_client *clp;
+       char dev[8], fsid[17];
+
+       /* display header on line 1 */
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(m, "NV SERVER   PORT DEV     FSID              FSC\n");
+               return 0;
+       }
+       /* display one transport per line on subsequent lines */
+       server = list_entry(v, struct nfs_server, master_link);
+       clp = server->nfs_client;
+
+       snprintf(dev, 8, "%u:%u",
+                MAJOR(server->s_dev), MINOR(server->s_dev));
+
+       snprintf(fsid, 17, "%llx:%llx",
+                server->fsid.major, server->fsid.minor);
+
+       seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s %s\n",
+                  clp->cl_nfsversion,
+                  NIPQUAD(clp->cl_addr.sin_addr),
+                  ntohs(clp->cl_addr.sin_port),
+                  dev,
+                  fsid,
+                  nfs_server_fscache_state(server));
+
+       return 0;
+}
+
+/*
+ * initialise the /proc/fs/nfsfs/ directory
+ */
+int __init nfs_fs_proc_init(void)
+{
+       struct proc_dir_entry *p;
+
+       proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs);
+       if (!proc_fs_nfs)
+               goto error_0;
+
+       proc_fs_nfs->owner = THIS_MODULE;
+
+       /* a file of servers with which we're dealing */
+       p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs);
+       if (!p)
+               goto error_1;
+
+       p->proc_fops = &nfs_server_list_fops;
+       p->owner = THIS_MODULE;
+
+       /* a file of volumes that we have mounted */
+       p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs);
+       if (!p)
+               goto error_2;
+
+       p->proc_fops = &nfs_volume_list_fops;
+       p->owner = THIS_MODULE;
+       return 0;
+
+error_2:
+       remove_proc_entry("servers", proc_fs_nfs);
+error_1:
+       remove_proc_entry("nfsfs", proc_root_fs);
+error_0:
+       return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/nfsfs/ directory
+ */
+void nfs_fs_proc_exit(void)
+{
+       remove_proc_entry("volumes", proc_fs_nfs);
+       remove_proc_entry("servers", proc_fs_nfs);
+       remove_proc_entry("nfsfs", proc_root_fs);
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
new file mode 100644 (file)
index 0000000..0949bac
--- /dev/null
@@ -0,0 +1,345 @@
+/* fscache.c: NFS filesystem cache interface
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/in6.h>
+
+#include "internal.h"
+
+/*
+ * Sysctl variables
+ */
+atomic_t nfs_fscache_to_pages;
+atomic_t nfs_fscache_from_pages;
+atomic_t nfs_fscache_uncache_page;
+int nfs_fscache_from_error;
+int nfs_fscache_to_error;
+
+#define NFSDBG_FACILITY                NFSDBG_FSCACHE
+
+/* the auxiliary data in the cache (used for coherency management) */
+struct nfs_fh_auxdata {
+       struct timespec i_mtime;
+       struct timespec i_ctime;
+       loff_t          i_size;
+};
+
+static struct fscache_netfs_operations nfs_cache_ops = {
+};
+
+struct fscache_netfs nfs_cache_netfs = {
+       .name                   = "nfs",
+       .version                = 0,
+       .ops                    = &nfs_cache_ops,
+};
+
+static const uint8_t nfs_cache_ipv6_wrapper_for_ipv4[12] = {
+       [0 ... 9]       = 0x00,
+       [10 ... 11]     = 0xff
+};
+
+struct nfs_server_key {
+       uint16_t nfsversion;
+       uint16_t port;
+       union {
+               struct {
+                       uint8_t         ipv6wrapper[12];
+                       struct in_addr  addr;
+               } ipv4_addr;
+               struct in6_addr ipv6_addr;
+       };
+};
+
+static uint16_t nfs_server_get_key(const void *cookie_netfs_data,
+                                  void *buffer, uint16_t bufmax)
+{
+       const struct nfs_client *clp = cookie_netfs_data;
+       struct nfs_server_key *key = buffer;
+       uint16_t len = 0;
+
+       key->nfsversion = clp->cl_nfsversion;
+
+       switch (clp->cl_addr.sin_family) {
+       case AF_INET:
+               key->port = clp->cl_addr.sin_port;
+
+               memcpy(&key->ipv4_addr.ipv6wrapper,
+                      &nfs_cache_ipv6_wrapper_for_ipv4,
+                      sizeof(key->ipv4_addr.ipv6wrapper));
+               memcpy(&key->ipv4_addr.addr,
+                      &clp->cl_addr.sin_addr,
+                      sizeof(key->ipv4_addr.addr));
+               len = sizeof(struct nfs_server_key);
+               break;
+
+       case AF_INET6:
+               key->port = clp->cl_addr.sin_port;
+
+               memcpy(&key->ipv6_addr,
+                      &clp->cl_addr.sin_addr,
+                      sizeof(key->ipv6_addr));
+               len = sizeof(struct nfs_server_key);
+               break;
+
+       default:
+               len = 0;
+               printk(KERN_WARNING "NFS: Unknown network family '%d'\n",
+                       clp->cl_addr.sin_family);
+               break;
+       }
+
+       return len;
+}
+
+/*
+ * the root index for the filesystem is defined by nfsd IP address and ports
+ */
+struct fscache_cookie_def nfs_cache_server_index_def = {
+       .name           = "NFS.servers",
+       .type           = FSCACHE_COOKIE_TYPE_INDEX,
+       .get_key        = nfs_server_get_key,
+};
+
+static uint16_t nfs_fh_get_key(const void *cookie_netfs_data,
+               void *buffer, uint16_t bufmax)
+{
+       const struct nfs_inode *nfsi = cookie_netfs_data;
+       uint16_t nsize;
+
+       /* set the file handle */
+       nsize = nfsi->fh.size;
+       memcpy(buffer, nfsi->fh.data, nsize);
+       return nsize;
+}
+
+/*
+ * indication of pages that now have cache metadata retained
+ * - this function should mark the specified pages as now being cached
+ */
+static void nfs_fh_mark_pages_cached(void *cookie_netfs_data,
+                                    struct address_space *mapping,
+                                    struct pagevec *cached_pvec)
+{
+       struct nfs_inode *nfsi = cookie_netfs_data;
+       unsigned long loop;
+
+       dprintk("NFS: nfs_fh_mark_pages_cached: nfs_inode 0x%p pages %ld\n",
+               nfsi, cached_pvec->nr);
+
+       for (loop = 0; loop < cached_pvec->nr; loop++)
+               SetPageNfsCached(cached_pvec->pages[loop]);
+}
+
+/*
+ * get an extra reference on a read context
+ * - this function can be absent if the completion function doesn't
+ *   require a context
+ */
+static void nfs_fh_get_context(void *cookie_netfs_data, void *context)
+{
+       get_nfs_open_context(context);
+}
+
+/*
+ * release an extra reference on a read context
+ * - this function can be absent if the completion function doesn't
+ *   require a context
+ */
+static void nfs_fh_put_context(void *cookie_netfs_data, void *context)
+{
+       if (context)
+               put_nfs_open_context(context);
+}
+
+/*
+ * indication the cookie is no longer uncached
+ * - this function is called when the backing store currently caching a cookie
+ *   is removed
+ * - the netfs should use this to clean up any markers indicating cached pages
+ * - this is mandatory for any object that may have data
+ */
+static void nfs_fh_now_uncached(void *cookie_netfs_data)
+{
+       struct nfs_inode *nfsi = cookie_netfs_data;
+       struct pagevec pvec;
+       pgoff_t first;
+       int loop, nr_pages;
+
+       pagevec_init(&pvec, 0);
+       first = 0;
+
+       dprintk("NFS: nfs_fh_now_uncached: nfs_inode 0x%p\n", nfsi);
+
+       for (;;) {
+               /* grab a bunch of pages to clean */
+               nr_pages = pagevec_lookup(&pvec,
+                                         nfsi->vfs_inode.i_mapping,
+                                         first,
+                                         PAGEVEC_SIZE - pagevec_count(&pvec));
+               if (!nr_pages)
+                       break;
+
+               for (loop = 0; loop < nr_pages; loop++)
+                       ClearPageNfsCached(pvec.pages[loop]);
+
+               first = pvec.pages[nr_pages - 1]->index + 1;
+
+               pvec.nr = nr_pages;
+               pagevec_release(&pvec);
+               cond_resched();
+       }
+}
+
+/*
+ * get certain file attributes from the netfs data
+ * - this function can be absent for an index
+ * - not permitted to return an error
+ * - the netfs data from the cookie being used as the source is
+ *   presented
+ */
+static void nfs_fh_get_attr(const void *cookie_netfs_data, uint64_t *size)
+{
+       const struct nfs_inode *nfsi = cookie_netfs_data;
+
+       *size = nfsi->vfs_inode.i_size;
+}
+
+/*
+ * get the auxilliary data from netfs data
+ * - this function can be absent if the index carries no state data
+ * - should store the auxilliary data in the buffer
+ * - should return the amount of amount stored
+ * - not permitted to return an error
+ * - the netfs data from the cookie being used as the source is
+ *   presented
+ */
+static uint16_t nfs_fh_get_aux(const void *cookie_netfs_data,
+                              void *buffer, uint16_t bufmax)
+{
+       struct nfs_fh_auxdata auxdata;
+       const struct nfs_inode *nfsi = cookie_netfs_data;
+
+       auxdata.i_size = nfsi->vfs_inode.i_size;
+       auxdata.i_mtime = nfsi->vfs_inode.i_mtime;
+       auxdata.i_ctime = nfsi->vfs_inode.i_ctime;
+
+       if (bufmax > sizeof(auxdata))
+               bufmax = sizeof(auxdata);
+
+       memcpy(buffer, &auxdata, bufmax);
+       return bufmax;
+}
+
+/*
+ * consult the netfs about the state of an object
+ * - this function can be absent if the index carries no state data
+ * - the netfs data from the cookie being used as the target is
+ *   presented, as is the auxilliary data
+ */
+static fscache_checkaux_t nfs_fh_check_aux(void *cookie_netfs_data,
+                                          const void *data, uint16_t datalen)
+{
+       struct nfs_fh_auxdata auxdata;
+       struct nfs_inode *nfsi = cookie_netfs_data;
+
+       if (datalen > sizeof(auxdata))
+               return FSCACHE_CHECKAUX_OBSOLETE;
+
+       auxdata.i_size = nfsi->vfs_inode.i_size;
+       auxdata.i_mtime = nfsi->vfs_inode.i_mtime;
+       auxdata.i_ctime = nfsi->vfs_inode.i_ctime;
+
+       if (memcmp(data, &auxdata, datalen) != 0)
+               return FSCACHE_CHECKAUX_OBSOLETE;
+
+       return FSCACHE_CHECKAUX_OKAY;
+}
+
+/*
+ * the primary index for each server is simply made up of a series of NFS file
+ * handles
+ */
+struct fscache_cookie_def nfs_cache_fh_index_def = {
+       .name                   = "NFS.fh",
+       .type                   = FSCACHE_COOKIE_TYPE_DATAFILE,
+       .get_key                = nfs_fh_get_key,
+       .get_attr               = nfs_fh_get_attr,
+       .get_aux                = nfs_fh_get_aux,
+       .check_aux              = nfs_fh_check_aux,
+       .get_context            = nfs_fh_get_context,
+       .put_context            = nfs_fh_put_context,
+       .mark_pages_cached      = nfs_fh_mark_pages_cached,
+       .now_uncached           = nfs_fh_now_uncached,
+};
+
+static int nfs_file_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+       wait_on_page_fs_misc(page);
+       return 0;
+}
+
+struct vm_operations_struct nfs_fs_vm_operations = {
+       .nopage         = filemap_nopage,
+       .populate       = filemap_populate,
+       .page_mkwrite   = nfs_file_page_mkwrite,
+};
+
+/*
+ * handle completion of a page being stored in the cache
+ */
+void nfs_readpage_to_fscache_complete(struct page *page, void *data, int error)
+{
+       dfprintk(FSCACHE,
+               "NFS:     readpage_to_fscache_complete (p:%p(i:%lx f:%lx)/%d)\n",
+               page, page->index, page->flags, error);
+
+       end_page_fs_misc(page);
+}
+
+/*
+ * handle completion of a page being read from the cache
+ * - called in process (keventd) context
+ */
+void nfs_readpage_from_fscache_complete(struct page *page,
+                                       void *context,
+                                       int error)
+{
+       dfprintk(FSCACHE,
+                "NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n",
+                page, context, error);
+
+       /* if the read completes with an error, we just unlock the page and let
+        * the VM reissue the readpage */
+       if (!error) {
+               SetPageUptodate(page);
+               unlock_page(page);
+       } else {
+               error = nfs_readpage_async(context, page->mapping->host, page);
+               if (error)
+                       unlock_page(page);
+       }
+}
+
+/*
+ * handle completion of a page being read from the cache
+ * - really need to synchronise the end of writeback, probably using a page
+ *   flag, but for the moment we disable caching on writable files
+ */
+void nfs_writepage_to_fscache_complete(struct page *page,
+                                      void *data,
+                                      int error)
+{
+}
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
new file mode 100644 (file)
index 0000000..69f0f40
--- /dev/null
@@ -0,0 +1,466 @@
+/* fscache.h: NFS filesystem cache interface definitions
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _NFS_FSCACHE_H
+#define _NFS_FSCACHE_H
+
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include <linux/nfs4_mount.h>
+
+#ifdef CONFIG_NFS_FSCACHE
+#include <linux/fscache.h>
+
+extern struct fscache_netfs nfs_cache_netfs;
+extern struct fscache_cookie_def nfs_cache_server_index_def;
+extern struct fscache_cookie_def nfs_cache_fh_index_def;
+extern struct vm_operations_struct nfs_fs_vm_operations;
+
+extern void nfs_invalidatepage(struct page *, unsigned long);
+extern int nfs_releasepage(struct page *, gfp_t);
+
+extern atomic_t nfs_fscache_to_pages;
+extern atomic_t nfs_fscache_from_pages;
+extern atomic_t nfs_fscache_uncache_page;
+extern int nfs_fscache_from_error;
+extern int nfs_fscache_to_error;
+
+/*
+ * register NFS for caching
+ */
+static inline int nfs_fscache_register(void)
+{
+       return fscache_register_netfs(&nfs_cache_netfs);
+}
+
+/*
+ * unregister NFS for caching
+ */
+static inline void nfs_fscache_unregister(void)
+{
+       fscache_unregister_netfs(&nfs_cache_netfs);
+}
+
+/*
+ * get the per-client index cookie for an NFS client if the appropriate mount
+ * flag was set
+ * - we always try and get an index cookie for the client, but get filehandle
+ *   cookies on a per-superblock basis, depending on the mount flags
+ */
+static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp)
+{
+       /* create a cache index for looking up filehandles */
+       clp->fscache = fscache_acquire_cookie(nfs_cache_netfs.primary_index,
+                                             &nfs_cache_server_index_def,
+                                             clp);
+       dfprintk(FSCACHE,"NFS: get client cookie (0x%p/0x%p)\n",
+                clp, clp->fscache);
+}
+
+/*
+ * dispose of a per-client cookie
+ */
+static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp)
+{
+       dfprintk(FSCACHE,"NFS: releasing client cookie (0x%p/0x%p)\n",
+               clp, clp->fscache);
+
+       fscache_relinquish_cookie(clp->fscache, 0);
+       clp->fscache = NULL;
+}
+
+/*
+ * indicate the client caching state as readable text
+ */
+static inline const char *nfs_server_fscache_state(struct nfs_server *server)
+{
+       if (server->nfs_client->fscache && (server->flags & NFS_MOUNT_FSCACHE))
+               return "yes";
+       return "no ";
+}
+
+/*
+ * get the per-filehandle cookie for an NFS inode
+ */
+static inline void nfs_fscache_get_fh_cookie(struct super_block *sb,
+                                            struct nfs_inode *nfsi,
+                                            int maycache)
+{
+       nfsi->fscache = NULL;
+       if (maycache && (NFS_SB(sb)->flags & NFS_MOUNT_FSCACHE)) {
+               nfsi->fscache = fscache_acquire_cookie(
+                       NFS_SB(sb)->nfs_client->fscache,
+                       &nfs_cache_fh_index_def,
+                       nfsi);
+
+               fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size);
+
+               dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n",
+                        sb, nfsi, nfsi->fscache);
+       }
+}
+
+/*
+ * change the filesize associated with a per-filehandle cookie
+ */
+static inline void nfs_fscache_set_size(struct nfs_server *server,
+                                       struct nfs_inode *nfsi,
+                                       loff_t i_size)
+{
+       fscache_set_i_size(nfsi->fscache, i_size);
+}
+
+/*
+ * replace a per-filehandle cookie due to revalidation detecting a file having
+ * changed on the server
+ */
+static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server,
+                                              struct nfs_inode *nfsi)
+{
+       struct fscache_cookie *old = nfsi->fscache;
+
+       if (nfsi->fscache) {
+               /* retire the current fscache cache and get a new one */
+               fscache_relinquish_cookie(nfsi->fscache, 1);
+
+               nfsi->fscache = fscache_acquire_cookie(
+                       server->nfs_client->fscache,
+                       &nfs_cache_fh_index_def,
+                       nfsi);
+               fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size);
+
+               dfprintk(FSCACHE,
+                        "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n",
+                        server, nfsi, old, nfsi->fscache);
+       }
+}
+
+/*
+ * release a per-filehandle cookie
+ */
+static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server,
+                                                struct nfs_inode *nfsi)
+{
+       dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n",
+                nfsi, nfsi->fscache);
+
+       fscache_relinquish_cookie(nfsi->fscache, 0);
+       nfsi->fscache = NULL;
+}
+
+/*
+ * retire a per-filehandle cookie, destroying the data attached to it
+ */
+static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server,
+                                            struct nfs_inode *nfsi)
+{
+       dfprintk(FSCACHE,"NFS: zapping cookie (0x%p/0x%p)\n",
+               nfsi, nfsi->fscache);
+
+       fscache_relinquish_cookie(nfsi->fscache, 1);
+       nfsi->fscache = NULL;
+}
+
+/*
+ * turn off the cache with regard to a filehandle cookie if opened for writing,
+ * invalidating all the pages in the page cache relating to the associated
+ * inode to clear the per-page caching
+ */
+static inline void nfs_fscache_disable_fh_cookie(struct inode *inode)
+{
+       if (NFS_I(inode)->fscache) {
+               dfprintk(FSCACHE,
+                        "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode));
+
+               /* Need to invalided any mapped pages that were read in before
+                * turning off the cache.
+                */
+               if (inode->i_mapping && inode->i_mapping->nrpages)
+                       invalidate_inode_pages2(inode->i_mapping);
+
+               nfs_fscache_zap_fh_cookie(NFS_SERVER(inode), NFS_I(inode));
+       }
+}
+
+/*
+ * install the VM ops for mmap() of an NFS file so that we can hold up writes
+ * to pages on shared writable mappings until the store to the cache is
+ * complete
+ */
+static inline void nfs_fscache_install_vm_ops(struct inode *inode,
+                                             struct vm_area_struct *vma)
+{
+       if (NFS_I(inode)->fscache)
+               vma->vm_ops = &nfs_fs_vm_operations;
+}
+
+/*
+ * release the caching state associated with a page
+ */
+static void nfs_fscache_release_page(struct page *page)
+{
+       if (PageNfsCached(page)) {
+               struct nfs_inode *nfsi = NFS_I(page->mapping->host);
+
+               BUG_ON(nfsi->fscache == NULL);
+
+               dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
+                        nfsi->fscache, page, nfsi);
+
+               wait_on_page_fs_misc(page);
+               fscache_uncache_page(nfsi->fscache, page);
+               atomic_inc(&nfs_fscache_uncache_page);
+               ClearPageNfsCached(page);
+       }
+}
+
+/*
+ * release the caching state associated with a page if undergoing complete page
+ * invalidation
+ */
+static inline void nfs_fscache_invalidate_page(struct page *page,
+                                              struct inode *inode,
+                                              unsigned long offset)
+{
+       if (PageNfsCached(page)) {
+               struct nfs_inode *nfsi = NFS_I(page->mapping->host);
+
+               BUG_ON(!nfsi->fscache);
+
+               dfprintk(FSCACHE,
+                        "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
+                        nfsi->fscache, page, nfsi);
+
+               if (offset == 0) {
+                       BUG_ON(!PageLocked(page));
+                       if (!PageWriteback(page))
+                               nfs_fscache_release_page(page);
+               }
+       }
+}
+
+/*
+ * store a newly fetched page in fscache
+ */
+extern void nfs_readpage_to_fscache_complete(struct page *, void *, int);
+
+static inline void nfs_readpage_to_fscache(struct inode *inode,
+                                          struct page *page,
+                                          int sync)
+{
+       int ret;
+
+       if (PageNfsCached(page)) {
+               dfprintk(FSCACHE,
+                        "NFS: "
+                        "readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n",
+                        NFS_I(inode)->fscache, page, page->index, page->flags,
+                        sync);
+
+               if (TestSetPageFsMisc(page))
+                       BUG();
+
+               ret = fscache_write_page(NFS_I(inode)->fscache, page,
+                                        nfs_readpage_to_fscache_complete,
+                                        NULL, GFP_KERNEL);
+               dfprintk(FSCACHE,
+                        "NFS:     "
+                        "readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n",
+                        page, page->index, page->flags, ret);
+
+               if (ret != 0) {
+                       fscache_uncache_page(NFS_I(inode)->fscache, page);
+                       atomic_inc(&nfs_fscache_uncache_page);
+                       ClearPageNfsCached(page);
+                       end_page_fs_misc(page);
+                       nfs_fscache_to_error = ret;
+               } else {
+                       atomic_inc(&nfs_fscache_to_pages);
+               }
+       }
+}
+
+/*
+ * retrieve a page from fscache
+ */
+extern void nfs_readpage_from_fscache_complete(struct page *, void *, int);
+
+static inline
+int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
+                             struct inode *inode,
+                             struct page *page)
+{
+       int ret;
+
+       if (!NFS_I(inode)->fscache)
+               return 1;
+
+       dfprintk(FSCACHE,
+                "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
+                NFS_I(inode)->fscache, page, page->index, page->flags, inode);
+
+       ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
+                                        page,
+                                        nfs_readpage_from_fscache_complete,
+                                        ctx,
+                                        GFP_KERNEL);
+
+       switch (ret) {
+       case 0: /* read BIO submitted (page in fscache) */
+               dfprintk(FSCACHE,
+                        "NFS:    readpage_from_fscache: BIO submitted\n");
+               atomic_inc(&nfs_fscache_from_pages);
+               return ret;
+
+       case -ENOBUFS: /* inode not in cache */
+       case -ENODATA: /* page not in cache */
+               dfprintk(FSCACHE,
+                        "NFS:    readpage_from_fscache error %d\n", ret);
+               return 1;
+
+       default:
+               dfprintk(FSCACHE, "NFS:    readpage_from_fscache %d\n", ret);
+               nfs_fscache_from_error = ret;
+       }
+       return ret;
+}
+
+/*
+ * retrieve a set of pages from fscache
+ */
+static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
+                                            struct inode *inode,
+                                            struct address_space *mapping,
+                                            struct list_head *pages,
+                                            unsigned *nr_pages)
+{
+       int ret, npages = *nr_pages;
+
+       if (!NFS_I(inode)->fscache)
+               return 1;
+
+       dfprintk(FSCACHE,
+                "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
+                NFS_I(inode)->fscache, *nr_pages, inode);
+
+       ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
+                                         mapping, pages, nr_pages,
+                                         nfs_readpage_from_fscache_complete,
+                                         ctx,
+                                         mapping_gfp_mask(mapping));
+
+
+       switch (ret) {
+       case 0: /* read BIO submitted (page in fscache) */
+               BUG_ON(!list_empty(pages));
+               BUG_ON(*nr_pages != 0);
+               dfprintk(FSCACHE,
+                        "NFS: nfs_getpages_from_fscache: BIO submitted\n");
+
+               atomic_add(npages, &nfs_fscache_from_pages);
+               return ret;
+
+       case -ENOBUFS: /* inode not in cache */
+       case -ENODATA: /* page not in cache */
+               dfprintk(FSCACHE,
+                        "NFS: nfs_getpages_from_fscache: no page: %d\n", ret);
+               return 1;
+
+       default:
+               dfprintk(FSCACHE,
+                        "NFS: nfs_getpages_from_fscache: ret  %d\n", ret);
+               nfs_fscache_from_error = ret;
+       }
+
+       return ret;
+}
+
+/*
+ * store an updated page in fscache
+ */
+extern void nfs_writepage_to_fscache_complete(struct page *page, void *data, int error);
+
+static inline void nfs_writepage_to_fscache(struct inode *inode,
+                                           struct page *page)
+{
+       int error;
+
+       if (PageNfsCached(page) && NFS_I(inode)->fscache) {
+               dfprintk(FSCACHE,
+                        "NFS: writepage_to_fscache (0x%p/0x%p/0x%p)\n",
+                        NFS_I(inode)->fscache, page, inode);
+
+               error = fscache_write_page(NFS_I(inode)->fscache, page,
+                                          nfs_writepage_to_fscache_complete,
+                                          NULL, GFP_KERNEL);
+               if (error != 0) {
+                       dfprintk(FSCACHE,
+                                "NFS:    fscache_write_page error %d\n",
+                                error);
+                       fscache_uncache_page(NFS_I(inode)->fscache, page);
+               }
+       }
+}
+
+#else /* CONFIG_NFS_FSCACHE */
+static inline int nfs_fscache_register(void) { return 0; }
+static inline void nfs_fscache_unregister(void) {}
+static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {}
+static inline void nfs4_fscache_get_client_cookie(struct nfs_client *clp) {}
+static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {}
+static inline const char *nfs_server_fscache_state(struct nfs_server *server) { return "no "; }
+
+static inline void nfs_fscache_get_fh_cookie(struct super_block *sb,
+                                            struct nfs_inode *nfsi,
+                                            int maycache)
+{
+}
+static inline void nfs_fscache_set_size(struct nfs_server *server,
+                                       struct nfs_inode *nfsi,
+                                       loff_t i_size)
+{
+}
+static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server,
+                                                struct nfs_inode *nfsi)
+{
+}
+static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server, struct nfs_inode *nfsi) {}
+static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server, struct nfs_inode *nfsi) {}
+static inline void nfs_fscache_disable_fh_cookie(struct inode *inode) {}
+static inline void nfs_fscache_install_vm_ops(struct inode *inode, struct vm_area_struct *vma) {}
+static inline void nfs_fscache_release_page(struct page *page) {}
+static inline void nfs_fscache_invalidate_page(struct page *page,
+                                              struct inode *inode,
+                                              unsigned long offset)
+{
+}
+static inline void nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) {}
+static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
+                                           struct inode *inode, struct page *page)
+{
+       return -ENOBUFS;
+}
+static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
+                                            struct inode *inode,
+                                            struct address_space *mapping,
+                                            struct list_head *pages,
+                                            unsigned *nr_pages)
+{
+       return -ENOBUFS;
+}
+
+static inline void nfs_writepage_to_fscache(struct inode *inode, struct page *page)
+{
+       BUG_ON(PageNfsCached(page));
+}
+
+#endif /* CONFIG_NFS_FSCACHE */
+#endif /* _NFS_FSCACHE_H */
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
new file mode 100644 (file)
index 0000000..20c6f39
--- /dev/null
@@ -0,0 +1,310 @@
+/* getroot.c: get the root dentry for an NFS mount
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/stats.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include <linux/nfs4_mount.h>
+#include <linux/lockd/bind.h>
+#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/nfs_idmap.h>
+#include <linux/vfs.h>
+#include <linux/namei.h>
+#include <linux/namespace.h>
+#include <linux/security.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "nfs4_fs.h"
+#include "delegation.h"
+#include "internal.h"
+
+#define NFSDBG_FACILITY                NFSDBG_CLIENT
+#define NFS_PARANOIA 1
+
+/*
+ * get an NFS2/NFS3 root dentry from the root filehandle
+ */
+struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+{
+       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_fsinfo fsinfo;
+       struct nfs_fattr fattr;
+       struct dentry *mntroot;
+       struct inode *inode;
+       int error;
+
+       /* create a dummy root dentry with dummy inode for this superblock */
+       if (!sb->s_root) {
+               struct nfs_fh dummyfh;
+               struct dentry *root;
+               struct inode *iroot;
+
+               memset(&dummyfh, 0, sizeof(dummyfh));
+               memset(&fattr, 0, sizeof(fattr));
+               nfs_fattr_init(&fattr);
+               fattr.valid = NFS_ATTR_FATTR;
+               fattr.type = NFDIR;
+               fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
+               fattr.nlink = 2;
+
+               iroot = nfs_fhget(sb, &dummyfh, &fattr);
+               if (IS_ERR(iroot))
+                       return ERR_PTR(PTR_ERR(iroot));
+
+               root = d_alloc_root(iroot);
+               if (!root) {
+                       iput(iroot);
+                       return ERR_PTR(-ENOMEM);
+               }
+
+               sb->s_root = root;
+       }
+
+       /* get the actual root for this mount */
+       fsinfo.fattr = &fattr;
+
+       error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+       if (error < 0) {
+               dprintk("nfs_get_root: getattr error = %d\n", -error);
+               return ERR_PTR(error);
+       }
+
+       inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
+       if (IS_ERR(inode)) {
+               dprintk("nfs_get_root: get root inode failed\n");
+               return ERR_PTR(PTR_ERR(inode));
+       }
+
+       /* root dentries normally start off anonymous and get spliced in later
+        * if the dentry tree reaches them; however if the dentry already
+        * exists, we'll pick it up at this point and use it as the root
+        */
+       mntroot = d_alloc_anon(inode);
+       if (!mntroot) {
+               iput(inode);
+               dprintk("nfs_get_root: get root dentry failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       security_d_instantiate(mntroot, inode);
+
+       if (!mntroot->d_op)
+               mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops;
+
+       return mntroot;
+}
+
+#ifdef CONFIG_NFS_V4
+
+/*
+ * Do a simple pathwalk from the root FH of the server to the nominated target
+ * of the mountpoint
+ * - give error on symlinks
+ * - give error on ".." occurring in the path
+ * - follow traversals
+ */
+int nfs4_path_walk(struct nfs_server *server,
+                  struct nfs_fh *mntfh,
+                  const char *path)
+{
+       struct nfs_fsinfo fsinfo;
+       struct nfs_fattr fattr;
+       struct nfs_fh lastfh;
+       struct qstr name;
+       int ret;
+       //int referral_count = 0;
+
+       dprintk("--> nfs4_path_walk(,,%s)\n", path);
+
+       fsinfo.fattr = &fattr;
+       nfs_fattr_init(&fattr);
+
+       if (*path++ != '/') {
+               dprintk("nfs4_get_root: Path does not begin with a slash\n");
+               return -EINVAL;
+       }
+
+       /* Start by getting the root filehandle from the server */
+       ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
+       if (ret < 0) {
+               dprintk("nfs4_get_root: getroot error = %d\n", -ret);
+               return ret;
+       }
+
+       if (fattr.type != NFDIR) {
+               printk(KERN_ERR "nfs4_get_root:"
+                      " getroot encountered non-directory\n");
+               return -ENOTDIR;
+       }
+
+       if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
+               printk(KERN_ERR "nfs4_get_root:"
+                      " getroot obtained referral\n");
+               return -EREMOTE;
+       }
+
+next_component:
+       dprintk("Next: %s\n", path);
+
+       /* extract the next bit of the path */
+       if (!*path)
+               goto path_walk_complete;
+
+       name.name = path;
+       while (*path && *path != '/')
+               path++;
+       name.len = path - (const char *) name.name;
+
+eat_dot_dir:
+       while (*path == '/')
+               path++;
+
+       if (path[0] == '.' && (path[1] == '/' || !path[1])) {
+               path += 2;
+               goto eat_dot_dir;
+       }
+
+       if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2])
+           ) {
+               printk(KERN_ERR "nfs4_get_root:"
+                      " Mount path contains reference to \"..\"\n");
+               return -EINVAL;
+       }
+
+       /* lookup the next FH in the sequence */
+       memcpy(&lastfh, mntfh, sizeof(lastfh));
+
+       dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path);
+
+       ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name,
+                                                   mntfh, &fattr);
+       if (ret < 0) {
+               dprintk("nfs4_get_root: getroot error = %d\n", -ret);
+               return ret;
+       }
+
+       if (fattr.type != NFDIR) {
+               printk(KERN_ERR "nfs4_get_root:"
+                      " lookupfh encountered non-directory\n");
+               return -ENOTDIR;
+       }
+
+       if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) {
+               printk(KERN_ERR "nfs4_get_root:"
+                      " lookupfh obtained referral\n");
+               return -EREMOTE;
+       }
+
+       goto next_component;
+
+path_walk_complete:
+       memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid));
+       dprintk("<-- nfs4_path_walk() = 0\n");
+       return 0;
+}
+
+/*
+ * get an NFS4 root dentry from the root filehandle
+ */
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+{
+       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_fattr fattr;
+       struct dentry *mntroot;
+       struct inode *inode;
+       int error;
+
+       dprintk("--> nfs4_get_root()\n");
+
+       /* create a dummy root dentry with dummy inode for this superblock */
+       if (!sb->s_root) {
+               struct nfs_fh dummyfh;
+               struct dentry *root;
+               struct inode *iroot;
+
+               memset(&dummyfh, 0, sizeof(dummyfh));
+               memset(&fattr, 0, sizeof(fattr));
+               nfs_fattr_init(&fattr);
+               fattr.valid = NFS_ATTR_FATTR;
+               fattr.type = NFDIR;
+               fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
+               fattr.nlink = 2;
+
+               iroot = nfs_fhget(sb, &dummyfh, &fattr);
+               if (IS_ERR(iroot))
+                       return ERR_PTR(PTR_ERR(iroot));
+
+               root = d_alloc_root(iroot);
+               if (!root) {
+                       iput(iroot);
+                       return ERR_PTR(-ENOMEM);
+               }
+
+               sb->s_root = root;
+       }
+
+       /* get the info about the server and filesystem */
+       error = nfs4_server_capabilities(server, mntfh);
+       if (error < 0) {
+               dprintk("nfs_get_root: getcaps error = %d\n",
+                       -error);
+               return ERR_PTR(error);
+       }
+
+       /* get the actual root for this mount */
+       error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr);
+       if (error < 0) {
+               dprintk("nfs_get_root: getattr error = %d\n", -error);
+               return ERR_PTR(error);
+       }
+
+       inode = nfs_fhget(sb, mntfh, &fattr);
+       if (IS_ERR(inode)) {
+               dprintk("nfs_get_root: get root inode failed\n");
+               return ERR_PTR(PTR_ERR(inode));
+       }
+
+       /* root dentries normally start off anonymous and get spliced in later
+        * if the dentry tree reaches them; however if the dentry already
+        * exists, we'll pick it up at this point and use it as the root
+        */
+       mntroot = d_alloc_anon(inode);
+       if (!mntroot) {
+               iput(inode);
+               dprintk("nfs_get_root: get root dentry failed\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       security_d_instantiate(mntroot, inode);
+
+       if (!mntroot->d_op)
+               mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops;
+
+       dprintk("<-- nfs4_get_root()\n");
+       return mntroot;
+}
+
+#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
new file mode 100644 (file)
index 0000000..18febb4
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * NFS internal definitions
+ */
+
+#include <linux/mount.h>
+
+#define NFS_PAGE_WRITING       0
+#define NFS_PAGE_CACHED                1
+
+#define PageNfsBit(bit, page)          test_bit(bit, &(page)->private)
+
+#define SetPageNfsBit(bit, page)               \
+do {                                           \
+       SetPagePrivate((page));                 \
+       set_bit(bit, &(page)->private);         \
+} while(0)
+
+#define ClearPageNfsBit(bit, page)             \
+do {                                           \
+       clear_bit(bit, &(page)->private);       \
+} while(0)
+
+#define PageNfsWriting(page)           PageNfsBit(NFS_PAGE_WRITING, (page))
+#define SetPageNfsWriting(page)                SetPageNfsBit(NFS_PAGE_WRITING, (page))
+#define ClearPageNfsWriting(page)      ClearPageNfsBit(NFS_PAGE_WRITING, (page))
+
+#define PageNfsCached(page)            PageNfsBit(NFS_PAGE_CACHED, (page))
+#define SetPageNfsCached(page)         SetPageNfsBit(NFS_PAGE_CACHED, (page))
+#define ClearPageNfsCached(page)       ClearPageNfsBit(NFS_PAGE_CACHED, (page))
+
+struct nfs_string;
+struct nfs_mount_data;
+struct nfs4_mount_data;
+
+/* Maximum number of readahead requests
+ * FIXME: this should really be a sysctl so that users may tune it to suit
+ *        their needs. People that do NFS over a slow network, might for
+ *        instance want to reduce it to something closer to 1 for improved
+ *        interactive response.
+ */
+#define NFS_MAX_READAHEAD      (RPC_DEF_SLOT_TABLE - 1)
+
+struct nfs_clone_mount {
+       const struct super_block *sb;
+       const struct dentry *dentry;
+       struct nfs_fh *fh;
+       struct nfs_fattr *fattr;
+       char *hostname;
+       char *mnt_path;
+       struct sockaddr_in *addr;
+       rpc_authflavor_t authflavor;
+};
+
+/*
+ * include filesystem caching stuff here
+ */
+#include "fscache.h"
+
+/* client.c */
+extern struct rpc_program nfs_program;
+
+extern void nfs_put_client(struct nfs_client *);
+extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int);
+extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *,
+                                           struct nfs_fh *);
+extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *,
+                                            const char *,
+                                            const struct sockaddr_in *,
+                                            const char *,
+                                            const char *,
+                                            rpc_authflavor_t,
+                                            struct nfs_fh *);
+extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
+                                                     struct nfs_fh *);
+extern void nfs_free_server(struct nfs_server *server);
+extern struct nfs_server *nfs_clone_server(struct nfs_server *,
+                                          struct nfs_fh *,
+                                          struct nfs_fattr *);
+#ifdef CONFIG_PROC_FS
+extern int __init nfs_fs_proc_init(void);
+extern void nfs_fs_proc_exit(void);
+#else
+static inline int nfs_fs_proc_init(void)
+{
+       return 0;
+}
+static inline void nfs_fs_proc_exit(void)
+{
+}
+#endif
+
+/* nfs4namespace.c */
+#ifdef CONFIG_NFS_V4
+extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
+#else
+static inline
+struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+{
+       return ERR_PTR(-ENOENT);
+}
+#endif
+
+/* callback_xdr.c */
+extern struct svc_version nfs4_callback_version1;
+
+/* pagelist.c */
+extern int __init nfs_init_nfspagecache(void);
+extern void nfs_destroy_nfspagecache(void);
+extern int __init nfs_init_readpagecache(void);
+extern void nfs_destroy_readpagecache(void);
+extern int __init nfs_init_writepagecache(void);
+extern void nfs_destroy_writepagecache(void);
+
+#ifdef CONFIG_NFS_DIRECTIO
+extern int __init nfs_init_directcache(void);
+extern void nfs_destroy_directcache(void);
+#else
+#define nfs_init_directcache() (0)
+#define nfs_destroy_directcache() do {} while(0)
+#endif
+
+/* nfs2xdr.c */
+extern int nfs_stat_to_errno(int);
+extern struct rpc_procinfo nfs_procedures[];
+extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
+
+/* nfs3xdr.c */
+extern struct rpc_procinfo nfs3_procedures[];
+extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
+
+/* nfs4xdr.c */
+#ifdef CONFIG_NFS_V4
+extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
+#endif
+
+/* nfs4proc.c */
+#ifdef CONFIG_NFS_V4
+extern struct rpc_procinfo nfs4_procedures[];
+
+extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
+                                 struct nfs4_fs_locations *fs_locations,
+                                 struct page *page);
+#endif
+
+/* inode.c */
+extern struct inode *nfs_alloc_inode(struct super_block *sb);
+extern void nfs_destroy_inode(struct inode *);
+extern int nfs_write_inode(struct inode *,int);
+extern void nfs_clear_inode(struct inode *);
+#ifdef CONFIG_NFS_V4
+extern void nfs4_clear_inode(struct inode *);
+#endif
+
+/* super.c */
+extern struct file_system_type nfs_xdev_fs_type;
+#ifdef CONFIG_NFS_V4
+extern struct file_system_type nfs4_xdev_fs_type;
+extern struct file_system_type nfs4_referral_fs_type;
+#endif
+
+extern struct rpc_stat nfs_rpcstat;
+
+extern int __init register_nfs_fs(void);
+extern void __exit unregister_nfs_fs(void);
+
+/* namespace.c */
+extern char *nfs_path(const char *base,
+                     const struct dentry *droot,
+                     const struct dentry *dentry,
+                     char *buffer, ssize_t buflen);
+
+/* getroot.c */
+extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *);
+#ifdef CONFIG_NFS_V4
+extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *);
+
+extern int nfs4_path_walk(struct nfs_server *server,
+                         struct nfs_fh *mntfh,
+                         const char *path);
+#endif
+
+/* read.c */
+extern int nfs_readpage_async(struct nfs_open_context *, struct inode *, struct page *);
+
+/*
+ * Determine the device name as a string
+ */
+static inline char *nfs_devname(const struct vfsmount *mnt_parent,
+                               const struct dentry *dentry,
+                               char *buffer, ssize_t buflen)
+{
+       return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root,
+                       dentry, buffer, buflen);
+}
+
+/*
+ * Determine the actual block size (and log2 thereof)
+ */
+static inline
+unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
+{
+       /* make sure blocksize is a power of two */
+       if ((bsize & (bsize - 1)) || nrbitsp) {
+               unsigned char   nrbits;
+
+               for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)
+                       ;
+               bsize = 1 << nrbits;
+               if (nrbitsp)
+                       *nrbitsp = nrbits;
+       }
+
+       return bsize;
+}
+
+/*
+ * Calculate the number of 512byte blocks used.
+ */
+static inline unsigned long nfs_calc_block_size(u64 tsize)
+{
+       loff_t used = (tsize + 511) >> 9;
+       return (used > ULONG_MAX) ? ULONG_MAX : used;
+}
+
+/*
+ * Compute and set NFS server blocksize
+ */
+static inline
+unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
+{
+       if (bsize < NFS_MIN_FILE_IO_SIZE)
+               bsize = NFS_DEF_FILE_IO_SIZE;
+       else if (bsize >= NFS_MAX_FILE_IO_SIZE)
+               bsize = NFS_MAX_FILE_IO_SIZE;
+
+       return nfs_block_bits(bsize, nrbitsp);
+}
+
+/*
+ * Determine the maximum file size for a superblock
+ */
+static inline
+void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
+{
+       sb->s_maxbytes = (loff_t)maxfilesize;
+       if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
+               sb->s_maxbytes = MAX_LFS_FILESIZE;
+}
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
new file mode 100644 (file)
index 0000000..f4763c1
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * linux/fs/nfs/namespace.c
+ *
+ * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
+ * - Modified by David Howells <dhowells@redhat.com>
+ *
+ * NFS namespace
+ */
+
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/nfs_fs.h>
+#include <linux/string.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/vfs.h>
+#include "internal.h"
+
+#define NFSDBG_FACILITY                NFSDBG_VFS
+
+static void nfs_expire_automounts(void *list);
+
+LIST_HEAD(nfs_automount_list);
+static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
+int nfs_mountpoint_expiry_timeout = 500 * HZ;
+
+/*
+ * nfs_path - reconstruct the path given an arbitrary dentry
+ * @base - arbitrary string to prepend to the path
+ * @droot - pointer to root dentry for mountpoint
+ * @dentry - pointer to dentry
+ * @buffer - result buffer
+ * @buflen - length of buffer
+ *
+ * Helper function for constructing the path from the
+ * root dentry to an arbitrary hashed dentry.
+ *
+ * This is mainly for use in figuring out the path on the
+ * server side when automounting on top of an existing partition.
+ */
+char *nfs_path(const char *base,
+              const struct dentry *droot,
+              const struct dentry *dentry,
+              char *buffer, ssize_t buflen)
+{
+       char *end = buffer+buflen;
+       int namelen;
+
+       *--end = '\0';
+       buflen--;
+       spin_lock(&dcache_lock);
+       while (!IS_ROOT(dentry) && dentry != droot) {
+               namelen = dentry->d_name.len;
+               buflen -= namelen + 1;
+               if (buflen < 0)
+                       goto Elong_unlock;
+               end -= namelen;
+               memcpy(end, dentry->d_name.name, namelen);
+               *--end = '/';
+               dentry = dentry->d_parent;
+       }
+       spin_unlock(&dcache_lock);
+       namelen = strlen(base);
+       /* Strip off excess slashes in base string */
+       while (namelen > 0 && base[namelen - 1] == '/')
+               namelen--;
+       buflen -= namelen;
+       if (buflen < 0)
+               goto Elong;
+       end -= namelen;
+       memcpy(end, base, namelen);
+       return end;
+Elong_unlock:
+       spin_unlock(&dcache_lock);
+Elong:
+       return ERR_PTR(-ENAMETOOLONG);
+}
+
+/*
+ * nfs_follow_mountpoint - handle crossing a mountpoint on the server
+ * @dentry - dentry of mountpoint
+ * @nd - nameidata info
+ *
+ * When we encounter a mountpoint on the server, we want to set up
+ * a mountpoint on the client too, to prevent inode numbers from
+ * colliding, and to allow "df" to work properly.
+ * On NFSv4, we also want to allow for the fact that different
+ * filesystems may be migrated to different servers in a failover
+ * situation, and that different filesystems may want to use
+ * different security flavours.
+ */
+static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
+{
+       struct vfsmount *mnt;
+       struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+       struct dentry *parent;
+       struct nfs_fh fh;
+       struct nfs_fattr fattr;
+       int err;
+
+       dprintk("--> nfs_follow_mountpoint()\n");
+
+       BUG_ON(IS_ROOT(dentry));
+       dprintk("%s: enter\n", __FUNCTION__);
+       dput(nd->dentry);
+       nd->dentry = dget(dentry);
+
+       /* Look it up again */
+       parent = dget_parent(nd->dentry);
+       err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
+                                                 &nd->dentry->d_name,
+                                                 &fh, &fattr);
+       dput(parent);
+       if (err != 0)
+               goto out_err;
+
+       if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL)
+               mnt = nfs_do_refmount(nd->mnt, nd->dentry);
+       else
+               mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr);
+       err = PTR_ERR(mnt);
+       if (IS_ERR(mnt))
+               goto out_err;
+
+       mntget(mnt);
+       err = do_add_mount(mnt, nd, nd->mnt->mnt_flags|MNT_SHRINKABLE, &nfs_automount_list);
+       if (err < 0) {
+               mntput(mnt);
+               if (err == -EBUSY)
+                       goto out_follow;
+               goto out_err;
+       }
+       mntput(nd->mnt);
+       dput(nd->dentry);
+       nd->mnt = mnt;
+       nd->dentry = dget(mnt->mnt_root);
+       schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
+out:
+       dprintk("%s: done, returned %d\n", __FUNCTION__, err);
+
+       dprintk("<-- nfs_follow_mountpoint() = %d\n", err);
+       return ERR_PTR(err);
+out_err:
+       path_release(nd);
+       goto out;
+out_follow:
+       while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
+               ;
+       err = 0;
+       goto out;
+}
+
+struct inode_operations nfs_mountpoint_inode_operations = {
+       .follow_link    = nfs_follow_mountpoint,
+       .getattr        = nfs_getattr,
+};
+
+struct inode_operations nfs_referral_inode_operations = {
+       .follow_link    = nfs_follow_mountpoint,
+};
+
+static void nfs_expire_automounts(void *data)
+{
+       struct list_head *list = (struct list_head *)data;
+
+       mark_mounts_for_expiry(list);
+       if (!list_empty(list))
+               schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
+}
+
+void nfs_release_automount_timer(void)
+{
+       if (list_empty(&nfs_automount_list)) {
+               cancel_delayed_work(&nfs_automount_task);
+               flush_scheduled_work();
+       }
+}
+
+/*
+ * Clone a mountpoint of the appropriate type
+ */
+static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
+                                          const char *devname,
+                                          struct nfs_clone_mount *mountdata)
+{
+#ifdef CONFIG_NFS_V4
+       struct vfsmount *mnt = NULL;
+       switch (server->nfs_client->cl_nfsversion) {
+               case 2:
+               case 3:
+                       mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
+                       break;
+               case 4:
+                       mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata);
+       }
+       return mnt;
+#else
+       return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
+#endif
+}
+
+/**
+ * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
+ * @mnt_parent - mountpoint of parent directory
+ * @dentry - parent directory
+ * @fh - filehandle for new root dentry
+ * @fattr - attributes for new root inode
+ *
+ */
+struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+               const struct dentry *dentry, struct nfs_fh *fh,
+               struct nfs_fattr *fattr)
+{
+       struct nfs_clone_mount mountdata = {
+               .sb = mnt_parent->mnt_sb,
+               .dentry = dentry,
+               .fh = fh,
+               .fattr = fattr,
+       };
+       struct vfsmount *mnt = ERR_PTR(-ENOMEM);
+       char *page = (char *) __get_free_page(GFP_USER);
+       char *devname;
+
+       dprintk("--> nfs_do_submount()\n");
+
+       dprintk("%s: submounting on %s/%s\n", __FUNCTION__,
+                       dentry->d_parent->d_name.name,
+                       dentry->d_name.name);
+       if (page == NULL)
+               goto out;
+       devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
+       mnt = (struct vfsmount *)devname;
+       if (IS_ERR(devname))
+               goto free_page;
+       mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata);
+free_page:
+       free_page((unsigned long)page);
+out:
+       dprintk("%s: done\n", __FUNCTION__);
+
+       dprintk("<-- nfs_do_submount() = %p\n", mnt);
+       return mnt;
+}
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
new file mode 100644 (file)
index 0000000..b872779
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * linux/fs/nfs/nfs4namespace.c
+ *
+ * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
+ * - Modified by David Howells <dhowells@redhat.com>
+ *
+ * NFSv4 namespace
+ */
+
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/nfs_fs.h>
+#include <linux/string.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/vfs.h>
+#include <linux/inet.h>
+#include "internal.h"
+
+#define NFSDBG_FACILITY                NFSDBG_VFS
+
+/*
+ * Check if fs_root is valid
+ */
+static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
+                                        char *buffer, ssize_t buflen)
+{
+       char *end = buffer + buflen;
+       int n;
+
+       *--end = '\0';
+       buflen--;
+
+       n = pathname->ncomponents;
+       while (--n >= 0) {
+               const struct nfs4_string *component = &pathname->components[n];
+               buflen -= component->len + 1;
+               if (buflen < 0)
+                       goto Elong;
+               end -= component->len;
+               memcpy(end, component->data, component->len);
+               *--end = '/';
+       }
+       return end;
+Elong:
+       return ERR_PTR(-ENAMETOOLONG);
+}
+
+/*
+ * Determine the mount path as a string
+ */
+static char *nfs4_path(const struct vfsmount *mnt_parent,
+                      const struct dentry *dentry,
+                      char *buffer, ssize_t buflen)
+{
+       const char *srvpath;
+
+       srvpath = strchr(mnt_parent->mnt_devname, ':');
+       if (srvpath)
+               srvpath++;
+       else
+               srvpath = mnt_parent->mnt_devname;
+
+       return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen);
+}
+
+/*
+ * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we
+ * believe to be the server path to this dentry
+ */
+static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
+                               const struct dentry *dentry,
+                               const struct nfs4_fs_locations *locations,
+                               char *page, char *page2)
+{
+       const char *path, *fs_path;
+
+       path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE);
+       if (IS_ERR(path))
+               return PTR_ERR(path);
+
+       fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE);
+       if (IS_ERR(fs_path))
+               return PTR_ERR(fs_path);
+
+       if (strncmp(path, fs_path, strlen(fs_path)) != 0) {
+               dprintk("%s: path %s does not begin with fsroot %s\n",
+                       __FUNCTION__, path, fs_path);
+               return -ENOENT;
+       }
+
+       return 0;
+}
+
+/*
+ * Check if the string represents a "valid" IPv4 address
+ */
+static inline int valid_ipaddr4(const char *buf)
+{
+       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;
+       }
+       return 0;
+}
+
+/**
+ * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
+ * @mnt_parent - mountpoint of parent directory
+ * @dentry - parent directory
+ * @fspath - fs path returned in fs_locations
+ * @mntpath - mount path to new server
+ * @hostname - hostname of new server
+ * @addr - host addr of new server
+ *
+ */
+static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
+                                           const struct dentry *dentry,
+                                           const struct nfs4_fs_locations *locations)
+{
+       struct vfsmount *mnt = ERR_PTR(-ENOENT);
+       struct nfs_clone_mount mountdata = {
+               .sb = mnt_parent->mnt_sb,
+               .dentry = dentry,
+               .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
+       };
+       char *page = NULL, *page2 = NULL;
+       char *devname;
+       int loc, s, error;
+
+       if (locations == NULL || locations->nlocations <= 0)
+               goto out;
+
+       dprintk("%s: referral at %s/%s\n", __FUNCTION__,
+               dentry->d_parent->d_name.name, dentry->d_name.name);
+
+       page = (char *) __get_free_page(GFP_USER);
+       if (!page)
+               goto out;
+
+       page2 = (char *) __get_free_page(GFP_USER);
+       if (!page2)
+               goto out;
+
+       /* Ensure fs path is a prefix of current dentry path */
+       error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2);
+       if (error < 0) {
+               mnt = ERR_PTR(error);
+               goto out;
+       }
+
+       devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
+       if (IS_ERR(devname)) {
+               mnt = (struct vfsmount *)devname;
+               goto out;
+       }
+
+       loc = 0;
+       while (loc < locations->nlocations && IS_ERR(mnt)) {
+               const struct nfs4_fs_location *location = &locations->locations[loc];
+               char *mnt_path;
+
+               if (location == NULL || location->nservers <= 0 ||
+                   location->rootpath.ncomponents == 0) {
+                       loc++;
+                       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 = {};
+
+                       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);
+                       addr.sin_family = AF_INET;
+                       addr.sin_port = htons(NFS_PORT);
+                       mountdata.addr = &addr;
+
+                       mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata);
+                       if (!IS_ERR(mnt)) {
+                               break;
+                       }
+                       s++;
+               }
+               loc++;
+       }
+
+out:
+       free_page((unsigned long) page);
+       free_page((unsigned long) page2);
+       dprintk("%s: done\n", __FUNCTION__);
+       return mnt;
+}
+
+/*
+ * nfs_do_refmount - handle crossing a referral on server
+ * @dentry - dentry of referral
+ * @nd - nameidata info
+ *
+ */
+struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+{
+       struct vfsmount *mnt = ERR_PTR(-ENOMEM);
+       struct dentry *parent;
+       struct nfs4_fs_locations *fs_locations = NULL;
+       struct page *page;
+       int err;
+
+       /* BUG_ON(IS_ROOT(dentry)); */
+       dprintk("%s: enter\n", __FUNCTION__);
+
+       page = alloc_page(GFP_KERNEL);
+       if (page == NULL)
+               goto out;
+
+       fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
+       if (fs_locations == NULL)
+               goto out_free;
+
+       /* Get locations */
+       mnt = ERR_PTR(-ENOENT);
+
+       parent = dget_parent(dentry);
+       dprintk("%s: getting locations for %s/%s\n",
+               __FUNCTION__, parent->d_name.name, dentry->d_name.name);
+
+       err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page);
+       dput(parent);
+       if (err != 0 ||
+           fs_locations->nlocations <= 0 ||
+           fs_locations->fs_path.ncomponents <= 0)
+               goto out_free;
+
+       mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations);
+out_free:
+       __free_page(page);
+       kfree(fs_locations);
+out:
+       dprintk("%s: done\n", __FUNCTION__);
+       return mnt;
+}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
new file mode 100644 (file)
index 0000000..62e627b
--- /dev/null
@@ -0,0 +1,1068 @@
+/*
+ *  linux/fs/nfs/super.c
+ *
+ *  Copyright (C) 1992  Rick Sladkey
+ *
+ *  nfs superblock handling functions
+ *
+ *  Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
+ *  experimental NFS changes. Modularisation taken straight from SYS5 fs.
+ *
+ *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
+ *  J.S.Peatfield@damtp.cam.ac.uk
+ *
+ *  Split from inode.c by David Howells <dhowells@redhat.com>
+ *
+ * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a
+ *   particular server are held in the same superblock
+ * - NFS superblocks can have several effective roots to the dentry tree
+ * - directory type roots are spliced into the tree when a path from one root reaches the root
+ *   of another (see nfs_lookup())
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/stats.h>
+#include <linux/sunrpc/metrics.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include <linux/nfs4_mount.h>
+#include <linux/lockd/bind.h>
+#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/nfs_idmap.h>
+#include <linux/vfs.h>
+#include <linux/inet.h>
+#include <linux/nfs_xdr.h>
+#include <linux/vserver/xid.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "nfs4_fs.h"
+#include "callback.h"
+#include "delegation.h"
+#include "iostat.h"
+#include "internal.h"
+
+#define NFSDBG_FACILITY                NFSDBG_VFS
+
+static void nfs_umount_begin(struct vfsmount *, int);
+static int  nfs_statfs(struct dentry *, struct kstatfs *);
+static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
+static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
+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 struct file_system_type nfs_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "nfs",
+       .get_sb         = nfs_get_sb,
+       .kill_sb        = nfs_kill_super,
+       .fs_flags       = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs_xdev_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "nfs",
+       .get_sb         = nfs_xdev_get_sb,
+       .kill_sb        = nfs_kill_super,
+       .fs_flags       = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct super_operations nfs_sops = {
+       .alloc_inode    = nfs_alloc_inode,
+       .destroy_inode  = nfs_destroy_inode,
+       .write_inode    = nfs_write_inode,
+       .statfs         = nfs_statfs,
+       .clear_inode    = nfs_clear_inode,
+       .umount_begin   = nfs_umount_begin,
+       .show_options   = nfs_show_options,
+       .show_stats     = nfs_show_stats,
+};
+
+#ifdef CONFIG_NFS_V4
+static int nfs4_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static int nfs4_xdev_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static int nfs4_referral_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static void nfs4_kill_super(struct super_block *sb);
+
+static struct file_system_type nfs4_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "nfs4",
+       .get_sb         = nfs4_get_sb,
+       .kill_sb        = nfs4_kill_super,
+       .fs_flags       = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs4_xdev_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "nfs4",
+       .get_sb         = nfs4_xdev_get_sb,
+       .kill_sb        = nfs4_kill_super,
+       .fs_flags       = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs4_referral_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "nfs4",
+       .get_sb         = nfs4_referral_get_sb,
+       .kill_sb        = nfs4_kill_super,
+       .fs_flags       = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct super_operations nfs4_sops = {
+       .alloc_inode    = nfs_alloc_inode,
+       .destroy_inode  = nfs_destroy_inode,
+       .write_inode    = nfs_write_inode,
+       .statfs         = nfs_statfs,
+       .clear_inode    = nfs4_clear_inode,
+       .umount_begin   = nfs_umount_begin,
+       .show_options   = nfs_show_options,
+       .show_stats     = nfs_show_stats,
+};
+#endif
+
+/*
+ * Register the NFS filesystems
+ */
+int __init register_nfs_fs(void)
+{
+       int ret;
+
+        ret = register_filesystem(&nfs_fs_type);
+       if (ret < 0)
+               goto error_0;
+
+#ifdef CONFIG_NFS_V4
+       ret = nfs_register_sysctl();
+       if (ret < 0)
+               goto error_1;
+       ret = register_filesystem(&nfs4_fs_type);
+       if (ret < 0)
+               goto error_2;
+#endif
+       return 0;
+
+#ifdef CONFIG_NFS_V4
+error_2:
+       nfs_unregister_sysctl();
+error_1:
+       unregister_filesystem(&nfs_fs_type);
+#endif
+error_0:
+       return ret;
+}
+
+/*
+ * Unregister the NFS filesystems
+ */
+void __exit unregister_nfs_fs(void)
+{
+#ifdef CONFIG_NFS_V4
+       unregister_filesystem(&nfs4_fs_type);
+       nfs_unregister_sysctl();
+#endif
+       unregister_filesystem(&nfs_fs_type);
+}
+
+/*
+ * Deliver file system statistics to userspace
+ */
+static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+       struct nfs_server *server = NFS_SB(dentry->d_sb);
+       unsigned char blockbits;
+       unsigned long blockres;
+       struct nfs_fh *fh = NFS_FH(dentry->d_inode);
+       struct nfs_fattr fattr;
+       struct nfs_fsstat res = {
+                       .fattr = &fattr,
+       };
+       int error;
+
+       lock_kernel();
+
+       error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
+       buf->f_type = NFS_SUPER_MAGIC;
+       if (error < 0)
+               goto out_err;
+
+       /*
+        * Current versions of glibc do not correctly handle the
+        * case where f_frsize != f_bsize.  Eventually we want to
+        * report the value of wtmult in this field.
+        */
+       buf->f_frsize = dentry->d_sb->s_blocksize;
+
+       /*
+        * On most *nix systems, f_blocks, f_bfree, and f_bavail
+        * are reported in units of f_frsize.  Linux hasn't had
+        * an f_frsize field in its statfs struct until recently,
+        * thus historically Linux's sys_statfs reports these
+        * fields in units of f_bsize.
+        */
+       buf->f_bsize = dentry->d_sb->s_blocksize;
+       blockbits = dentry->d_sb->s_blocksize_bits;
+       blockres = (1 << blockbits) - 1;
+       buf->f_blocks = (res.tbytes + blockres) >> blockbits;
+       buf->f_bfree = (res.fbytes + blockres) >> blockbits;
+       buf->f_bavail = (res.abytes + blockres) >> blockbits;
+
+       buf->f_files = res.tfiles;
+       buf->f_ffree = res.afiles;
+
+       buf->f_namelen = server->namelen;
+ out:
+       unlock_kernel();
+       return 0;
+
+ out_err:
+       dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
+       buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
+       goto out;
+
+}
+
+/*
+ * Map the security flavour number to a name
+ */
+static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
+{
+       static const struct {
+               rpc_authflavor_t flavour;
+               const char *str;
+       } sec_flavours[] = {
+               { RPC_AUTH_NULL, "null" },
+               { RPC_AUTH_UNIX, "sys" },
+               { RPC_AUTH_GSS_KRB5, "krb5" },
+               { RPC_AUTH_GSS_KRB5I, "krb5i" },
+               { RPC_AUTH_GSS_KRB5P, "krb5p" },
+               { RPC_AUTH_GSS_LKEY, "lkey" },
+               { RPC_AUTH_GSS_LKEYI, "lkeyi" },
+               { RPC_AUTH_GSS_LKEYP, "lkeyp" },
+               { RPC_AUTH_GSS_SPKM, "spkm" },
+               { RPC_AUTH_GSS_SPKMI, "spkmi" },
+               { RPC_AUTH_GSS_SPKMP, "spkmp" },
+               { -1, "unknown" }
+       };
+       int i;
+
+       for (i=0; sec_flavours[i].flavour != -1; i++) {
+               if (sec_flavours[i].flavour == flavour)
+                       break;
+       }
+       return sec_flavours[i].str;
+}
+
+/*
+ * Describe the mount options in force on this server representation
+ */
+static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
+{
+       static const struct proc_nfs_info {
+               int flag;
+               const char *str;
+               const char *nostr;
+       } nfs_info[] = {
+               { NFS_MOUNT_SOFT, ",soft", ",hard" },
+               { NFS_MOUNT_INTR, ",intr", "" },
+               { NFS_MOUNT_NOCTO, ",nocto", "" },
+               { NFS_MOUNT_NOAC, ",noac", "" },
+               { NFS_MOUNT_NONLM, ",nolock", "" },
+               { NFS_MOUNT_NOACL, ",noacl", "" },
+               { NFS_MOUNT_FSCACHE, ",fsc", "" },
+               { NFS_MOUNT_TAGXID, ",tagxid", "" },
+               { 0, NULL, NULL }
+       };
+       const struct proc_nfs_info *nfs_infop;
+       struct nfs_client *clp = nfss->nfs_client;
+       char buf[12];
+       const char *proto;
+
+       seq_printf(m, ",vers=%d", clp->rpc_ops->version);
+       seq_printf(m, ",rsize=%d", nfss->rsize);
+       seq_printf(m, ",wsize=%d", nfss->wsize);
+       if (nfss->acregmin != 3*HZ || showdefaults)
+               seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
+       if (nfss->acregmax != 60*HZ || showdefaults)
+               seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
+       if (nfss->acdirmin != 30*HZ || showdefaults)
+               seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
+       if (nfss->acdirmax != 60*HZ || showdefaults)
+               seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
+       for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
+               if (nfss->flags & nfs_infop->flag)
+                       seq_puts(m, nfs_infop->str);
+               else
+                       seq_puts(m, nfs_infop->nostr);
+       }
+       switch (nfss->client->cl_xprt->prot) {
+               case IPPROTO_TCP:
+                       proto = "tcp";
+                       break;
+               case IPPROTO_UDP:
+                       proto = "udp";
+                       break;
+               default:
+                       snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
+                       proto = buf;
+       }
+       seq_printf(m, ",proto=%s", proto);
+       seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ);
+       seq_printf(m, ",retrans=%u", clp->retrans_count);
+       seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
+}
+
+/*
+ * Describe the mount options on this VFS mountpoint
+ */
+static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+       struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+
+       nfs_show_mount_options(m, nfss, 0);
+
+       seq_puts(m, ",addr=");
+       seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\");
+
+       return 0;
+}
+
+/*
+ * Present statistical information for this VFS mountpoint
+ */
+static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+{
+       int i, cpu;
+       struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+       struct rpc_auth *auth = nfss->client->cl_auth;
+       struct nfs_iostats totals = { };
+
+       seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
+
+       /*
+        * Display all mount option settings
+        */
+       seq_printf(m, "\n\topts:\t");
+       seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
+       seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
+       seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
+       seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
+       nfs_show_mount_options(m, nfss, 1);
+
+       seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
+
+       seq_printf(m, "\n\tcaps:\t");
+       seq_printf(m, "caps=0x%x", nfss->caps);
+       seq_printf(m, ",wtmult=%d", nfss->wtmult);
+       seq_printf(m, ",dtsize=%d", nfss->dtsize);
+       seq_printf(m, ",bsize=%d", nfss->bsize);
+       seq_printf(m, ",namelen=%d", nfss->namelen);
+
+#ifdef CONFIG_NFS_V4
+       if (nfss->nfs_client->cl_nfsversion == 4) {
+               seq_printf(m, "\n\tnfsv4:\t");
+               seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
+               seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
+               seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
+       }
+#endif
+
+       /*
+        * Display security flavor in effect for this mount
+        */
+       seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
+       if (auth->au_flavor)
+               seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
+
+       /*
+        * Display superblock I/O counters
+        */
+       for_each_possible_cpu(cpu) {
+               struct nfs_iostats *stats;
+
+               preempt_disable();
+               stats = per_cpu_ptr(nfss->io_stats, cpu);
+
+               for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
+                       totals.events[i] += stats->events[i];
+               for (i = 0; i < __NFSIOS_BYTESMAX; i++)
+                       totals.bytes[i] += stats->bytes[i];
+
+               preempt_enable();
+       }
+
+       seq_printf(m, "\n\tevents:\t");
+       for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
+               seq_printf(m, "%lu ", totals.events[i]);
+       seq_printf(m, "\n\tbytes:\t");
+       for (i = 0; i < __NFSIOS_BYTESMAX; i++)
+               seq_printf(m, "%Lu ", totals.bytes[i]);
+       seq_printf(m, "\n");
+
+       rpc_print_iostats(m, nfss->client);
+
+       return 0;
+}
+
+/*
+ * Begin unmount by attempting to remove all automounted mountpoints we added
+ * in response to xdev traversals and referrals
+ */
+static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
+{
+       shrink_submounts(vfsmnt, &nfs_automount_list);
+}
+
+/*
+ * Validate the NFS2/NFS3 mount data
+ * - fills in the mount root filehandle
+ */
+static int nfs_validate_mount_data(struct nfs_mount_data *data,
+                                  struct nfs_fh *mntfh)
+{
+       if (data == NULL) {
+               dprintk("%s: missing data argument\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
+               dprintk("%s: bad mount version\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       switch (data->version) {
+               case 1:
+                       data->namlen = 0;
+               case 2:
+                       data->bsize  = 0;
+               case 3:
+                       if (data->flags & NFS_MOUNT_VER3) {
+                               dprintk("%s: mount structure version %d does not support NFSv3\n",
+                                               __FUNCTION__,
+                                               data->version);
+                               return -EINVAL;
+                       }
+                       data->root.size = NFS2_FHSIZE;
+                       memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+               case 4:
+                       if (data->flags & NFS_MOUNT_SECFLAVOUR) {
+                               dprintk("%s: mount structure version %d does not support strong security\n",
+                                               __FUNCTION__,
+                                               data->version);
+                               return -EINVAL;
+                       }
+                       /* Fill in pseudoflavor for mount version < 5 */
+                       data->pseudoflavor = RPC_AUTH_UNIX;
+               case 5:
+                       memset(data->context, 0, sizeof(data->context));
+       }
+
+#ifndef CONFIG_NFS_V3
+       /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
+       if (data->flags & NFS_MOUNT_VER3) {
+               dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
+               return -EPROTONOSUPPORT;
+       }
+#endif /* CONFIG_NFS_V3 */
+
+       /* We now require that the mount process passes the remote address */
+       if (data->addr.sin_addr.s_addr == INADDR_ANY) {
+               dprintk("%s: mount program didn't pass remote address!\n",
+                       __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Prepare the root filehandle */
+       if (data->flags & NFS_MOUNT_VER3)
+               mntfh->size = data->root.size;
+       else
+               mntfh->size = NFS2_FHSIZE;
+
+       if (mntfh->size > sizeof(mntfh->data)) {
+               dprintk("%s: invalid root filehandle\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       memcpy(mntfh->data, data->root.data, mntfh->size);
+       if (mntfh->size < sizeof(mntfh->data))
+               memset(mntfh->data + mntfh->size, 0,
+                      sizeof(mntfh->data) - mntfh->size);
+
+       return 0;
+}
+
+/*
+ * Initialise the common bits of the superblock
+ */
+static inline void nfs_initialise_sb(struct super_block *sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       sb->s_magic = NFS_SUPER_MAGIC;
+
+       /* We probably want something more informative here */
+       snprintf(sb->s_id, sizeof(sb->s_id),
+                "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
+
+       if (sb->s_blocksize == 0)
+               sb->s_blocksize = nfs_block_bits(server->wsize,
+                                                &sb->s_blocksize_bits);
+
+       if (server->flags & NFS_MOUNT_NOAC)
+               sb->s_flags |= MS_SYNCHRONOUS;
+       if (server->flags & NFS_MOUNT_TAGXID)
+               sb->s_flags |= MS_TAGXID;
+
+       nfs_super_set_maxbytes(sb, server->maxfilesize);
+}
+
+/*
+ * Finish setting up an NFS2/3 superblock
+ */
+static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       sb->s_blocksize_bits = 0;
+       sb->s_blocksize = 0;
+       if (data->bsize)
+               sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
+
+       if (server->flags & NFS_MOUNT_VER3) {
+               /* The VFS shouldn't apply the umask to mode bits. We will do
+                * so ourselves when necessary.
+                */
+               sb->s_flags |= MS_POSIXACL;
+               sb->s_time_gran = 1;
+       }
+
+       sb->s_op = &nfs_sops;
+       nfs_initialise_sb(sb);
+}
+
+/*
+ * Finish setting up a cloned NFS2/3 superblock
+ */
+static void nfs_clone_super(struct super_block *sb,
+                           const struct super_block *old_sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       sb->s_blocksize_bits = old_sb->s_blocksize_bits;
+       sb->s_blocksize = old_sb->s_blocksize;
+       sb->s_maxbytes = old_sb->s_maxbytes;
+
+       if (server->flags & NFS_MOUNT_VER3) {
+               /* The VFS shouldn't apply the umask to mode bits. We will do
+                * so ourselves when necessary.
+                */
+               sb->s_flags |= MS_POSIXACL;
+               sb->s_time_gran = 1;
+       }
+
+       sb->s_op = old_sb->s_op;
+       nfs_initialise_sb(sb);
+}
+
+static int nfs_set_super(struct super_block *s, void *_server)
+{
+       struct nfs_server *server = _server;
+       int ret;
+
+       s->s_fs_info = server;
+       ret = set_anon_super(s, server);
+       if (ret == 0)
+               server->s_dev = s->s_dev;
+       return ret;
+}
+
+static int nfs_compare_super(struct super_block *sb, void *data)
+{
+       struct nfs_server *server = data, *old = NFS_SB(sb);
+
+       if (old->nfs_client != server->nfs_client)
+               return 0;
+       if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
+               return 0;
+       return 1;
+}
+
+static int nfs_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+       struct nfs_server *server = NULL;
+       struct super_block *s;
+       struct nfs_fh mntfh;
+       struct nfs_mount_data *data = raw_data;
+       struct dentry *mntroot;
+       int error;
+
+       /* Validate the mount data */
+       error = nfs_validate_mount_data(data, &mntfh);
+       if (error < 0)
+               return error;
+
+       /* Get a volume representation */
+       server = nfs_create_server(data, &mntfh);
+       if (IS_ERR(server)) {
+               error = PTR_ERR(server);
+               goto out_err_noserver;
+       }
+
+       /* Get a superblock - note that we may end up sharing one that already exists */
+       s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+       }
+
+       if (s->s_fs_info != server) {
+               nfs_free_server(server);
+               server = NULL;
+       }
+
+       if (!s->s_root) {
+               /* initial superblock/root creation */
+               s->s_flags = flags;
+               nfs_fill_super(s, data);
+       }
+
+       mntroot = nfs_get_root(s, &mntfh);
+       if (IS_ERR(mntroot)) {
+               error = PTR_ERR(mntroot);
+               goto error_splat_super;
+       }
+
+       s->s_flags |= MS_ACTIVE;
+       mnt->mnt_sb = s;
+       mnt->mnt_root = mntroot;
+       return 0;
+
+out_err_nosb:
+       nfs_free_server(server);
+out_err_noserver:
+       return error;
+
+error_splat_super:
+       up_write(&s->s_umount);
+       deactivate_super(s);
+       return error;
+}
+
+/*
+ * Destroy an NFS2/3 superblock
+ */
+static void nfs_kill_super(struct super_block *s)
+{
+       struct nfs_server *server = NFS_SB(s);
+
+       kill_anon_super(s);
+       nfs_free_server(server);
+}
+
+/*
+ * Clone an NFS2/3 server record on xdev traversal (FSID-change)
+ */
+static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
+                          const char *dev_name, void *raw_data,
+                          struct vfsmount *mnt)
+{
+       struct nfs_clone_mount *data = raw_data;
+       struct super_block *s;
+       struct nfs_server *server;
+       struct dentry *mntroot;
+       int error;
+
+       dprintk("--> nfs_xdev_get_sb()\n");
+
+       /* create a new volume representation */
+       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+       if (IS_ERR(server)) {
+               error = PTR_ERR(server);
+               goto out_err_noserver;
+       }
+
+       /* Get a superblock - note that we may end up sharing one that already exists */
+       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+       }
+
+       if (s->s_fs_info != server) {
+               nfs_free_server(server);
+               server = NULL;
+       }
+
+       if (!s->s_root) {
+               /* initial superblock/root creation */
+               s->s_flags = flags;
+               nfs_clone_super(s, data->sb);
+       }
+
+       mntroot = nfs_get_root(s, data->fh);
+       if (IS_ERR(mntroot)) {
+               error = PTR_ERR(mntroot);
+               goto error_splat_super;
+       }
+
+       s->s_flags |= MS_ACTIVE;
+       mnt->mnt_sb = s;
+       mnt->mnt_root = mntroot;
+
+       dprintk("<-- nfs_xdev_get_sb() = 0\n");
+       return 0;
+
+out_err_nosb:
+       nfs_free_server(server);
+out_err_noserver:
+       dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error);
+       return error;
+
+error_splat_super:
+       up_write(&s->s_umount);
+       deactivate_super(s);
+       dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
+       return error;
+}
+
+#ifdef CONFIG_NFS_V4
+
+/*
+ * Finish setting up a cloned NFS4 superblock
+ */
+static void nfs4_clone_super(struct super_block *sb,
+                           const struct super_block *old_sb)
+{
+       sb->s_blocksize_bits = old_sb->s_blocksize_bits;
+       sb->s_blocksize = old_sb->s_blocksize;
+       sb->s_maxbytes = old_sb->s_maxbytes;
+       sb->s_time_gran = 1;
+       sb->s_op = old_sb->s_op;
+       nfs_initialise_sb(sb);
+}
+
+/*
+ * Set up an NFS4 superblock
+ */
+static void nfs4_fill_super(struct super_block *sb)
+{
+       sb->s_time_gran = 1;
+       sb->s_op = &nfs4_sops;
+       nfs_initialise_sb(sb);
+}
+
+static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
+{
+       void *p = NULL;
+
+       if (!src->len)
+               return ERR_PTR(-EINVAL);
+       if (src->len < maxlen)
+               maxlen = src->len;
+       if (dst == NULL) {
+               p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
+               if (p == NULL)
+                       return ERR_PTR(-ENOMEM);
+       }
+       if (copy_from_user(dst, src->data, maxlen)) {
+               kfree(p);
+               return ERR_PTR(-EFAULT);
+       }
+       dst[maxlen] = '\0';
+       return dst;
+}
+
+/*
+ * Get the superblock for an NFS4 mountpoint
+ */
+static int nfs4_get_sb(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+       struct nfs4_mount_data *data = raw_data;
+       struct super_block *s;
+       struct nfs_server *server;
+       struct sockaddr_in addr;
+       rpc_authflavor_t authflavour;
+       struct nfs_fh mntfh;
+       struct dentry *mntroot;
+       char *mntpath = NULL, *hostname = NULL, ip_addr[16];
+       void *p;
+       int error;
+
+       if (data == NULL) {
+               dprintk("%s: missing data argument\n", __FUNCTION__);
+               return -EINVAL;
+       }
+       if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
+               dprintk("%s: bad mount version\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* We now require that the mount process passes the remote address */
+       if (data->host_addrlen != sizeof(addr))
+               return -EINVAL;
+
+       if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
+               return -EFAULT;
+
+       if (addr.sin_family != AF_INET ||
+           addr.sin_addr.s_addr == INADDR_ANY
+           ) {
+               dprintk("%s: mount program didn't pass remote IP address!\n",
+                               __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* Grab the authentication type */
+       authflavour = RPC_AUTH_UNIX;
+       if (data->auth_flavourlen != 0) {
+               if (data->auth_flavourlen != 1) {
+                       dprintk("%s: Invalid number of RPC auth flavours %d.\n",
+                                       __FUNCTION__, data->auth_flavourlen);
+                       error = -EINVAL;
+                       goto out_err_noserver;
+               }
+
+               if (copy_from_user(&authflavour, data->auth_flavours,
+                                  sizeof(authflavour))) {
+                       error = -EFAULT;
+                       goto out_err_noserver;
+               }
+       }
+
+       p = nfs_copy_user_string(NULL, &data->hostname, 256);
+       if (IS_ERR(p))
+               goto out_err;
+       hostname = p;
+
+       p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
+       if (IS_ERR(p))
+               goto out_err;
+       mntpath = p;
+
+       dprintk("MNTPATH: %s\n", mntpath);
+
+       p = nfs_copy_user_string(ip_addr, &data->client_addr,
+                                sizeof(ip_addr) - 1);
+       if (IS_ERR(p))
+               goto out_err;
+
+       /* Get a volume representation */
+       server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
+                                   authflavour, &mntfh);
+       if (IS_ERR(server)) {
+               error = PTR_ERR(server);
+               goto out_err_noserver;
+       }
+
+       /* Get a superblock - note that we may end up sharing one that already exists */
+       s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_free;
+       }
+
+       if (s->s_fs_info != server) {
+               nfs_free_server(server);
+               server = NULL;
+       }
+
+       if (!s->s_root) {
+               /* initial superblock/root creation */
+               s->s_flags = flags;
+               nfs4_fill_super(s);
+       }
+
+       mntroot = nfs4_get_root(s, &mntfh);
+       if (IS_ERR(mntroot)) {
+               error = PTR_ERR(mntroot);
+               goto error_splat_super;
+       }
+
+       s->s_flags |= MS_ACTIVE;
+       mnt->mnt_sb = s;
+       mnt->mnt_root = mntroot;
+       kfree(mntpath);
+       kfree(hostname);
+       return 0;
+
+out_err:
+       error = PTR_ERR(p);
+       goto out_err_noserver;
+
+out_free:
+       nfs_free_server(server);
+out_err_noserver:
+       kfree(mntpath);
+       kfree(hostname);
+       return error;
+
+error_splat_super:
+       up_write(&s->s_umount);
+       deactivate_super(s);
+       goto out_err_noserver;
+}
+
+static void nfs4_kill_super(struct super_block *sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       nfs_return_all_delegations(sb);
+       kill_anon_super(sb);
+
+       nfs4_renewd_prepare_shutdown(server);
+       nfs_free_server(server);
+}
+
+/*
+ * Clone an NFS4 server record on xdev traversal (FSID-change)
+ */
+static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
+                           const char *dev_name, void *raw_data,
+                           struct vfsmount *mnt)
+{
+       struct nfs_clone_mount *data = raw_data;
+       struct super_block *s;
+       struct nfs_server *server;
+       struct dentry *mntroot;
+       int error;
+
+       dprintk("--> nfs4_xdev_get_sb()\n");
+
+       /* create a new volume representation */
+       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+       if (IS_ERR(server)) {
+               error = PTR_ERR(server);
+               goto out_err_noserver;
+       }
+
+       /* Get a superblock - note that we may end up sharing one that already exists */
+       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+       }
+
+       if (s->s_fs_info != server) {
+               nfs_free_server(server);
+               server = NULL;
+       }
+
+       if (!s->s_root) {
+               /* initial superblock/root creation */
+               s->s_flags = flags;
+               nfs4_clone_super(s, data->sb);
+       }
+
+       mntroot = nfs4_get_root(s, data->fh);
+       if (IS_ERR(mntroot)) {
+               error = PTR_ERR(mntroot);
+               goto error_splat_super;
+       }
+
+       s->s_flags |= MS_ACTIVE;
+       mnt->mnt_sb = s;
+       mnt->mnt_root = mntroot;
+
+       dprintk("<-- nfs4_xdev_get_sb() = 0\n");
+       return 0;
+
+out_err_nosb:
+       nfs_free_server(server);
+out_err_noserver:
+       dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error);
+       return error;
+
+error_splat_super:
+       up_write(&s->s_umount);
+       deactivate_super(s);
+       dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
+       return error;
+}
+
+/*
+ * Create an NFS4 server record on referral traversal
+ */
+static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
+                               const char *dev_name, void *raw_data,
+                               struct vfsmount *mnt)
+{
+       struct nfs_clone_mount *data = raw_data;
+       struct super_block *s;
+       struct nfs_server *server;
+       struct dentry *mntroot;
+       struct nfs_fh mntfh;
+       int error;
+
+       dprintk("--> nfs4_referral_get_sb()\n");
+
+       /* create a new volume representation */
+       server = nfs4_create_referral_server(data, &mntfh);
+       if (IS_ERR(server)) {
+               error = PTR_ERR(server);
+               goto out_err_noserver;
+       }
+
+       /* Get a superblock - note that we may end up sharing one that already exists */
+       s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+       if (IS_ERR(s)) {
+               error = PTR_ERR(s);
+               goto out_err_nosb;
+       }
+
+       if (s->s_fs_info != server) {
+               nfs_free_server(server);
+               server = NULL;
+       }
+
+       if (!s->s_root) {
+               /* initial superblock/root creation */
+               s->s_flags = flags;
+               nfs4_fill_super(s);
+       }
+
+       mntroot = nfs4_get_root(s, data->fh);
+       if (IS_ERR(mntroot)) {
+               error = PTR_ERR(mntroot);
+               goto error_splat_super;
+       }
+
+       s->s_flags |= MS_ACTIVE;
+       mnt->mnt_sb = s;
+       mnt->mnt_root = mntroot;
+
+       dprintk("<-- nfs4_referral_get_sb() = 0\n");
+       return 0;
+
+out_err_nosb:
+       nfs_free_server(server);
+out_err_noserver:
+       dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error);
+       return error;
+
+error_splat_super:
+       up_write(&s->s_umount);
+       deactivate_super(s);
+       dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
+       return error;
+}
+
+#endif /* CONFIG_NFS_V4 */
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
new file mode 100644 (file)
index 0000000..dcbef0d
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.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 Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs.h
+ */
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+#endif
+
+#ifdef SQUASHFS_TRACE
+#define TRACE(s, args...)      printk(KERN_NOTICE "SQUASHFS: "s, ## args)
+#else
+#define TRACE(s, args...)      {}
+#endif
+
+#define ERROR(s, args...)      printk(KERN_ERR "SQUASHFS error: "s, ## args)
+
+#define SERROR(s, args...)     do { \
+                               if (!silent) \
+                               printk(KERN_ERR "SQUASHFS error: "s, ## args);\
+                               } while(0)
+
+#define WARNING(s, args...)    printk(KERN_WARNING "SQUASHFS: "s, ## args)
+
+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
+{
+       return list_entry(inode, struct squashfs_inode_info, vfs_inode);
+}
+
+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
+#define SQSH_EXTERN
+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+                               long long index, unsigned int length,
+                               long long *next_index);
+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
+                               long long block, unsigned int offset,
+                               int length, long long *next_block,
+                               unsigned int *next_offset);
+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
+                                       squashfs_fragment_cache *fragment);
+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
+                                       *s, long long start_block,
+                                       int length);
+extern struct address_space_operations squashfs_symlink_aops;
+extern struct address_space_operations squashfs_aops;
+extern struct address_space_operations squashfs_aops_4K;
+extern struct inode_operations squashfs_dir_inode_ops;
+#else
+#define SQSH_EXTERN static
+#endif
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
+#else
+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
+{
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
+#else
+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
+{
+       return 0;
+}
+#endif
diff --git a/fs/squashfs/squashfs2_0.c b/fs/squashfs/squashfs2_0.c
new file mode 100644 (file)
index 0000000..53ce95e
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.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 Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs2_0.c
+ */
+
+#include <linux/types.h>
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/zlib.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/squashfs_fs_sb.h>
+#include <linux/squashfs_fs_i.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/init.h>
+#include <linux/dcache.h>
+#include <linux/wait.h>
+#include <linux/zlib.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "squashfs.h"
+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
+                               struct nameidata *);
+
+static struct file_operations squashfs_dir_ops_2 = {
+       .read = generic_read_dir,
+       .readdir = squashfs_readdir_2
+};
+
+static struct inode_operations squashfs_dir_inode_ops_2 = {
+       .lookup = squashfs_lookup_2
+};
+
+static unsigned char squashfs_filetype_table[] = {
+       DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
+};
+
+static int read_fragment_index_table_2(struct super_block *s)
+{
+       struct squashfs_sb_info *msblk = s->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+
+       if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
+                                       (sblk->fragments), GFP_KERNEL))) {
+               ERROR("Failed to allocate uid/gid table\n");
+               return 0;
+       }
+   
+       if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
+                                       !squashfs_read_data(s, (char *)
+                                       msblk->fragment_index_2,
+                                       sblk->fragment_table_start,
+                                       SQUASHFS_FRAGMENT_INDEX_BYTES_2
+                                       (sblk->fragments) |
+                                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+               ERROR("unable to read fragment index table\n");
+               return 0;
+       }
+
+       if (msblk->swap) {
+               int i;
+               unsigned int fragment;
+
+               for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
+                                                                       i++) {
+                       SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
+                                               &msblk->fragment_index_2[i], 1);
+                       msblk->fragment_index_2[i] = fragment;
+               }
+       }
+
+       return 1;
+}
+
+
+static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
+                               long long *fragment_start_block,
+                               unsigned int *fragment_size)
+{
+       struct squashfs_sb_info *msblk = s->s_fs_info;
+       long long start_block =
+               msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
+       int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
+       struct squashfs_fragment_entry_2 fragment_entry;
+
+       if (msblk->swap) {
+               struct squashfs_fragment_entry_2 sfragment_entry;
+
+               if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
+                                       start_block, offset,
+                                       sizeof(sfragment_entry), &start_block,
+                                       &offset))
+                       goto out;
+               SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
+       } else
+               if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
+                                       start_block, offset,
+                                       sizeof(fragment_entry), &start_block,
+                                       &offset))
+                       goto out;
+
+       *fragment_start_block = fragment_entry.start_block;
+       *fragment_size = fragment_entry.size;
+
+       return 1;
+
+out:
+       return 0;
+}
+
+
+static struct inode *squashfs_new_inode(struct super_block *s,
+               struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
+{
+       struct squashfs_sb_info *msblk = s->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+       struct inode *i = new_inode(s);
+
+       if (i) {
+               i->i_ino = ino;
+               i->i_mtime.tv_sec = sblk->mkfs_time;
+               i->i_atime.tv_sec = sblk->mkfs_time;
+               i->i_ctime.tv_sec = sblk->mkfs_time;
+               i->i_uid = msblk->uid[inodeb->uid];
+               i->i_mode = inodeb->mode;
+               i->i_nlink = 1;
+               i->i_size = 0;
+               if (inodeb->guid == SQUASHFS_GUIDS)
+                       i->i_gid = i->i_uid;
+               else
+                       i->i_gid = msblk->guid[inodeb->guid];
+       }
+
+       return i;
+}
+
+
+static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
+{
+       struct inode *i;
+       struct squashfs_sb_info *msblk = s->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+       unsigned int block = SQUASHFS_INODE_BLK(inode) +
+               sblk->inode_table_start;
+       unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+       unsigned int ino = SQUASHFS_MK_VFS_INODE(block
+               - sblk->inode_table_start, offset);
+       long long next_block;
+       unsigned int next_offset;
+       union squashfs_inode_header_2 id, sid;
+       struct squashfs_base_inode_header_2 *inodeb = &id.base,
+                                         *sinodeb = &sid.base;
+
+       TRACE("Entered squashfs_iget\n");
+
+       if (msblk->swap) {
+               if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
+                                       offset, sizeof(*sinodeb), &next_block,
+                                       &next_offset))
+                       goto failed_read;
+               SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
+                                       sizeof(*sinodeb));
+       } else
+               if (!squashfs_get_cached_block(s, (char *) inodeb, block,
+                                       offset, sizeof(*inodeb), &next_block,
+                                       &next_offset))
+                       goto failed_read;
+
+       switch(inodeb->inode_type) {
+               case SQUASHFS_FILE_TYPE: {
+                       struct squashfs_reg_inode_header_2 *inodep = &id.reg;
+                       struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
+                       long long frag_blk;
+                       unsigned int frag_size;
+                               
+                       if (msblk->swap) {
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               sinodep, block, offset,
+                                               sizeof(*sinodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
+                       } else
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               inodep, block, offset,
+                                               sizeof(*inodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                       frag_blk = SQUASHFS_INVALID_BLK;
+                       if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+                                       !get_fragment_location_2(s,
+                                       inodep->fragment, &frag_blk, &frag_size))
+                               goto failed_read;
+                               
+                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+                               goto failed_read1;
+
+                       i->i_size = inodep->file_size;
+                       i->i_fop = &generic_ro_fops;
+                       i->i_mode |= S_IFREG;
+                       i->i_mtime.tv_sec = inodep->mtime;
+                       i->i_atime.tv_sec = inodep->mtime;
+                       i->i_ctime.tv_sec = inodep->mtime;
+                       i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+                       SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+                       SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+                       SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+                       SQUASHFS_I(i)->start_block = inodep->start_block;
+                       SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+                       SQUASHFS_I(i)->offset = next_offset;
+                       if (sblk->block_size > 4096)
+                               i->i_data.a_ops = &squashfs_aops;
+                       else
+                               i->i_data.a_ops = &squashfs_aops_4K;
+
+                       TRACE("File inode %x:%x, start_block %x, "
+                                       "block_list_start %llx, offset %x\n",
+                                       SQUASHFS_INODE_BLK(inode), offset,
+                                       inodep->start_block, next_block,
+                                       next_offset);
+                       break;
+               }
+               case SQUASHFS_DIR_TYPE: {
+                       struct squashfs_dir_inode_header_2 *inodep = &id.dir;
+                       struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
+
+                       if (msblk->swap) {
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               sinodep, block, offset,
+                                               sizeof(*sinodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
+                       } else
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               inodep, block, offset,
+                                               sizeof(*inodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+                               goto failed_read1;
+
+                       i->i_size = inodep->file_size;
+                       i->i_op = &squashfs_dir_inode_ops_2;
+                       i->i_fop = &squashfs_dir_ops_2;
+                       i->i_mode |= S_IFDIR;
+                       i->i_mtime.tv_sec = inodep->mtime;
+                       i->i_atime.tv_sec = inodep->mtime;
+                       i->i_ctime.tv_sec = inodep->mtime;
+                       SQUASHFS_I(i)->start_block = inodep->start_block;
+                       SQUASHFS_I(i)->offset = inodep->offset;
+                       SQUASHFS_I(i)->u.s2.directory_index_count = 0;
+                       SQUASHFS_I(i)->u.s2.parent_inode = 0;
+
+                       TRACE("Directory inode %x:%x, start_block %x, offset "
+                                       "%x\n", SQUASHFS_INODE_BLK(inode),
+                                       offset, inodep->start_block,
+                                       inodep->offset);
+                       break;
+               }
+               case SQUASHFS_LDIR_TYPE: {
+                       struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
+                       struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
+
+                       if (msblk->swap) {
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               sinodep, block, offset,
+                                               sizeof(*sinodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
+                                               sinodep);
+                       } else
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               inodep, block, offset,
+                                               sizeof(*inodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+                               goto failed_read1;
+
+                       i->i_size = inodep->file_size;
+                       i->i_op = &squashfs_dir_inode_ops_2;
+                       i->i_fop = &squashfs_dir_ops_2;
+                       i->i_mode |= S_IFDIR;
+                       i->i_mtime.tv_sec = inodep->mtime;
+                       i->i_atime.tv_sec = inodep->mtime;
+                       i->i_ctime.tv_sec = inodep->mtime;
+                       SQUASHFS_I(i)->start_block = inodep->start_block;
+                       SQUASHFS_I(i)->offset = inodep->offset;
+                       SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
+                       SQUASHFS_I(i)->u.s2.directory_index_offset =
+                                                               next_offset;
+                       SQUASHFS_I(i)->u.s2.directory_index_count =
+                                                               inodep->i_count;
+                       SQUASHFS_I(i)->u.s2.parent_inode = 0;
+
+                       TRACE("Long directory inode %x:%x, start_block %x, "
+                                       "offset %x\n",
+                                       SQUASHFS_INODE_BLK(inode), offset,
+                                       inodep->start_block, inodep->offset);
+                       break;
+               }
+               case SQUASHFS_SYMLINK_TYPE: {
+                       struct squashfs_symlink_inode_header_2 *inodep =
+                                                               &id.symlink;
+                       struct squashfs_symlink_inode_header_2 *sinodep =
+                                                               &sid.symlink;
+       
+                       if (msblk->swap) {
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               sinodep, block, offset,
+                                               sizeof(*sinodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
+                                                               sinodep);
+                       } else
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               inodep, block, offset,
+                                               sizeof(*inodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                       if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+                               goto failed_read1;
+
+                       i->i_size = inodep->symlink_size;
+                       i->i_op = &page_symlink_inode_operations;
+                       i->i_data.a_ops = &squashfs_symlink_aops;
+                       i->i_mode |= S_IFLNK;
+                       SQUASHFS_I(i)->start_block = next_block;
+                       SQUASHFS_I(i)->offset = next_offset;
+
+                       TRACE("Symbolic link inode %x:%x, start_block %llx, "
+                                       "offset %x\n",
+                                       SQUASHFS_INODE_BLK(inode), offset,
+                                       next_block, next_offset);
+                       break;
+                }
+                case SQUASHFS_BLKDEV_TYPE:
+                case SQUASHFS_CHRDEV_TYPE: {
+                       struct squashfs_dev_inode_header_2 *inodep = &id.dev;
+                       struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
+
+                       if (msblk->swap) {
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               sinodep, block, offset,
+                                               sizeof(*sinodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
+                       } else  
+                               if (!squashfs_get_cached_block(s, (char *)
+                                               inodep, block, offset,
+                                               sizeof(*inodep), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                       if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+                               goto failed_read1;
+
+                       i->i_mode |= (inodeb->inode_type ==
+                                       SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
+                                       S_IFBLK;
+                       init_special_inode(i, i->i_mode,
+                                       old_decode_dev(inodep->rdev));
+
+                       TRACE("Device inode %x:%x, rdev %x\n",
+                                       SQUASHFS_INODE_BLK(inode), offset,
+                                       inodep->rdev);
+                       break;
+                }
+                case SQUASHFS_FIFO_TYPE:
+                case SQUASHFS_SOCKET_TYPE: {
+                       if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+                               goto failed_read1;
+
+                       i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
+                                                       ? S_IFIFO : S_IFSOCK;
+                       init_special_inode(i, i->i_mode, 0);
+                       break;
+                }
+                default:
+                       ERROR("Unknown inode type %d in squashfs_iget!\n",
+                                       inodeb->inode_type);
+                       goto failed_read1;
+       }
+       
+       insert_inode_hash(i);
+       return i;
+
+failed_read:
+       ERROR("Unable to read inode [%x:%x]\n", block, offset);
+
+failed_read1:
+       return NULL;
+}
+
+
+static int get_dir_index_using_offset(struct super_block *s, long long 
+                               *next_block, unsigned int *next_offset,
+                               long long index_start,
+                               unsigned int index_offset, int i_count,
+                               long long f_pos)
+{
+       struct squashfs_sb_info *msblk = s->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+       int i, length = 0;
+       struct squashfs_dir_index_2 index;
+
+       TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
+                                       i_count, (unsigned int) f_pos);
+
+       if (f_pos == 0)
+               goto finish;
+
+       for (i = 0; i < i_count; i++) {
+               if (msblk->swap) {
+                       struct squashfs_dir_index_2 sindex;
+                       squashfs_get_cached_block(s, (char *) &sindex,
+                                       index_start, index_offset,
+                                       sizeof(sindex), &index_start,
+                                       &index_offset);
+                       SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
+               } else
+                       squashfs_get_cached_block(s, (char *) &index,
+                                       index_start, index_offset,
+                                       sizeof(index), &index_start,
+                                       &index_offset);
+
+               if (index.index > f_pos)
+                       break;
+
+               squashfs_get_cached_block(s, NULL, index_start, index_offset,
+                                       index.size + 1, &index_start,
+                                       &index_offset);
+
+               length = index.index;
+               *next_block = index.start_block + sblk->directory_table_start;
+       }
+
+       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+
+finish:
+       return length;
+}
+
+
+static int get_dir_index_using_name(struct super_block *s, long long
+                               *next_block, unsigned int *next_offset,
+                               long long index_start,
+                               unsigned int index_offset, int i_count,
+                               const char *name, int size)
+{
+       struct squashfs_sb_info *msblk = s->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+       int i, length = 0;
+       char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
+       struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
+       char str[SQUASHFS_NAME_LEN + 1];
+
+       TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
+
+       strncpy(str, name, size);
+       str[size] = '\0';
+
+       for (i = 0; i < i_count; i++) {
+               if (msblk->swap) {
+                       struct squashfs_dir_index_2 sindex;
+                       squashfs_get_cached_block(s, (char *) &sindex,
+                                       index_start, index_offset,
+                                       sizeof(sindex), &index_start,
+                                       &index_offset);
+                       SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
+               } else
+                       squashfs_get_cached_block(s, (char *) index,
+                                       index_start, index_offset,
+                                       sizeof(struct squashfs_dir_index_2),
+                                       &index_start, &index_offset);
+
+               squashfs_get_cached_block(s, index->name, index_start,
+                                       index_offset, index->size + 1,
+                                       &index_start, &index_offset);
+
+               index->name[index->size + 1] = '\0';
+
+               if (strcmp(index->name, str) > 0)
+                       break;
+
+               length = index->index;
+               *next_block = index->start_block + sblk->directory_table_start;
+       }
+
+       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+       return length;
+}
+
+               
+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
+{
+       struct inode *i = file->f_dentry->d_inode;
+       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+       long long next_block = SQUASHFS_I(i)->start_block +
+               sblk->directory_table_start;
+       int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
+               dir_count;
+       struct squashfs_dir_header_2 dirh;
+       char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
+       struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+
+       TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
+
+       length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
+                               SQUASHFS_I(i)->u.s2.directory_index_start,
+                               SQUASHFS_I(i)->u.s2.directory_index_offset,
+                               SQUASHFS_I(i)->u.s2.directory_index_count,
+                               file->f_pos);
+
+       while (length < i_size_read(i)) {
+               /* read directory header */
+               if (msblk->swap) {
+                       struct squashfs_dir_header_2 sdirh;
+                       
+                       if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+                                       next_block, next_offset, sizeof(sdirh),
+                                       &next_block, &next_offset))
+                               goto failed_read;
+
+                       length += sizeof(sdirh);
+                       SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
+               } else {
+                       if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+                                       next_block, next_offset, sizeof(dirh),
+                                       &next_block, &next_offset))
+                               goto failed_read;
+
+                       length += sizeof(dirh);
+               }
+
+               dir_count = dirh.count + 1;
+               while (dir_count--) {
+                       if (msblk->swap) {
+                               struct squashfs_dir_entry_2 sdire;
+                               if (!squashfs_get_cached_block(i->i_sb, (char *)
+                                               &sdire, next_block, next_offset,
+                                               sizeof(sdire), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               
+                               length += sizeof(sdire);
+                               SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
+                       } else {
+                               if (!squashfs_get_cached_block(i->i_sb, (char *)
+                                               dire, next_block, next_offset,
+                                               sizeof(*dire), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                               length += sizeof(*dire);
+                       }
+
+                       if (!squashfs_get_cached_block(i->i_sb, dire->name,
+                                               next_block, next_offset,
+                                               dire->size + 1, &next_block,
+                                               &next_offset))
+                               goto failed_read;
+
+                       length += dire->size + 1;
+
+                       if (file->f_pos >= length)
+                               continue;
+
+                       dire->name[dire->size + 1] = '\0';
+
+                       TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
+                                       (unsigned int) dirent, dire->name,
+                                       dire->size + 1, (int) file->f_pos,
+                                       dirh.start_block, dire->offset,
+                                       squashfs_filetype_table[dire->type]);
+
+                       if (filldir(dirent, dire->name, dire->size + 1,
+                                       file->f_pos, SQUASHFS_MK_VFS_INODE(
+                                       dirh.start_block, dire->offset),
+                                       squashfs_filetype_table[dire->type])
+                                       < 0) {
+                               TRACE("Filldir returned less than 0\n");
+                               goto finish;
+                       }
+                       file->f_pos = length;
+                       dirs_read++;
+               }
+       }
+
+finish:
+       return dirs_read;
+
+failed_read:
+       ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+               next_offset);
+       return 0;
+}
+
+
+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
+                               struct nameidata *nd)
+{
+       const unsigned char *name = dentry->d_name.name;
+       int len = dentry->d_name.len;
+       struct inode *inode = NULL;
+       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
+       struct squashfs_super_block *sblk = &msblk->sblk;
+       long long next_block = SQUASHFS_I(i)->start_block +
+                               sblk->directory_table_start;
+       int next_offset = SQUASHFS_I(i)->offset, length = 0,
+                               dir_count;
+       struct squashfs_dir_header_2 dirh;
+       char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
+       struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+       int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
+
+       TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
+
+       if (len > SQUASHFS_NAME_LEN)
+               goto exit_loop;
+
+       length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
+                               SQUASHFS_I(i)->u.s2.directory_index_start,
+                               SQUASHFS_I(i)->u.s2.directory_index_offset,
+                               SQUASHFS_I(i)->u.s2.directory_index_count, name,
+                               len);
+
+       while (length < i_size_read(i)) {
+               /* read directory header */
+               if (msblk->swap) {
+                       struct squashfs_dir_header_2 sdirh;
+                       if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+                                       next_block, next_offset, sizeof(sdirh),
+                                       &next_block, &next_offset))
+                               goto failed_read;
+
+                       length += sizeof(sdirh);
+                       SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
+               } else {
+                       if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+                                       next_block, next_offset, sizeof(dirh),
+                                       &next_block, &next_offset))
+                               goto failed_read;
+
+                       length += sizeof(dirh);
+               }
+
+               dir_count = dirh.count + 1;
+               while (dir_count--) {
+                       if (msblk->swap) {
+                               struct squashfs_dir_entry_2 sdire;
+                               if (!squashfs_get_cached_block(i->i_sb, (char *)
+                                               &sdire, next_block,next_offset,
+                                               sizeof(sdire), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+                               
+                               length += sizeof(sdire);
+                               SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
+                       } else {
+                               if (!squashfs_get_cached_block(i->i_sb, (char *)
+                                               dire, next_block,next_offset,
+                                               sizeof(*dire), &next_block,
+                                               &next_offset))
+                                       goto failed_read;
+
+                               length += sizeof(*dire);
+                       }
+
+                       if (!squashfs_get_cached_block(i->i_sb, dire->name,
+                                       next_block, next_offset, dire->size + 1,
+                                       &next_block, &next_offset))
+                               goto failed_read;
+
+                       length += dire->size + 1;
+
+                       if (sorted && name[0] < dire->name[0])
+                               goto exit_loop;
+
+                       if ((len == dire->size + 1) && !strncmp(name,
+                                               dire->name, len)) {
+                               squashfs_inode_t ino =
+                                       SQUASHFS_MKINODE(dirh.start_block,
+                                       dire->offset);
+
+                               TRACE("calling squashfs_iget for directory "
+                                       "entry %s, inode %x:%x, %lld\n", name,
+                                       dirh.start_block, dire->offset, ino);
+
+                               inode = (msblk->iget)(i->i_sb, ino);
+
+                               goto exit_loop;
+                       }
+               }
+       }
+
+exit_loop:
+       d_add(dentry, inode);
+       return ERR_PTR(0);
+
+failed_read:
+       ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+               next_offset);
+       goto exit_loop;
+}
+
+
+int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
+{
+       struct squashfs_super_block *sblk = &msblk->sblk;
+
+       msblk->iget = squashfs_iget_2;
+       msblk->read_fragment_index_table = read_fragment_index_table_2;
+
+       sblk->bytes_used = sblk->bytes_used_2;
+       sblk->uid_start = sblk->uid_start_2;
+       sblk->guid_start = sblk->guid_start_2;
+       sblk->inode_table_start = sblk->inode_table_start_2;
+       sblk->directory_table_start = sblk->directory_table_start_2;
+       sblk->fragment_table_start = sblk->fragment_table_start_2;
+
+       return 1;
+}
diff --git a/include/Kbuild b/include/Kbuild
new file mode 100644 (file)
index 0000000..2d03f99
--- /dev/null
@@ -0,0 +1,9 @@
+header-y += asm-generic/
+header-y += linux/
+header-y += scsi/
+header-y += sound/
+header-y += mtd/
+header-y += rdma/
+header-y += video/
+
+header-y += asm-$(ARCH)/
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
new file mode 100644 (file)
index 0000000..1049f2a
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __ACPI_NUMA_H
+#define __ACPI_NUMA_H
+
+#ifdef CONFIG_ACPI_NUMA
+#include <linux/kernel.h>
+
+/* Proximity bitmap length */
+#if MAX_NUMNODES > 256
+#define MAX_PXM_DOMAINS MAX_NUMNODES
+#else
+#define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */
+#endif
+
+extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS];
+extern int __cpuinitdata node_to_pxm_map[MAX_NUMNODES];
+
+extern int __cpuinit pxm_to_node(int);
+extern int __cpuinit node_to_pxm(int);
+extern int __cpuinit acpi_map_pxm_to_node(int);
+extern void __cpuinit acpi_unmap_pxm_to_node(int);
+
+#endif                         /* CONFIG_ACPI_NUMA */
+#endif                         /* __ACP_NUMA_H */
diff --git a/include/asm-alpha/Kbuild b/include/asm-alpha/Kbuild
new file mode 100644 (file)
index 0000000..b7c8f18
--- /dev/null
@@ -0,0 +1,11 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += gentrap.h
+header-y += regdef.h
+header-y += pal.h
+header-y += reg.h
+
+unifdef-y += console.h
+unifdef-y += fpu.h
+unifdef-y += sysinfo.h
+unifdef-y += compiler.h
diff --git a/include/asm-arm/Kbuild b/include/asm-arm/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h
new file mode 100644 (file)
index 0000000..bff5ea4
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_spi.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Serial Peripheral Interface (SPI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91RM9200_SPI_H
+#define AT91RM9200_SPI_H
+
+#define AT91_SPI_CR                    0x00            /* Control Register */
+#define                AT91_SPI_SPIEN          (1 <<  0)               /* SPI Enable */
+#define                AT91_SPI_SPIDIS         (1 <<  1)               /* SPI Disable */
+#define                AT91_SPI_SWRST          (1 <<  7)               /* SPI Software Reset */
+#define                AT91_SPI_LASTXFER       (1 << 24)               /* Last Transfer [SAM9261 only] */
+
+#define AT91_SPI_MR                    0x04            /* Mode Register */
+#define                AT91_SPI_MSTR           (1    <<  0)            /* Master/Slave Mode */
+#define                AT91_SPI_PS             (1    <<  1)            /* Peripheral Select */
+#define                        AT91_SPI_PS_FIXED       (0 << 1)
+#define                        AT91_SPI_PS_VARIABLE    (1 << 1)
+#define                AT91_SPI_PCSDEC         (1    <<  2)            /* Chip Select Decode */
+#define                AT91_SPI_DIV32          (1    <<  3)            /* Clock Selection */
+#define                AT91_SPI_MODFDIS        (1    <<  4)            /* Mode Fault Detection */
+#define                AT91_SPI_LLB            (1    <<  7)            /* Local Loopback Enable */
+#define                AT91_SPI_PCS            (0xf  << 16)            /* Peripheral Chip Select */
+#define                AT91_SPI_DLYBCS         (0xff << 24)            /* Delay Between Chip Selects */
+
+#define AT91_SPI_RDR           0x08                    /* Receive Data Register */
+#define                AT91_SPI_RD             (0xffff <<  0)          /* Receive Data */
+#define                AT91_SPI_PCS            (0xf    << 16)          /* Peripheral Chip Select */
+
+#define AT91_SPI_TDR           0x0c                    /* Transmit Data Register */
+#define                AT91_SPI_TD             (0xffff <<  0)          /* Transmit Data */
+#define                AT91_SPI_PCS            (0xf    << 16)          /* Peripheral Chip Select */
+#define                AT91_SPI_LASTXFER       (1      << 24)          /* Last Transfer [SAM9261 only] */
+
+#define AT91_SPI_SR            0x10                    /* Status Register */
+#define                AT91_SPI_RDRF           (1 <<  0)               /* Receive Data Register Full */
+#define                AT91_SPI_TDRE           (1 <<  1)               /* Transmit Data Register Full */
+#define                AT91_SPI_MODF           (1 <<  2)               /* Mode Fault Error */
+#define                AT91_SPI_OVRES          (1 <<  3)               /* Overrun Error Status */
+#define                AT91_SPI_ENDRX          (1 <<  4)               /* End of RX buffer */
+#define                AT91_SPI_ENDTX          (1 <<  5)               /* End of TX buffer */
+#define                AT91_SPI_RXBUFF         (1 <<  6)               /* RX Buffer Full */
+#define                AT91_SPI_TXBUFE         (1 <<  7)               /* TX Buffer Empty */
+#define                AT91_SPI_NSSR           (1 <<  8)               /* NSS Rising [SAM9261 only] */
+#define                AT91_SPI_TXEMPTY        (1 <<  9)               /* Transmission Register Empty [SAM9261 only] */
+#define                AT91_SPI_SPIENS         (1 << 16)               /* SPI Enable Status */
+
+#define AT91_SPI_IER           0x14                    /* Interrupt Enable Register */
+#define AT91_SPI_IDR           0x18                    /* Interrupt Disable Register */
+#define AT91_SPI_IMR           0x1c                    /* Interrupt Mask Register */
+
+#define AT91_SPI_CSR(n)                (0x30 + ((n) * 4))      /* Chip Select Registers 0-3 */
+#define                AT91_SPI_CPOL           (1    <<  0)            /* Clock Polarity */
+#define                AT91_SPI_NCPHA          (1    <<  1)            /* Clock Phase */
+#define                AT91_SPI_CSAAT          (1    <<  3)            /* Chip Select Active After Transfer [SAM9261 only] */
+#define                AT91_SPI_BITS           (0xf  <<  4)            /* Bits Per Transfer */
+#define                        AT91_SPI_BITS_8         (0 << 4)
+#define                        AT91_SPI_BITS_9         (1 << 4)
+#define                        AT91_SPI_BITS_10        (2 << 4)
+#define                        AT91_SPI_BITS_11        (3 << 4)
+#define                        AT91_SPI_BITS_12        (4 << 4)
+#define                        AT91_SPI_BITS_13        (5 << 4)
+#define                        AT91_SPI_BITS_14        (6 << 4)
+#define                        AT91_SPI_BITS_15        (7 << 4)
+#define                        AT91_SPI_BITS_16        (8 << 4)
+#define                AT91_SPI_SCBR           (0xff <<  8)            /* Serial Clock Baud Rate */
+#define                AT91_SPI_DLYBS          (0xff << 16)            /* Delay before SPCK */
+#define                AT91_SPI_DLYBCT         (0xff << 24)            /* Delay between Consecutive Transfers */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h
new file mode 100644 (file)
index 0000000..ac88022
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Serial Synchronous Controller (SSC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91RM9200_SSC_H
+#define AT91RM9200_SSC_H
+
+#define AT91_SSC_CR            0x00    /* Control Register */
+#define                AT91_SSC_RXEN           (1 <<  0)       /* Receive Enable */
+#define                AT91_SSC_RXDIS          (1 <<  1)       /* Receive Disable */
+#define                AT91_SSC_TXEN           (1 <<  8)       /* Transmit Enable */
+#define                AT91_SSC_TXDIS          (1 <<  9)       /* Transmit Disable */
+#define                AT91_SSC_SWRST          (1 << 15)       /* Software Reset */
+
+#define AT91_SSC_CMR           0x04    /* Clock Mode Register */
+#define                AT91_SSC_CMR_DIV        (0xfff << 0)    /* Clock Divider */
+
+#define AT91_SSC_RCMR          0x10    /* Receive Clock Mode Register */
+#define                AT91_SSC_CKS            (3    <<  0)    /* Clock Selection */
+#define                        AT91_SSC_CKS_DIV                (0 << 0)
+#define                        AT91_SSC_CKS_CLOCK              (1 << 0)
+#define                        AT91_SSC_CKS_PIN                (2 << 0)
+#define                AT91_SSC_CKO            (7    <<  2)    /* Clock Output Mode Selection */
+#define                        AT91_SSC_CKO_NONE               (0 << 2)
+#define                        AT91_SSC_CKO_CONTINUOUS         (1 << 2)
+#define                AT91_SSC_CKI            (1    <<  5)    /* Clock Inversion */
+#define                        AT91_SSC_CKI_FALLING            (0 << 5)
+#define                        AT91_SSC_CK_RISING              (1 << 5)
+#define                AT91_SSC_START          (0xf  <<  8)    /* Start Selection */
+#define                        AT91_SSC_START_CONTINUOUS       (0 << 8)
+#define                        AT91_SSC_START_TX_RX            (1 << 8)
+#define                        AT91_SSC_START_LOW_RF           (2 << 8)
+#define                        AT91_SSC_START_HIGH_RF          (3 << 8)
+#define                        AT91_SSC_START_FALLING_RF       (4 << 8)
+#define                        AT91_SSC_START_RISING_RF        (5 << 8)
+#define                        AT91_SSC_START_LEVEL_RF         (6 << 8)
+#define                        AT91_SSC_START_EDGE_RF          (7 << 8)
+#define                AT91_SSC_STTDLY         (0xff << 16)    /* Start Delay */
+#define                AT91_SSC_PERIOD         (0xff << 24)    /* Period Divider Selection */
+
+#define AT91_SSC_RFMR          0x14    /* Receive Frame Mode Register */
+#define                AT91_SSC_DATALEN        (0x1f <<  0)    /* Data Length */
+#define                AT91_SSC_LOOP           (1    <<  5)    /* Loop Mode */
+#define                AT91_SSC_MSBF           (1    <<  7)    /* Most Significant Bit First */
+#define                AT91_SSC_DATNB          (0xf  <<  8)    /* Data Number per Frame */
+#define                AT91_SSC_FSLEN          (0xf  << 16)    /* Frame Sync Length */
+#define                AT91_SSC_FSOS           (7    << 20)    /* Frame Sync Output Selection */
+#define                        AT91_SSC_FSOS_NONE              (0 << 20)
+#define                        AT91_SSC_FSOS_NEGATIVE          (1 << 20)
+#define                        AT91_SSC_FSOS_POSITIVE          (2 << 20)
+#define                        AT91_SSC_FSOS_LOW               (3 << 20)
+#define                        AT91_SSC_FSOS_HIGH              (4 << 20)
+#define                        AT91_SSC_FSOS_TOGGLE            (5 << 20)
+#define                AT91_SSC_FSEDGE         (1    << 24)    /* Frame Sync Edge Detection */
+#define                        AT91_SSC_FSEDGE_POSITIVE        (0 << 24)
+#define                        AT91_SSC_FSEDGE_NEGATIVE        (1 << 24)
+
+#define AT91_SSC_TCMR          0x18    /* Transmit Clock Mode Register */
+#define AT91_SSC_TFMR          0x1c    /* Transmit Fram Mode Register */
+#define                AT91_SSC_DATDEF         (1 <<  5)       /* Data Default Value */
+#define                AT91_SSC_FSDEN          (1 << 23)       /* Frame Sync Data Enable */
+
+#define AT91_SSC_RHR           0x20    /* Receive Holding Register */
+#define AT91_SSC_THR           0x24    /* Transmit Holding Register */
+#define AT91_SSC_RSHR          0x30    /* Receive Sync Holding Register */
+#define AT91_SSC_TSHR          0x34    /* Transmit Sync Holding Register */
+
+#define AT91_SSC_SR            0x40    /* Status Register */
+#define                AT91_SSC_TXRDY          (1 <<  0)       /* Transmit Ready */
+#define                AT91_SSC_TXEMPTY        (1 <<  1)       /* Transmit Empty */
+#define                AT91_SSC_ENDTX          (1 <<  2)       /* End of Transmission */
+#define                AT91_SSC_TXBUFE         (1 <<  3)       /* Transmit Buffer Empty */
+#define                AT91_SSC_RXRDY          (1 <<  4)       /* Receive Ready */
+#define                AT91_SSC_OVRUN          (1 <<  5)       /* Receive Overrun */
+#define                AT91_SSC_ENDRX          (1 <<  6)       /* End of Reception */
+#define                AT91_SSC_RXBUFF         (1 <<  7)       /* Receive Buffer Full */
+#define                AT91_SSC_TXSYN          (1 << 10)       /* Transmit Sync */
+#define                AT91_SSC_RXSYN          (1 << 11)       /* Receive Sync */
+#define                AT91_SSC_TXENA          (1 << 16)       /* Transmit Enable */
+#define                AT91_SSC_RXENA          (1 << 17)       /* Receive Enable */
+
+#define AT91_SSC_IER           0x44    /* Interrupt Enable Register */
+#define AT91_SSC_IDR           0x48    /* Interrupt Disable Register */
+#define AT91_SSC_IMR           0x4c    /* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
new file mode 100644 (file)
index 0000000..f4da752
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Timer/Counter Unit (TC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91RM9200_TC_H
+#define AT91RM9200_TC_H
+
+#define AT91_TC_BCR            0xc0            /* TC Block Control Register */
+#define                AT91_TC_SYNC            (1 << 0)        /* Synchro Command */
+
+#define AT91_TC_BMR            0xc4            /* TC Block Mode Register */
+#define                AT91_TC_TC0XC0S         (3 << 0)        /* External Clock Signal 0 Selection */
+#define                        AT91_TC_TC0XC0S_TCLK0           (0 << 0)
+#define                        AT91_TC_TC0XC0S_NONE            (1 << 0)
+#define                        AT91_TC_TC0XC0S_TIOA1           (2 << 0)
+#define                        AT91_TC_TC0XC0S_TIOA2           (3 << 0)
+#define                AT91_TC_TC1XC1S         (3 << 2)        /* External Clock Signal 1 Selection */
+#define                        AT91_TC_TC1XC1S_TCLK1           (0 << 2)
+#define                        AT91_TC_TC1XC1S_NONE            (1 << 2)
+#define                        AT91_TC_TC1XC1S_TIOA0           (2 << 2)
+#define                        AT91_TC_TC1XC1S_TIOA2           (3 << 2)
+#define                AT91_TC_TC2XC2S         (3 << 4)        /* External Clock Signal 2 Selection */
+#define                        AT91_TC_TC2XC2S_TCLK2           (0 << 4)
+#define                        AT91_TC_TC2XC2S_NONE            (1 << 4)
+#define                        AT91_TC_TC2XC2S_TIOA0           (2 << 4)
+#define                        AT91_TC_TC2XC2S_TIOA1           (3 << 4)
+
+
+#define AT91_TC_CCR            0x00            /* Channel Control Register */
+#define                AT91_TC_CLKEN           (1 << 0)        /* Counter Clock Enable Command */
+#define                AT91_TC_CLKDIS          (1 << 1)        /* Counter CLock Disable Command */
+#define                AT91_TC_SWTRG           (1 << 2)        /* Software Trigger Command */
+
+#define AT91_TC_CMR            0x04            /* Channel Mode Register */
+#define                AT91_TC_TCCLKS          (7 << 0)        /* Capture/Waveform Mode: Clock Selection */
+#define                        AT91_TC_TIMER_CLOCK1            (0 << 0)
+#define                        AT91_TC_TIMER_CLOCK2            (1 << 0)
+#define                        AT91_TC_TIMER_CLOCK3            (2 << 0)
+#define                        AT91_TC_TIMER_CLOCK4            (3 << 0)
+#define                        AT91_TC_TIMER_CLOCK5            (4 << 0)
+#define                        AT91_TC_XC0                     (5 << 0)
+#define                        AT91_TC_XC1                     (6 << 0)
+#define                        AT91_TC_XC2                     (7 << 0)
+#define                AT91_TC_CLKI            (1 << 3)        /* Capture/Waveform Mode: Clock Invert */
+#define                AT91_TC_BURST           (3 << 4)        /* Capture/Waveform Mode: Burst Signal Selection */
+#define                AT91_TC_LDBSTOP         (1 << 6)        /* Capture Mode: Counter Clock Stopped with TB Loading */
+#define                AT91_TC_LDBDIS          (1 << 7)        /* Capture Mode: Counter Clock Disable with RB Loading */
+#define                AT91_TC_ETRGEDG         (3 << 8)        /* Capture Mode: External Trigger Edge Selection */
+#define                AT91_TC_ABETRG          (1 << 10)       /* Capture Mode: TIOA or TIOB External Trigger Selection */
+#define                AT91_TC_CPCTRG          (1 << 14)       /* Capture Mode: RC Compare Trigger Enable */
+#define                AT91_TC_WAVE            (1 << 15)       /* Capture/Waveform mode */
+#define                AT91_TC_LDRA            (3 << 16)       /* Capture Mode: RA Loading Selection */
+#define                AT91_TC_LDRB            (3 << 18)       /* Capture Mode: RB Loading Selection */
+
+#define                AT91_TC_CPCSTOP         (1 <<  6)       /* Waveform Mode: Counter Clock Stopped with RC Compare */
+#define                AT91_TC_CPCDIS          (1 <<  7)       /* Waveform Mode: Counter Clock Disable with RC Compare */
+#define                AT91_TC_EEVTEDG         (3 <<  8)       /* Waveform Mode: External Event Edge Selection */
+#define                        AT91_TC_EEVTEDG_NONE            (0 << 8)
+#define                        AT91_TC_EEVTEDG_RISING          (1 << 8)
+#define                        AT91_TC_EEVTEDG_FALLING         (2 << 8)
+#define                        AT91_TC_EEVTEDG_BOTH            (3 << 8)
+#define                AT91_TC_EEVT            (3 << 10)       /* Waveform Mode: External Event Selection */
+#define                        AT91_TC_EEVT_TIOB               (0 << 10)
+#define                        AT91_TC_EEVT_XC0                (1 << 10)
+#define                        AT91_TC_EEVT_XC1                (2 << 10)
+#define                        AT91_TC_EEVT_XC2                (3 << 10)
+#define                AT91_TC_ENETRG          (1 << 12)       /* Waveform Mode: External Event Trigger Enable */
+#define                AT91_TC_WAVESEL         (3 << 13)       /* Waveform Mode: Waveform Selection */
+#define                        AT91_TC_WAVESEL_UP              (0 << 13)
+#define                        AT91_TC_WAVESEL_UP_AUTO         (2 << 13)
+#define                        AT91_TC_WAVESEL_UPDOWN          (1 << 13)
+#define                        AT91_TC_WAVESEL_UPDOWN_AUTO     (3 << 13)
+#define                AT91_TC_ACPA            (3 << 16)       /* Waveform Mode: RA Compare Effect on TIOA */
+#define                        AT91_TC_ACPA_NONE               (0 << 16)
+#define                        AT91_TC_ACPA_SET                (1 << 16)
+#define                        AT91_TC_ACPA_CLEAR              (2 << 16)
+#define                        AT91_TC_ACPA_TOGGLE             (3 << 16)
+#define                AT91_TC_ACPC            (3 << 18)       /* Waveform Mode: RC Compre Effect on TIOA */
+#define                        AT91_TC_ACPC_NONE               (0 << 18)
+#define                        AT91_TC_ACPC_SET                (1 << 18)
+#define                        AT91_TC_ACPC_CLEAR              (2 << 18)
+#define                        AT91_TC_ACPC_TOGGLE             (3 << 18)
+#define                AT91_TC_AEEVT           (3 << 20)       /* Waveform Mode: External Event Effect on TIOA */
+#define                        AT91_TC_AEEVT_NONE              (0 << 20)
+#define                        AT91_TC_AEEVT_SET               (1 << 20)
+#define                        AT91_TC_AEEVT_CLEAR             (2 << 20)
+#define                        AT91_TC_AEEVT_TOGGLE            (3 << 20)
+#define                AT91_TC_ASWTRG          (3 << 22)       /* Waveform Mode: Software Trigger Effect on TIOA */
+#define                        AT91_TC_ASWTRG_NONE             (0 << 22)
+#define                        AT91_TC_ASWTRG_SET              (1 << 22)
+#define                        AT91_TC_ASWTRG_CLEAR            (2 << 22)
+#define                        AT91_TC_ASWTRG_TOGGLE           (3 << 22)
+#define                AT91_TC_BCPB            (3 << 24)       /* Waveform Mode: RB Compare Effect on TIOB */
+#define                        AT91_TC_BCPB_NONE               (0 << 24)
+#define                        AT91_TC_BCPB_SET                (1 << 24)
+#define                        AT91_TC_BCPB_CLEAR              (2 << 24)
+#define                        AT91_TC_BCPB_TOGGLE             (3 << 24)
+#define                AT91_TC_BCPC            (3 << 26)       /* Waveform Mode: RC Compare Effect on TIOB */
+#define                        AT91_TC_BCPC_NONE               (0 << 26)
+#define                        AT91_TC_BCPC_SET                (1 << 26)
+#define                        AT91_TC_BCPC_CLEAR              (2 << 26)
+#define                        AT91_TC_BCPC_TOGGLE             (3 << 26)
+#define                AT91_TC_BEEVT           (3 << 28)       /* Waveform Mode: External Event Effect on TIOB */
+#define                        AT91_TC_BEEVT_NONE              (0 << 28)
+#define                        AT91_TC_BEEVT_SET               (1 << 28)
+#define                        AT91_TC_BEEVT_CLEAR             (2 << 28)
+#define                        AT91_TC_BEEVT_TOGGLE            (3 << 28)
+#define                AT91_TC_BSWTRG          (3 << 30)       /* Waveform Mode: Software Trigger Effect on TIOB */
+#define                        AT91_TC_BSWTRG_NONE             (0 << 30)
+#define                        AT91_TC_BSWTRG_SET              (1 << 30)
+#define                        AT91_TC_BSWTRG_CLEAR            (2 << 30)
+#define                        AT91_TC_BSWTRG_TOGGLE           (3 << 30)
+
+#define AT91_TC_CV             0x10            /* Counter Value */
+#define AT91_TC_RA             0x14            /* Register A */
+#define AT91_TC_RB             0x18            /* Register B */
+#define AT91_TC_RC             0x1c            /* Register C */
+
+#define AT91_TC_SR             0x20            /* Status Register */
+#define                AT91_TC_COVFS           (1 <<  0)       /* Counter Overflow Status */
+#define                AT91_TC_LOVRS           (1 <<  1)       /* Load Overrun Status */
+#define                AT91_TC_CPAS            (1 <<  2)       /* RA Compare Status */
+#define                AT91_TC_CPBS            (1 <<  3)       /* RB Compare Status */
+#define                AT91_TC_CPCS            (1 <<  4)       /* RC Compare Status */
+#define                AT91_TC_LDRAS           (1 <<  5)       /* RA Loading Status */
+#define                AT91_TC_LDRBS           (1 <<  6)       /* RB Loading Status */
+#define                AT91_TC_ETRGS           (1 <<  7)       /* External Trigger Status */
+#define                AT91_TC_CLKSTA          (1 << 16)       /* Clock Enabling Status */
+#define                AT91_TC_MTIOA           (1 << 17)       /* TIOA Mirror */
+#define                AT91_TC_MTIOB           (1 << 18)       /* TIOB Mirror */
+
+#define AT91_TC_IER            0x24            /* Interrupt Enable Register */
+#define AT91_TC_IDR            0x28            /* Interrupt Disable Register */
+#define AT91_TC_IMR            0x2c            /* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
new file mode 100644 (file)
index 0000000..951e3f6
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * USB Device Port (UDP) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 AT91RM9200_UDP_H
+#define AT91RM9200_UDP_H
+
+#define AT91_UDP_FRM_NUM       0x00            /* Frame Number Register */
+#define                AT91_UDP_NUM            (0x7ff <<  0)           /* Frame Number */
+#define                AT91_UDP_FRM_ERR        (1     << 16)           /* Frame Error */
+#define                AT91_UDP_FRM_OK         (1     << 17)           /* Frame OK */
+
+#define AT91_UDP_GLB_STAT      0x04            /* Global State Register */
+#define                AT91_UDP_FADDEN         (1 <<  0)               /* Function Address Enable */
+#define                AT91_UDP_CONFG          (1 <<  1)               /* Configured */
+#define                AT91_UDP_ESR            (1 <<  2)               /* Enable Send Resume */
+#define                AT91_UDP_RSMINPR        (1 <<  3)               /* Resume has been sent */
+#define                AT91_UDP_RMWUPE         (1 <<  4)               /* Remote Wake Up Enable */
+
+#define AT91_UDP_FADDR         0x08            /* Function Address Register */
+#define                AT91_UDP_FADD           (0x7f << 0)             /* Function Address Value */
+#define                AT91_UDP_FEN            (1    << 8)             /* Function Enable */
+
+#define AT91_UDP_IER           0x10            /* Interrupt Enable Register */
+#define AT91_UDP_IDR           0x14            /* Interrupt Disable Register */
+#define AT91_UDP_IMR           0x18            /* Interrupt Mask Register */
+
+#define AT91_UDP_ISR           0x1c            /* Interrupt Status Register */
+#define                AT91_UDP_EP(n)          (1 << (n))              /* Endpoint Interrupt Status */
+#define                AT91_UDP_RXSUSP         (1 <<  8)               /* USB Suspend Interrupt Status */
+#define                AT91_UDP_RXRSM          (1 <<  9)               /* USB Resume Interrupt Status */
+#define                AT91_UDP_EXTRSM         (1 << 10)               /* External Resume Interrupt Status */
+#define                AT91_UDP_SOFINT         (1 << 11)               /* Start of Frame Interrupt Status */
+#define                AT91_UDP_ENDBUSRES      (1 << 12)               /* End of Bus Reset Interrpt Status */
+#define                AT91_UDP_WAKEUP         (1 << 13)               /* USB Wakeup Interrupt Status */
+
+#define AT91_UDP_ICR           0x20            /* Interrupt Clear Register */
+#define AT91_UDP_RST_EP                0x28            /* Reset Endpoint Register */
+
+#define AT91_UDP_CSR(n)                (0x30 + ((n) * 4))      /* Endpoint Control/Status Registers 0-7 */
+#define                AT91_UDP_TXCOMP         (1 <<  0)               /* Generates IN packet with data previously written in DPR */
+#define                AT91_UDP_RX_DATA_BK0    (1 <<  1)               /* Receive Data Bank 0 */
+#define                AT91_UDP_RXSETUP        (1 <<  2)               /* Send STALL to the host */
+#define                AT91_UDP_STALLSENT      (1 <<  3)               /* Stall Sent / Isochronous error (Isochronous endpoints) */
+#define                AT91_UDP_TXPKTRDY       (1 <<  4)               /* Transmit Packet Ready */
+#define                AT91_UDP_FORCESTALL     (1 <<  5)               /* Force Stall */
+#define                AT91_UDP_RX_DATA_BK1    (1 <<  6)               /* Receive Data Bank 1 */
+#define                AT91_UDP_DIR            (1 <<  7)               /* Transfer Direction */
+#define                AT91_UDP_EPTYPE         (7 <<  8)               /* Endpoint Type */
+#define                        AT91_UDP_EPTYPE_CTRL            (0 <<  8)
+#define                        AT91_UDP_EPTYPE_ISO_OUT         (1 <<  8)
+#define                        AT91_UDP_EPTYPE_BULK_OUT        (2 <<  8)
+#define                        AT91_UDP_EPTYPE_INT_OUT         (3 <<  8)
+#define                        AT91_UDP_EPTYPE_ISO_IN          (5 <<  8)
+#define                        AT91_UDP_EPTYPE_BULK_IN         (6 <<  8)
+#define                        AT91_UDP_EPTYPE_INT_IN          (7 <<  8)
+#define                AT91_UDP_DTGLE          (1 << 11)               /* Data Toggle */
+#define                AT91_UDP_EPEDS          (1 << 15)               /* Endpoint Enable/Disable */
+#define                AT91_UDP_RXBYTECNT      (0x7ff << 16)           /* Number of bytes in FIFO */
+
+#define AT91_UDP_FDR(n)                (0x50 + ((n) * 4))      /* Endpoint FIFO Data Registers 0-7 */
+
+#define AT91_UDP_TXVC          0x74            /* Transceiver Control Register */
+#define                AT91_UDP_TXVC_TXVDIS    (1 << 8)                /* Transceiver Disable */
+
+#endif
diff --git a/include/asm-arm/arch-lh7a40x/clocks.h b/include/asm-arm/arch-lh7a40x/clocks.h
new file mode 100644 (file)
index 0000000..7d0ba18
--- /dev/null
@@ -0,0 +1,18 @@
+/* include/asm-arm/arch-lh7a40x/clocks.h
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_ARCH_CLOCKS_H
+#define __ASM_ARCH_CLOCKS_H
+
+unsigned int fclkfreq_get (void);
+unsigned int hclkfreq_get (void);
+unsigned int pclkfreq_get (void);
+
+#endif  /* _ASM_ARCH_CLOCKS_H */
diff --git a/include/asm-arm/arch-lh7a40x/ssp.h b/include/asm-arm/arch-lh7a40x/ssp.h
new file mode 100644 (file)
index 0000000..132b1c4
--- /dev/null
@@ -0,0 +1,71 @@
+/* ssp.h
+     $Id$
+
+   written by Marc Singer
+   6 Dec 2004
+
+   Copyright (C) 2004 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   This SSP header is available throughout the kernel, for this
+   machine/architecture, because drivers that use it may be dispersed.
+
+   This file was cloned from the 7952x implementation.  It would be
+   better to share them, but we're taking an easier approach for the
+   time being.
+
+*/
+
+#if !defined (__SSP_H__)
+#    define   __SSP_H__
+
+/* ----- Includes */
+
+/* ----- Types */
+
+struct ssp_driver {
+       int  (*init)            (void);
+       void (*exit)            (void);
+       void (*acquire)         (void);
+       void (*release)         (void);
+       int  (*configure)       (int device, int mode, int speed,
+                                int frame_size_write, int frame_size_read);
+       void (*chip_select)     (int enable);
+       void (*set_callbacks)   (void* handle,
+                                irqreturn_t (*callback_tx)(void*),
+                                irqreturn_t (*callback_rx)(void*));
+       void (*enable)          (void);
+       void (*disable)         (void);
+//     int  (*save_state)      (void*);
+//     void (*restore_state)   (void*);
+       int  (*read)            (void);
+       int  (*write)           (u16 data);
+       int  (*write_read)      (u16 data);
+       void (*flush)           (void);
+       void (*write_async)     (void* pv, size_t cb);
+       size_t (*write_pos)     (void);
+};
+
+       /* These modes are only available on the LH79524 */
+#define SSP_MODE_SPI           (1)
+#define SSP_MODE_SSI           (2)
+#define SSP_MODE_MICROWIRE     (3)
+#define SSP_MODE_I2S           (4)
+
+       /* CPLD SPI devices */
+#define DEVICE_EEPROM  0       /* Configuration eeprom */
+#define DEVICE_MAC     1       /* MAC eeprom (LPD79524) */
+#define DEVICE_CODEC   2       /* Audio codec */
+#define DEVICE_TOUCH   3       /* Touch screen (LPD79520) */
+
+/* ----- Globals */
+
+/* ----- Prototypes */
+
+//extern struct ssp_driver lh79520_i2s_driver;
+extern struct ssp_driver lh7a400_cpld_ssp_driver;
+
+#endif  /* __SSP_H__ */
diff --git a/include/asm-arm/arch-netx/debug-macro.S b/include/asm-arm/arch-netx/debug-macro.S
new file mode 100644 (file)
index 0000000..a940d0e
--- /dev/null
@@ -0,0 +1,38 @@
+/* linux/include/asm-arm/arch-netx/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can 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 "hardware.h"
+
+               .macro  addruart,rx
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1                 @ MMU enabled?
+               moveq   \rx, #0x00100000                @ physical
+               movne   \rx, #io_p2v(0x00100000)        @ virtual
+               orr     \rx, \rx, #0x00000a00
+               .endm
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #0]
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #0x18]
+               tst     \rd, #(1 << 3)
+               bne     1002b
+               .endm
+
+               .macro  waituart,rd,rx
+1001:          ldr     \rd, [\rx, #0x18]
+               tst     \rd, #(1 << 3)
+               bne     1001b
+               .endm
diff --git a/include/asm-arm/arch-netx/dma.h b/include/asm-arm/arch-netx/dma.h
new file mode 100644 (file)
index 0000000..4eda5fe
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-netx/dma.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#define MAX_DMA_CHANNELS 0
+#define MAX_DMA_ADDRESS ~0
diff --git a/include/asm-arm/arch-netx/entry-macro.S b/include/asm-arm/arch-netx/entry-macro.S
new file mode 100644 (file)
index 0000000..658df4d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * include/asm-arm/arch-netx/entry-macro.S
+ *
+ * Low-level IRQ helper macros for Hilscher netX based platforms
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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 <asm/hardware.h>
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+               mov     \base, #io_p2v(0x00100000)
+               add     \base, \base, #0x000ff000
+
+               ldr     \irqstat, [\base, #0]
+               clz     \irqnr, \irqstat
+               rsb     \irqnr, \irqnr, #31
+               cmp     \irqstat, #0
+               .endm
+
diff --git a/include/asm-arm/arch-netx/eth.h b/include/asm-arm/arch-netx/eth.h
new file mode 100644 (file)
index 0000000..643c90e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-netx/eth.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#ifndef ASMARM_ARCH_ETH_H
+#define ASMARM_ARCH_ETH_H
+
+struct netxeth_platform_data {
+       unsigned int xcno;      /* number of xmac/xpec engine this eth uses */
+};
+
+#endif
diff --git a/include/asm-arm/arch-netx/hardware.h b/include/asm-arm/arch-netx/hardware.h
new file mode 100644 (file)
index 0000000..7786c45
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-netx/hardware.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#define NETX_IO_PHYS   0x00100000
+#define NETX_IO_VIRT   0xe0000000
+#define NETX_IO_SIZE   0x00100000
+
+#define SRAM_INTERNAL_PHYS_0 0x00000
+#define SRAM_INTERNAL_PHYS_1 0x08000
+#define SRAM_INTERNAL_PHYS_2 0x10000
+#define SRAM_INTERNAL_PHYS_3 0x18000
+#define SRAM_INTERNAL_PHYS(no) ((no) * 0x8000)
+
+#define XPEC_MEM_SIZE 0x4000
+#define XMAC_MEM_SIZE 0x1000
+#define SRAM_MEM_SIZE 0x8000
+
+#define io_p2v(x) ((x) - NETX_IO_PHYS + NETX_IO_VIRT)
+#define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS)
+
+#endif
diff --git a/include/asm-arm/arch-netx/io.h b/include/asm-arm/arch-netx/io.h
new file mode 100644 (file)
index 0000000..a7a53f8
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  linux/include/asm-arm/arch-netx/io.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)         ((void __iomem *)(a))
+#define __mem_pci(a)            (a)
+
+#endif
diff --git a/include/asm-arm/arch-netx/irqs.h b/include/asm-arm/arch-netx/irqs.h
new file mode 100644 (file)
index 0000000..a487dc6
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * include/asm-arm/arch-netx/irqs.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#define NETX_IRQ_VIC_START   0
+#define NETX_IRQ_SOFTINT     0
+#define NETX_IRQ_TIMER0      1
+#define NETX_IRQ_TIMER1      2
+#define NETX_IRQ_TIMER2      3
+#define NETX_IRQ_SYSTIME_NS  4
+#define NETX_IRQ_SYSTIME_S   5
+#define NETX_IRQ_GPIO_15     6
+#define NETX_IRQ_WATCHDOG    7
+#define NETX_IRQ_UART0       8
+#define NETX_IRQ_UART1       9
+#define NETX_IRQ_UART2      10
+#define NETX_IRQ_USB        11
+#define NETX_IRQ_SPI        12
+#define NETX_IRQ_I2C        13
+#define NETX_IRQ_LCD        14
+#define NETX_IRQ_HIF        15
+#define NETX_IRQ_GPIO_0_14  16
+#define NETX_IRQ_XPEC0      17
+#define NETX_IRQ_XPEC1      18
+#define NETX_IRQ_XPEC2      19
+#define NETX_IRQ_XPEC3      20
+#define NETX_IRQ_XPEC(no)   (17 + (no))
+#define NETX_IRQ_MSYNC0     21
+#define NETX_IRQ_MSYNC1     22
+#define NETX_IRQ_MSYNC2     23
+#define NETX_IRQ_MSYNC3     24
+#define NETX_IRQ_IRQ_PHY    25
+#define NETX_IRQ_ISO_AREA   26
+/* int 27 is reserved */
+/* int 28 is reserved */
+#define NETX_IRQ_TIMER3     29
+#define NETX_IRQ_TIMER4     30
+/* int 31 is reserved */
+
+#define NETX_IRQS 32
+
+/* for multiplexed irqs on gpio 0..14 */
+#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x))
+#define NETX_IRQ_GPIO_LAST NETX_IRQ_GPIO(14)
+
+/* Host interface interrupts */
+#define NETX_IRQ_HIF_CHAINED(x)    (NETX_IRQ_GPIO_LAST + 1 + (x))
+#define NETX_IRQ_HIF_PIO35         NETX_IRQ_HIF_CHAINED(0)
+#define NETX_IRQ_HIF_PIO36         NETX_IRQ_HIF_CHAINED(1)
+#define NETX_IRQ_HIF_PIO40         NETX_IRQ_HIF_CHAINED(2)
+#define NETX_IRQ_HIF_PIO47         NETX_IRQ_HIF_CHAINED(3)
+#define NETX_IRQ_HIF_PIO72         NETX_IRQ_HIF_CHAINED(4)
+#define NETX_IRQ_HIF_LAST          NETX_IRQ_HIF_CHAINED(4)
+
+#define NR_IRQS (NETX_IRQ_HIF_LAST + 1)
diff --git a/include/asm-arm/arch-netx/memory.h b/include/asm-arm/arch-netx/memory.h
new file mode 100644 (file)
index 0000000..6d8d2df
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-netx/memory.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET UL(0x80000000)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)         __virt_to_phys(x)
+#define __bus_to_virt(x)         __phys_to_virt(x)
+
+#endif
+
diff --git a/include/asm-arm/arch-netx/netx-regs.h b/include/asm-arm/arch-netx/netx-regs.h
new file mode 100644 (file)
index 0000000..8ab45be
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * include/asm-arm/arch-netx/netx-regs.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#ifndef __ASM_ARCH_NETX_REGS_H
+#define __ASM_ARCH_NETX_REGS_H
+
+/* offsets relative to the beginning of the io space */
+#define NETX_OFS_SYSTEM  0x00000
+#define NETX_OFS_MEMCR   0x00100
+#define NETX_OFS_DPMAS   0x03000
+#define NETX_OFS_GPIO    0x00800
+#define NETX_OFS_PIO     0x00900
+#define NETX_OFS_UART0   0x00a00
+#define NETX_OFS_UART1   0x00a40
+#define NETX_OFS_UART2   0x00a80
+#define NETX_OF_MIIMU    0x00b00
+#define NETX_OFS_SPI     0x00c00
+#define NETX_OFS_I2C     0x00d00
+#define NETX_OFS_SYSTIME 0x01100
+#define NETX_OFS_RTC     0x01200
+#define NETX_OFS_EXTBUS  0x03600
+#define NETX_OFS_LCD     0x04000
+#define NETX_OFS_USB     0x20000
+#define NETX_OFS_XMAC0   0x60000
+#define NETX_OFS_XMAC1   0x61000
+#define NETX_OFS_XMAC2   0x62000
+#define NETX_OFS_XMAC3   0x63000
+#define NETX_OFS_XMAC(no) (0x60000 + (no) * 0x1000)
+#define NETX_OFS_PFIFO   0x64000
+#define NETX_OFS_XPEC0   0x70000
+#define NETX_OFS_XPEC1   0x74000
+#define NETX_OFS_XPEC2   0x78000
+#define NETX_OFS_XPEC3   0x7c000
+#define NETX_OFS_XPEC(no) (0x70000 + (no) * 0x4000)
+#define NETX_OFS_VIC     0xff000
+
+/* physical addresses */
+#define NETX_PA_SYSTEM   (NETX_IO_PHYS + NETX_OFS_SYSTEM)
+#define NETX_PA_MEMCR    (NETX_IO_PHYS + NETX_OFS_MEMCR)
+#define NETX_PA_DPMAS    (NETX_IO_PHYS + NETX_OFS_DPMAS)
+#define NETX_PA_GPIO     (NETX_IO_PHYS + NETX_OFS_GPIO)
+#define NETX_PA_PIO      (NETX_IO_PHYS + NETX_OFS_PIO)
+#define NETX_PA_UART0    (NETX_IO_PHYS + NETX_OFS_UART0)
+#define NETX_PA_UART1    (NETX_IO_PHYS + NETX_OFS_UART1)
+#define NETX_PA_UART2    (NETX_IO_PHYS + NETX_OFS_UART2)
+#define NETX_PA_MIIMU    (NETX_IO_PHYS + NETX_OF_MIIMU)
+#define NETX_PA_SPI      (NETX_IO_PHYS + NETX_OFS_SPI)
+#define NETX_PA_I2C      (NETX_IO_PHYS + NETX_OFS_I2C)
+#define NETX_PA_SYSTIME  (NETX_IO_PHYS + NETX_OFS_SYSTIME)
+#define NETX_PA_RTC      (NETX_IO_PHYS + NETX_OFS_RTC)
+#define NETX_PA_EXTBUS   (NETX_IO_PHYS + NETX_OFS_EXTBUS)
+#define NETX_PA_LCD      (NETX_IO_PHYS + NETX_OFS_LCD)
+#define NETX_PA_USB      (NETX_IO_PHYS + NETX_OFS_USB)
+#define NETX_PA_XMAC0    (NETX_IO_PHYS + NETX_OFS_XMAC0)
+#define NETX_PA_XMAC1    (NETX_IO_PHYS + NETX_OFS_XMAC1)
+#define NETX_PA_XMAC2    (NETX_IO_PHYS + NETX_OFS_XMAC2)
+#define NETX_PA_XMAC3    (NETX_IO_PHYS + NETX_OFS_XMAC3)
+#define NETX_PA_XMAC(no) (NETX_IO_PHYS + NETX_OFS_XMAC(no))
+#define NETX_PA_PFIFO    (NETX_IO_PHYS + NETX_OFS_PFIFO)
+#define NETX_PA_XPEC0    (NETX_IO_PHYS + NETX_OFS_XPEC0)
+#define NETX_PA_XPEC1    (NETX_IO_PHYS + NETX_OFS_XPEC1)
+#define NETX_PA_XPEC2    (NETX_IO_PHYS + NETX_OFS_XPEC2)
+#define NETX_PA_XPEC3    (NETX_IO_PHYS + NETX_OFS_XPEC3)
+#define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no))
+#define NETX_PA_VIC      (NETX_IO_PHYS + NETX_OFS_VIC)
+
+/* virual addresses */
+#define NETX_VA_SYSTEM   (NETX_IO_VIRT + NETX_OFS_SYSTEM)
+#define NETX_VA_MEMCR    (NETX_IO_VIRT + NETX_OFS_MEMCR)
+#define NETX_VA_DPMAS    (NETX_IO_VIRT + NETX_OFS_DPMAS)
+#define NETX_VA_GPIO     (NETX_IO_VIRT + NETX_OFS_GPIO)
+#define NETX_VA_PIO      (NETX_IO_VIRT + NETX_OFS_PIO)
+#define NETX_VA_UART0    (NETX_IO_VIRT + NETX_OFS_UART0)
+#define NETX_VA_UART1    (NETX_IO_VIRT + NETX_OFS_UART1)
+#define NETX_VA_UART2    (NETX_IO_VIRT + NETX_OFS_UART2)
+#define NETX_VA_MIIMU    (NETX_IO_VIRT + NETX_OF_MIIMU)
+#define NETX_VA_SPI      (NETX_IO_VIRT + NETX_OFS_SPI)
+#define NETX_VA_I2C      (NETX_IO_VIRT + NETX_OFS_I2C)
+#define NETX_VA_SYSTIME  (NETX_IO_VIRT + NETX_OFS_SYSTIME)
+#define NETX_VA_RTC      (NETX_IO_VIRT + NETX_OFS_RTC)
+#define NETX_VA_EXTBUS   (NETX_IO_VIRT + NETX_OFS_EXTBUS)
+#define NETX_VA_LCD      (NETX_IO_VIRT + NETX_OFS_LCD)
+#define NETX_VA_USB      (NETX_IO_VIRT + NETX_OFS_USB)
+#define NETX_VA_XMAC0    (NETX_IO_VIRT + NETX_OFS_XMAC0)
+#define NETX_VA_XMAC1    (NETX_IO_VIRT + NETX_OFS_XMAC1)
+#define NETX_VA_XMAC2    (NETX_IO_VIRT + NETX_OFS_XMAC2)
+#define NETX_VA_XMAC3    (NETX_IO_VIRT + NETX_OFS_XMAC3)
+#define NETX_VA_XMAC(no) (NETX_IO_VIRT + NETX_OFS_XMAC(no))
+#define NETX_VA_PFIFO    (NETX_IO_VIRT + NETX_OFS_PFIFO)
+#define NETX_VA_XPEC0    (NETX_IO_VIRT + NETX_OFS_XPEC0)
+#define NETX_VA_XPEC1    (NETX_IO_VIRT + NETX_OFS_XPEC1)
+#define NETX_VA_XPEC2    (NETX_IO_VIRT + NETX_OFS_XPEC2)
+#define NETX_VA_XPEC3    (NETX_IO_VIRT + NETX_OFS_XPEC3)
+#define NETX_VA_XPEC(no) (NETX_IO_VIRT + NETX_OFS_XPEC(no))
+#define NETX_VA_VIC      (NETX_IO_VIRT + NETX_OFS_VIC)
+
+/*********************************
+ * System functions              *
+ *********************************/
+
+/* Registers */
+#define NETX_SYSTEM_REG(ofs)            __io(NETX_VA_SYSTEM + (ofs))
+#define NETX_SYSTEM_BOO_SR          NETX_SYSTEM_REG(0x00)
+#define NETX_SYSTEM_IOC_CR          NETX_SYSTEM_REG(0x04)
+#define NETX_SYSTEM_IOC_MR          NETX_SYSTEM_REG(0x08)
+
+/* FIXME: Docs are not consistent */
+#define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x08)
+/* #define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x0c) */
+
+#define NETX_SYSTEM_PHY_CONTROL     NETX_SYSTEM_REG(0x10)
+#define NETX_SYSTEM_REV             NETX_SYSTEM_REG(0x34)
+#define NETX_SYSTEM_IOC_ACCESS_KEY  NETX_SYSTEM_REG(0x70)
+#define NETX_SYSTEM_WDG_TR          NETX_SYSTEM_REG(0x200)
+#define NETX_SYSTEM_WDG_CTR         NETX_SYSTEM_REG(0x204)
+#define NETX_SYSTEM_WDG_IRQ_TIMEOUT NETX_SYSTEM_REG(0x208)
+#define NETX_SYSTEM_WDG_RES_TIMEOUT NETX_SYSTEM_REG(0x20c)
+
+/* Bits */
+#define NETX_SYSTEM_RES_CR_RSTIN         (1<<0)
+#define NETX_SYSTEM_RES_CR_WDG_RES       (1<<1)
+#define NETX_SYSTEM_RES_CR_HOST_RES      (1<<2)
+#define NETX_SYSTEM_RES_CR_FIRMW_RES     (1<<3)
+#define NETX_SYSTEM_RES_CR_XPEC0_RES     (1<<4)
+#define NETX_SYSTEM_RES_CR_XPEC1_RES     (1<<5)
+#define NETX_SYSTEM_RES_CR_XPEC2_RES     (1<<6)
+#define NETX_SYSTEM_RES_CR_XPEC3_RES     (1<<7)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC0_RES (1<<16)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC1_RES (1<<17)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC2_RES (1<<18)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC3_RES (1<<19)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG0    (1<<20)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG1    (1<<21)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG2    (1<<22)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG3    (1<<23)
+#define NETX_SYSTEM_RES_CR_FIRMW_RES_EN  (1<<24)
+#define NETX_SYSTEM_RES_CR_RSTOUT        (1<<25)
+#define NETX_SYSTEM_RES_CR_EN_RSTOUT     (1<<26)
+
+#define PHY_CONTROL_RESET            (1<<31)
+#define PHY_CONTROL_SIM_BYP          (1<<30)
+#define PHY_CONTROL_CLK_XLATIN       (1<<29)
+#define PHY_CONTROL_PHY1_EN          (1<<21)
+#define PHY_CONTROL_PHY1_NP_MSG_CODE
+#define PHY_CONTROL_PHY1_AUTOMDIX    (1<<17)
+#define PHY_CONTROL_PHY1_FIXMODE     (1<<16)
+#define PHY_CONTROL_PHY1_MODE(mode)  (((mode) & 0x7) << 13)
+#define PHY_CONTROL_PHY0_EN          (1<<12)
+#define PHY_CONTROL_PHY0_NP_MSG_CODE
+#define PHY_CONTROL_PHY0_AUTOMDIX    (1<<8)
+#define PHY_CONTROL_PHY0_FIXMODE     (1<<7)
+#define PHY_CONTROL_PHY0_MODE(mode)  (((mode) & 0x7) << 4)
+#define PHY_CONTROL_PHY_ADDRESS(adr) ((adr) & 0xf)
+
+#define PHY_MODE_10BASE_T_HALF      0
+#define PHY_MODE_10BASE_T_FULL      1
+#define PHY_MODE_100BASE_TX_FX_FULL 2
+#define PHY_MODE_100BASE_TX_FX_HALF 3
+#define PHY_MODE_100BASE_TX_HALF    4
+#define PHY_MODE_REPEATER           5
+#define PHY_MODE_POWER_DOWN         6
+#define PHY_MODE_ALL                7
+
+/* Bits */
+#define VECT_CNTL_ENABLE               (1 << 5)
+
+/*******************************
+ * GPIO and timer module       *
+ *******************************/
+
+/* Registers */
+#define NETX_GPIO_REG(ofs)                     __io(NETX_VA_GPIO + (ofs))
+#define NETX_GPIO_CFG(gpio)                NETX_GPIO_REG(0x0  + ((gpio)<<2))
+#define NETX_GPIO_THRESHOLD_CAPTURE(gpio)  NETX_GPIO_REG(0x40 + ((gpio)<<2))
+#define NETX_GPIO_COUNTER_CTRL(counter)    NETX_GPIO_REG(0x80 + ((counter)<<2))
+#define NETX_GPIO_COUNTER_MAX(counter)     NETX_GPIO_REG(0x94 + ((counter)<<2))
+#define NETX_GPIO_COUNTER_CURRENT(counter) NETX_GPIO_REG(0xa8 + ((counter)<<2))
+#define NETX_GPIO_IRQ_ENABLE               NETX_GPIO_REG(0xbc)
+#define NETX_GPIO_IRQ_DISABLE              NETX_GPIO_REG(0xc0)
+#define NETX_GPIO_SYSTIME_NS_CMP           NETX_GPIO_REG(0xc4)
+#define NETX_GPIO_LINE                     NETX_GPIO_REG(0xc8)
+#define NETX_GPIO_IRQ                      NETX_GPIO_REG(0xd0)
+
+/* Bits */
+#define NETX_GPIO_CFG_IOCFG_GP_INPUT                 (0x0)
+#define NETX_GPIO_CFG_IOCFG_GP_OUTPUT                (0x1)
+#define NETX_GPIO_CFG_IOCFG_GP_UART                  (0x2)
+#define NETX_GPIO_CFG_INV                            (1<<2)
+#define NETX_GPIO_CFG_MODE_INPUT_READ                (0<<3)
+#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_CONT_RISING (1<<3)
+#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_ONCE_RISING (2<<3)
+#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_HIGH_LEVEL  (3<<3)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER0             (0<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER1             (1<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER2             (2<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER3             (3<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER4             (4<<5)
+#define NETX_GPIO_CFG_COUNT_REF_SYSTIME              (7<<5)
+
+#define NETX_GPIO_COUNTER_CTRL_RUN                   (1<<0)
+#define NETX_GPIO_COUNTER_CTRL_SYM                   (1<<1)
+#define NETX_GPIO_COUNTER_CTRL_ONCE                  (1<<2)
+#define NETX_GPIO_COUNTER_CTRL_IRQ_EN                (1<<3)
+#define NETX_GPIO_COUNTER_CTRL_CNT_EVENT             (1<<4)
+#define NETX_GPIO_COUNTER_CTRL_RST_EN                (1<<5)
+#define NETX_GPIO_COUNTER_CTRL_SEL_EVENT             (1<<6)
+#define NETX_GPIO_COUNTER_CTRL_GPIO_REF /* FIXME */
+
+#define GPIO_BIT(gpio)                     (1<<(gpio))
+#define COUNTER_BIT(counter)               ((1<<16)<<(counter))
+
+/*******************************
+ * PIO                         *
+ *******************************/
+
+/* Registers */
+#define NETX_PIO_REG(ofs)        __io(NETX_VA_PIO + (ofs))
+#define NETX_PIO_INPIO       NETX_PIO_REG(0x0)
+#define NETX_PIO_OUTPIO      NETX_PIO_REG(0x4)
+#define NETX_PIO_OEPIO       NETX_PIO_REG(0x8)
+
+/*******************************
+ * MII Unit                    *
+ *******************************/
+
+/* Registers */
+#define NETX_MIIMU           __io(NETX_VA_MIIMU)
+
+/* Bits */
+#define MIIMU_SNRDY        (1<<0)
+#define MIIMU_PREAMBLE     (1<<1)
+#define MIIMU_OPMODE_WRITE (1<<2)
+#define MIIMU_MDC_PERIOD   (1<<3)
+#define MIIMU_PHY_NRES     (1<<4)
+#define MIIMU_RTA          (1<<5)
+#define MIIMU_REGADDR(adr) (((adr) & 0x1f) << 6)
+#define MIIMU_PHYADDR(adr) (((adr) & 0x1f) << 11)
+#define MIIMU_DATA(data)   (((data) & 0xffff) << 16)
+
+/*******************************
+ * xmac / xpec                 *
+ *******************************/
+
+/* XPEC register offsets relative to NETX_VA_XPEC(no) */
+#define NETX_XPEC_R0_OFS           0x00
+#define NETX_XPEC_R1_OFS           0x04
+#define NETX_XPEC_R2_OFS           0x08
+#define NETX_XPEC_R3_OFS           0x0c
+#define NETX_XPEC_R4_OFS           0x10
+#define NETX_XPEC_R5_OFS           0x14
+#define NETX_XPEC_R6_OFS           0x18
+#define NETX_XPEC_R7_OFS           0x1c
+#define NETX_XPEC_RANGE01_OFS      0x20
+#define NETX_XPEC_RANGE23_OFS      0x24
+#define NETX_XPEC_RANGE45_OFS      0x28
+#define NETX_XPEC_RANGE67_OFS      0x2c
+#define NETX_XPEC_PC_OFS           0x48
+#define NETX_XPEC_TIMER_OFS(timer) (0x30 + ((timer)<<2))
+#define NETX_XPEC_IRQ_OFS          0x8c
+#define NETX_XPEC_SYSTIME_NS_OFS   0x90
+#define NETX_XPEC_FIFO_DATA_OFS    0x94
+#define NETX_XPEC_SYSTIME_S_OFS    0x98
+#define NETX_XPEC_ADC_OFS          0x9c
+#define NETX_XPEC_URX_COUNT_OFS    0x40
+#define NETX_XPEC_UTX_COUNT_OFS    0x44
+#define NETX_XPEC_PC_OFS           0x48
+#define NETX_XPEC_ZERO_OFS         0x4c
+#define NETX_XPEC_STATCFG_OFS      0x50
+#define NETX_XPEC_EC_MASKA_OFS     0x54
+#define NETX_XPEC_EC_MASKB_OFS     0x58
+#define NETX_XPEC_EC_MASK0_OFS     0x5c
+#define NETX_XPEC_EC_MASK8_OFS     0x7c
+#define NETX_XPEC_EC_MASK9_OFS     0x80
+#define NETX_XPEC_XPU_HOLD_PC_OFS  0x100
+#define NETX_XPEC_RAM_START_OFS    0x2000
+
+/* Bits */
+#define XPU_HOLD_PC (1<<0)
+
+/* XMAC register offsets relative to NETX_VA_XMAC(no) */
+#define NETX_XMAC_RPU_PROGRAM_START_OFS       0x000
+#define NETX_XMAC_RPU_PROGRAM_END_OFS         0x3ff
+#define NETX_XMAC_TPU_PROGRAM_START_OFS       0x400
+#define NETX_XMAC_TPU_PROGRAM_END_OFS         0x7ff
+#define NETX_XMAC_RPU_HOLD_PC_OFS             0xa00
+#define NETX_XMAC_TPU_HOLD_PC_OFS             0xa04
+#define NETX_XMAC_STATUS_SHARED0_OFS          0x840
+#define NETX_XMAC_CONFIG_SHARED0_OFS          0x844
+#define NETX_XMAC_STATUS_SHARED1_OFS          0x848
+#define NETX_XMAC_CONFIG_SHARED1_OFS          0x84c
+#define NETX_XMAC_STATUS_SHARED2_OFS          0x850
+#define NETX_XMAC_CONFIG_SHARED2_OFS          0x854
+#define NETX_XMAC_STATUS_SHARED3_OFS          0x858
+#define NETX_XMAC_CONFIG_SHARED3_OFS          0x85c
+
+#define RPU_HOLD_PC            (1<<15)
+#define TPU_HOLD_PC            (1<<15)
+
+/*******************************
+ * Pointer FIFO                *
+ *******************************/
+
+/* Registers */
+#define NETX_PFIFO_REG(ofs)               __io(NETX_VA_PFIFO + (ofs))
+#define NETX_PFIFO_BASE(pfifo)        NETX_PFIFO_REG(0x00 + ((pfifo)<<2))
+#define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2))
+#define NETX_PFIFO_RESET              NETX_PFIFO_REG(0x100)
+#define NETX_PFIFO_FULL               NETX_PFIFO_REG(0x104)
+#define NETX_PFIFO_EMPTY              NETX_PFIFO_REG(0x108)
+#define NETX_PFIFO_OVEFLOW            NETX_PFIFO_REG(0x10c)
+#define NETX_PFIFO_UNDERRUN           NETX_PFIFO_REG(0x110)
+#define NETX_PFIFO_FILL_LEVEL(pfifo)  NETX_PFIFO_REG(0x180 + ((pfifo)<<2))
+#define NETX_PFIFO_XPEC_ISR(xpec)     NETX_PFIFO_REG(0x400 + ((xpec) << 2))
+
+/*******************************
+ * Dual Port Memory            *
+ *******************************/
+
+/* Registers */
+#define NETX_DPMAS_REG(ofs)               __io(NETX_VA_DPMAS + (ofs))
+#define NETX_DPMAS_SYS_STAT           NETX_DPMAS_REG(0x4d8)
+#define NETX_DPMAS_INT_STAT           NETX_DPMAS_REG(0x4e0)
+#define NETX_DPMAS_INT_EN             NETX_DPMAS_REG(0x4f0)
+#define NETX_DPMAS_IF_CONF0           NETX_DPMAS_REG(0x608)
+#define NETX_DPMAS_IF_CONF1           NETX_DPMAS_REG(0x60c)
+#define NETX_DPMAS_EXT_CONFIG(cs)     NETX_DPMAS_REG(0x610 + 4 * (cs))
+#define NETX_DPMAS_IO_MODE0           NETX_DPMAS_REG(0x620) /* I/O 32..63 */
+#define NETX_DPMAS_DRV_EN0            NETX_DPMAS_REG(0x624)
+#define NETX_DPMAS_DATA0              NETX_DPMAS_REG(0x628)
+#define NETX_DPMAS_IO_MODE1           NETX_DPMAS_REG(0x630) /* I/O 64..84 */
+#define NETX_DPMAS_DRV_EN1            NETX_DPMAS_REG(0x634)
+#define NETX_DPMAS_DATA1              NETX_DPMAS_REG(0x638)
+
+/* Bits */
+#define NETX_DPMAS_INT_EN_GLB_EN         (1<<31)
+#define NETX_DPMAS_INT_EN_MEM_LCK        (1<<30)
+#define NETX_DPMAS_INT_EN_WDG            (1<<29)
+#define NETX_DPMAS_INT_EN_PIO72          (1<<28)
+#define NETX_DPMAS_INT_EN_PIO47          (1<<27)
+#define NETX_DPMAS_INT_EN_PIO40          (1<<26)
+#define NETX_DPMAS_INT_EN_PIO36          (1<<25)
+#define NETX_DPMAS_INT_EN_PIO35          (1<<24)
+
+#define NETX_DPMAS_IF_CONF0_HIF_DISABLED (0<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_EXT_BUS  (1<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_UP_8BIT  (2<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_UP_16BIT (3<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_IO       (4<<28)
+#define NETX_DPMAS_IF_CONF0_WAIT_DRV_PP  (1<<14)
+#define NETX_DPMAS_IF_CONF0_WAIT_DRV_OD  (2<<14)
+#define NETX_DPMAS_IF_CONF0_WAIT_DRV_TRI (3<<14)
+
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO35 (1<<26)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO36 (1<<27)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO40 (1<<28)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO47 (1<<29)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO72 (1<<30)
+
+#define NETX_EXT_CONFIG_TALEWIDTH(x) (((x) & 0x7) << 29)
+#define NETX_EXT_CONFIG_TADRHOLD(x)  (((x) & 0x7) << 26)
+#define NETX_EXT_CONFIG_TCSON(x)     (((x) & 0x7) << 23)
+#define NETX_EXT_CONFIG_TRDON(x)     (((x) & 0x7) << 20)
+#define NETX_EXT_CONFIG_TWRON(x)     (((x) & 0x7)  << 17)
+#define NETX_EXT_CONFIG_TWROFF(x)    (((x) & 0x1f) << 12)
+#define NETX_EXT_CONFIG_TRDWRCYC(x)  (((x) & 0x1f) << 7)
+#define NETX_EXT_CONFIG_WAIT_POL     (1<<6)
+#define NETX_EXT_CONFIG_WAIT_EN      (1<<5)
+#define NETX_EXT_CONFIG_NRD_MODE     (1<<4)
+#define NETX_EXT_CONFIG_DS_MODE      (1<<3)
+#define NETX_EXT_CONFIG_NWR_MODE     (1<<2)
+#define NETX_EXT_CONFIG_16BIT        (1<<1)
+#define NETX_EXT_CONFIG_CS_ENABLE    (1<<0)
+
+#define NETX_DPMAS_IO_MODE0_WRL   (1<<13)
+#define NETX_DPMAS_IO_MODE0_WAIT  (1<<14)
+#define NETX_DPMAS_IO_MODE0_READY (1<<15)
+#define NETX_DPMAS_IO_MODE0_CS0   (1<<19)
+#define NETX_DPMAS_IO_MODE0_EXTRD (1<<20)
+
+#define NETX_DPMAS_IO_MODE1_CS2           (1<<15)
+#define NETX_DPMAS_IO_MODE1_CS1           (1<<16)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_NPOR   (0<<30)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_100MHZ (1<<30)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_NPIO36 (2<<30)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_PIO36  (3<<30)
+
+/*******************************
+ * I2C                         *
+ *******************************/
+#define NETX_I2C_REG(ofs)      __io(NETX_VA_I2C, (ofs))
+#define NETX_I2C_CTRL  NETX_I2C_REG(0x0)
+#define NETX_I2C_DATA  NETX_I2C_REG(0x4)
+
+#endif /* __ASM_ARCH_NETX_REGS_H */
diff --git a/include/asm-arm/arch-netx/param.h b/include/asm-arm/arch-netx/param.h
new file mode 100644 (file)
index 0000000..7a80c26
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *  linux/include/asm-arm/arch-netx/param.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
diff --git a/include/asm-arm/arch-netx/pfifo.h b/include/asm-arm/arch-netx/pfifo.h
new file mode 100644 (file)
index 0000000..4af2ee4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * include/asm-arm/arch-netx/pfifo.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+
+#ifndef ASM_ARCH_PFIFO_H
+#define ASM_ARCH_PFIFO_H
+
+static inline int pfifo_push(int no, unsigned int pointer)
+{
+       writel(pointer, NETX_PFIFO_BASE(no));
+       return 0;
+}
+
+static inline unsigned int pfifo_pop(int no)
+{
+       return readl(NETX_PFIFO_BASE(no));
+}
+
+static inline int pfifo_fill_level(int no)
+{
+
+       return readl(NETX_PFIFO_FILL_LEVEL(no));
+}
+
+static inline int pfifo_full(int no)
+{
+       return readl(NETX_PFIFO_FULL) & (1<<no) ? 1 : 0;
+}
+
+static inline int pfifo_empty(int no)
+{
+       return readl(NETX_PFIFO_EMPTY) & (1<<no) ? 1 : 0;
+}
+
+int pfifo_request(unsigned int pfifo_mask);
+void pfifo_free(unsigned int pfifo_mask);
+
+#endif /* ASM_ARCH_PFIFO_H */
diff --git a/include/asm-arm/arch-netx/system.h b/include/asm-arm/arch-netx/system.h
new file mode 100644 (file)
index 0000000..52adf36
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-netx/system.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include "netx-regs.h"
+
+static inline void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES,
+              NETX_SYSTEM_RES_CR);
+}
+
+#endif
+
diff --git a/include/asm-arm/arch-netx/timex.h b/include/asm-arm/arch-netx/timex.h
new file mode 100644 (file)
index 0000000..7fdb42d
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-netx/timex.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#define CLOCK_TICK_RATE 100000000
diff --git a/include/asm-arm/arch-netx/uncompress.h b/include/asm-arm/arch-netx/uncompress.h
new file mode 100644 (file)
index 0000000..f894345
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * include/asm-arm/arch-netx/uncompress.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader.  We search for the first enabled
+ * port in the most probable order.  If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
+ * This does not append a newline
+ */
+
+#define REG(x) (*(volatile unsigned long *)(x))
+
+#define UART1_BASE 0x100a00
+#define UART2_BASE 0x100a80
+
+#define UART_DR 0x0
+
+#define UART_CR 0x14
+#define CR_UART_EN (1<<0)
+
+#define UART_FR 0x18
+#define FR_BUSY (1<<3)
+#define FR_TXFF (1<<5)
+
+static void putc(char c)
+{
+       unsigned long base;
+
+       if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
+               base = UART1_BASE;
+       else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
+               base = UART2_BASE;
+       else
+               return;
+
+       while (REG(base + UART_FR) & FR_TXFF);
+       REG(base + UART_DR) = c;
+}
+
+static inline void flush(void)
+{
+       unsigned long base;
+
+       if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
+               base = UART1_BASE;
+       else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
+               base = UART2_BASE;
+       else
+               return;
+
+       while (REG(base + UART_FR) & FR_BUSY);
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-netx/vmalloc.h b/include/asm-arm/arch-netx/vmalloc.h
new file mode 100644 (file)
index 0000000..da2da5a
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-netx/vmalloc.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-netx/xc.h b/include/asm-arm/arch-netx/xc.h
new file mode 100644 (file)
index 0000000..659af19
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  linux/include/asm-arm/arch-netx/xc.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can 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
+ */
+
+#ifndef __ASM_ARCH_XC_H
+#define __ASM_ARCH_XC_H
+
+struct xc {
+       int no;
+       unsigned int type;
+       unsigned int version;
+       void __iomem *xpec_base;
+       void __iomem *xmac_base;
+       void __iomem *sram_base;
+       int irq;
+       struct device *dev;
+};
+
+int xc_reset(struct xc *x);
+int xc_stop(struct xc* x);
+int xc_start(struct xc *x);
+int xc_running(struct xc *x);
+int xc_request_firmware(struct xc* x);
+struct xc* request_xc(int xcno, struct device *dev);
+void free_xc(struct xc *x);
+
+#endif /* __ASM_ARCH_XC_H */
diff --git a/include/asm-arm/arch-omap/board-fsample.h b/include/asm-arm/arch-omap/board-fsample.h
new file mode 100644 (file)
index 0000000..89a1e52
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-fsample.h
+ *
+ * Board-specific goodies for TI F-Sample.
+ *
+ * Copyright (C) 2006 Google, Inc.
+ * Author: Brian Swetland <swetland@google.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.
+ */
+
+#ifndef __ASM_ARCH_OMAP_FSAMPLE_H
+#define __ASM_ARCH_OMAP_FSAMPLE_H
+
+/* fsample is pretty close to p2-sample */
+#include <asm/arch/board-perseus2.h>
+
+#define fsample_cpld_read(reg) __raw_readb(reg)
+#define fsample_cpld_write(val, reg) __raw_writeb(val, reg)
+
+#define FSAMPLE_CPLD_BASE    0xE8100000
+#define FSAMPLE_CPLD_SIZE    SZ_4K
+#define FSAMPLE_CPLD_START   0x05080000
+
+#define FSAMPLE_CPLD_REG_A   (FSAMPLE_CPLD_BASE + 0x00)
+#define FSAMPLE_CPLD_SWITCH  (FSAMPLE_CPLD_BASE + 0x02)
+#define FSAMPLE_CPLD_UART    (FSAMPLE_CPLD_BASE + 0x02)
+#define FSAMPLE_CPLD_REG_B   (FSAMPLE_CPLD_BASE + 0x04)
+#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06)
+#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06)
+
+#define FSAMPLE_CPLD_BIT_BT_RESET         0
+#define FSAMPLE_CPLD_BIT_LCD_RESET        1
+#define FSAMPLE_CPLD_BIT_CAM_PWDN         2
+#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE   3
+#define FSAMPLE_CPLD_BIT_SD_MMC_EN        4
+#define FSAMPLE_CPLD_BIT_aGPS_PWREN       5
+#define FSAMPLE_CPLD_BIT_BACKLIGHT        6
+#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET    7
+#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N    8
+#define FSAMPLE_CPLD_BIT_OTG_RESET        9
+
+#define fsample_cpld_set(bit) \
+    fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR)
+
+#define fsample_cpld_clear(bit) \
+    fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR)
+
+#endif
diff --git a/include/asm-arm/arch-omap/gpmc.h b/include/asm-arm/arch-omap/gpmc.h
new file mode 100644 (file)
index 0000000..1a0a520
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * General-Purpose Memory Controller for OMAP2
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP2_GPMC_H
+#define __OMAP2_GPMC_H
+
+#define GPMC_CS_CONFIG1                0x00
+#define GPMC_CS_CONFIG2                0x04
+#define GPMC_CS_CONFIG3                0x08
+#define GPMC_CS_CONFIG4                0x0c
+#define GPMC_CS_CONFIG5                0x10
+#define GPMC_CS_CONFIG6                0x14
+#define GPMC_CS_CONFIG7                0x18
+#define GPMC_CS_NAND_COMMAND   0x1c
+#define GPMC_CS_NAND_ADDRESS   0x20
+#define GPMC_CS_NAND_DATA      0x24
+
+#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
+#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 20)
+#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
+#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
+#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
+#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
+#define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
+#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
+#define GPMC_CONFIG1_WAIT_PIN_SEL(val)  ((val & 3) << 16)
+#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
+#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
+#define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
+#define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
+#define GPMC_CONFIG1_DEVICETYPE_NAND    GPMC_CONFIG1_DEVICETYPE(1)
+#define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
+#define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
+#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
+#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
+#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
+#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
+
+/*
+ * Note that all values in this struct are in nanoseconds, while
+ * the register values are in gpmc_fck cycles.
+ */
+struct gpmc_timings {
+       /* Minimum clock period for synchronous mode */
+       u16 sync_clk;
+
+       /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
+       u16 cs_on;              /* Assertion time */
+       u16 cs_rd_off;          /* Read deassertion time */
+       u16 cs_wr_off;          /* Write deassertion time */
+
+       /* ADV signal timings corresponding to GPMC_CONFIG3 */
+       u16 adv_on;             /* Assertion time */
+       u16 adv_rd_off;         /* Read deassertion time */
+       u16 adv_wr_off;         /* Write deassertion time */
+
+       /* WE signals timings corresponding to GPMC_CONFIG4 */
+       u16 we_on;              /* WE assertion time */
+       u16 we_off;             /* WE deassertion time */
+
+       /* OE signals timings corresponding to GPMC_CONFIG4 */
+       u16 oe_on;              /* OE assertion time */
+       u16 oe_off;             /* OE deassertion time */
+
+       /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
+       u16 page_burst_access;  /* Multiple access word delay */
+       u16 access;             /* Start-cycle to first data valid delay */
+       u16 rd_cycle;           /* Total read cycle time */
+       u16 wr_cycle;           /* Total write cycle time */
+};
+
+extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+
+extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
+extern u32 gpmc_cs_read_reg(int cs, int idx);
+extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
+extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
+extern unsigned long gpmc_cs_get_base_addr(int cs);
+
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/clock.h b/include/asm-arm/arch-pnx4008/clock.h
new file mode 100644 (file)
index 0000000..91ae003
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * include/asm-arm/arch-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - header file
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PNX4008_CLOCK_H__
+#define __PNX4008_CLOCK_H__
+
+struct module;
+struct clk;
+
+#define PWRMAN_VA_BASE         IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define HCLKDIVCTRL_REG                (PWRMAN_VA_BASE + 0x40)
+#define PWRCTRL_REG            (PWRMAN_VA_BASE + 0x44)
+#define PLLCTRL_REG            (PWRMAN_VA_BASE + 0x48)
+#define OSC13CTRL_REG          (PWRMAN_VA_BASE + 0x4c)
+#define SYSCLKCTRL_REG         (PWRMAN_VA_BASE + 0x50)
+#define HCLKPLLCTRL_REG                (PWRMAN_VA_BASE + 0x58)
+#define USBCTRL_REG            (PWRMAN_VA_BASE + 0x64)
+#define SDRAMCLKCTRL_REG       (PWRMAN_VA_BASE + 0x68)
+#define MSCTRL_REG             (PWRMAN_VA_BASE + 0x80)
+#define BTCLKCTRL              (PWRMAN_VA_BASE + 0x84)
+#define DUMCLKCTRL_REG         (PWRMAN_VA_BASE + 0x90)
+#define I2CCLKCTRL_REG         (PWRMAN_VA_BASE + 0xac)
+#define KEYCLKCTRL_REG         (PWRMAN_VA_BASE + 0xb0)
+#define TSCLKCTRL_REG          (PWRMAN_VA_BASE + 0xb4)
+#define PWMCLKCTRL_REG         (PWRMAN_VA_BASE + 0xb8)
+#define SPICTRL_REG            (PWRMAN_VA_BASE + 0xc4)
+#define FLASHCLKCTRL_REG       (PWRMAN_VA_BASE + 0xc8)
+#define UART3CLK_REG           (PWRMAN_VA_BASE + 0xd0)
+#define UARTCLKCTRL_REG                (PWRMAN_VA_BASE + 0xe4)
+#define DMACLKCTRL_REG         (PWRMAN_VA_BASE + 0xe8)
+#define AUTOCLK_CTRL           (PWRMAN_VA_BASE + 0xec)
+#define JPEGCLKCTRL_REG                (PWRMAN_VA_BASE + 0xfc)
+
+#define AUDIOCONFIG_VA_BASE    IO_ADDRESS(PNX4008_AUDIOCONFIG_BASE)
+#define DSPPLLCTRL_REG         (AUDIOCONFIG_VA_BASE + 0x60)
+#define DSPCLKCTRL_REG         (AUDIOCONFIG_VA_BASE + 0x64)
+#define AUDIOCLKCTRL_REG       (AUDIOCONFIG_VA_BASE + 0x68)
+#define AUDIOPLLCTRL_REG       (AUDIOCONFIG_VA_BASE + 0x6C)
+
+#define USB_OTG_CLKCTRL_REG    IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xff4)
+
+#define VFP9CLKCTRL_REG                IO_ADDRESS(PNX4008_DEBUG_BASE)
+
+#define CLK_RATE_13MHZ 13000
+#define CLK_RATE_1MHZ 1000
+#define CLK_RATE_208MHZ 208000
+#define CLK_RATE_48MHZ 48000
+#define CLK_RATE_32KHZ 32
+
+#define PNX4008_UART_CLK CLK_RATE_13MHZ * 1000 /* in MHz */
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/debug-macro.S b/include/asm-arm/arch-pnx4008/debug-macro.S
new file mode 100644 (file)
index 0000000..67d18a2
--- /dev/null
@@ -0,0 +1,23 @@
+/* linux/include/asm-arm/arch-pnx4008/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+               .macro  addruart,rx
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1                 @ MMU enabled?
+               mov     \rx, #0x00090000
+               addeq   \rx, \rx, #0x40000000
+               addne   \rx, \rx, #0xf4000000
+               .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-pnx4008/dma.h b/include/asm-arm/arch-pnx4008/dma.h
new file mode 100644 (file)
index 0000000..3aee120
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/dma.h
+ *
+ *  PNX4008 DMA header file
+ *
+ *  Author:    Vitaly Wool
+ *  Copyright: MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include "platform.h"
+
+#define MAX_DMA_ADDRESS                0xffffffff
+
+#define MAX_DMA_CHANNELS       8
+
+#define DMAC_BASE              IO_ADDRESS(PNX4008_DMA_CONFIG_BASE)
+#define DMAC_INT_STAT          (DMAC_BASE + 0x0000)
+#define DMAC_INT_TC_STAT       (DMAC_BASE + 0x0004)
+#define DMAC_INT_TC_CLEAR      (DMAC_BASE + 0x0008)
+#define DMAC_INT_ERR_STAT      (DMAC_BASE + 0x000c)
+#define DMAC_INT_ERR_CLEAR     (DMAC_BASE + 0x0010)
+#define DMAC_SOFT_SREQ         (DMAC_BASE + 0x0024)
+#define DMAC_CONFIG            (DMAC_BASE + 0x0030)
+#define DMAC_Cx_SRC_ADDR(c)    (DMAC_BASE + 0x0100 + (c) * 0x20)
+#define DMAC_Cx_DEST_ADDR(c)   (DMAC_BASE + 0x0104 + (c) * 0x20)
+#define DMAC_Cx_LLI(c)         (DMAC_BASE + 0x0108 + (c) * 0x20)
+#define DMAC_Cx_CONTROL(c)     (DMAC_BASE + 0x010c + (c) * 0x20)
+#define DMAC_Cx_CONFIG(c)      (DMAC_BASE + 0x0110 + (c) * 0x20)
+
+enum {
+       WIDTH_BYTE = 0,
+       WIDTH_HWORD,
+       WIDTH_WORD
+};
+
+enum {
+       FC_MEM2MEM_DMA,
+       FC_MEM2PER_DMA,
+       FC_PER2MEM_DMA,
+       FC_PER2PER_DMA,
+       FC_PER2PER_DPER,
+       FC_MEM2PER_PER,
+       FC_PER2MEM_PER,
+       FC_PER2PER_SPER
+};
+
+enum {
+       DMA_INT_UNKNOWN = 0,
+       DMA_ERR_INT = 1,
+       DMA_TC_INT = 2,
+};
+
+enum {
+       DMA_BUFFER_ALLOCATED = 1,
+       DMA_HAS_LL = 2,
+};
+
+enum {
+       PER_CAM_DMA_1 = 0,
+       PER_NDF_FLASH = 1,
+       PER_MBX_SLAVE_FIFO = 2,
+       PER_SPI2_REC_XMIT = 3,
+       PER_MS_SD_RX_XMIT = 4,
+       PER_HS_UART_1_XMIT = 5,
+       PER_HS_UART_1_RX = 6,
+       PER_HS_UART_2_XMIT = 7,
+       PER_HS_UART_2_RX = 8,
+       PER_HS_UART_7_XMIT = 9,
+       PER_HS_UART_7_RX = 10,
+       PER_SPI1_REC_XMIT = 11,
+       PER_MLC_NDF_SREC = 12,
+       PER_CAM_DMA_2 = 13,
+       PER_PRNG_INFIFO = 14,
+       PER_PRNG_OUTFIFO = 15,
+};
+
+struct pnx4008_dma_ch_ctrl {
+       int tc_mask;
+       int cacheable;
+       int bufferable;
+       int priv_mode;
+       int di;
+       int si;
+       int dest_ahb1;
+       int src_ahb1;
+       int dwidth;
+       int swidth;
+       int dbsize;
+       int sbsize;
+       int tr_size;
+};
+
+struct pnx4008_dma_ch_config {
+       int halt;
+       int active;
+       int lock;
+       int itc;
+       int ie;
+       int flow_cntrl;
+       int dest_per;
+       int src_per;
+};
+
+struct pnx4008_dma_ll {
+       unsigned long src_addr;
+       unsigned long dest_addr;
+       u32 next_dma;
+       unsigned long ch_ctrl;
+       struct pnx4008_dma_ll *next;
+       int flags;
+       void *alloc_data;
+       int (*free) (void *);
+};
+
+struct pnx4008_dma_config {
+       int is_ll;
+       unsigned long src_addr;
+       unsigned long dest_addr;
+       unsigned long ch_ctrl;
+       unsigned long ch_cfg;
+       struct pnx4008_dma_ll *ll;
+       u32 ll_dma;
+       int flags;
+       void *alloc_data;
+       int (*free) (void *);
+};
+
+extern struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t *);
+extern void pnx4008_free_ll_entry(struct pnx4008_dma_ll *, dma_addr_t);
+extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *);
+
+extern int pnx4008_request_channel(char *, int,
+                                  void (*)(int, int, void *, struct pt_regs *),
+                                  void *);
+extern void pnx4008_free_channel(int);
+extern int pnx4008_config_dma(int, int, int);
+extern int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl *,
+                                   unsigned long *);
+extern int pnx4008_dma_parse_control(unsigned long,
+                                    struct pnx4008_dma_ch_ctrl *);
+extern int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config *,
+                                  unsigned long *);
+extern int pnx4008_dma_parse_config(unsigned long,
+                                   struct pnx4008_dma_ch_config *);
+extern int pnx4008_config_channel(int, struct pnx4008_dma_config *);
+extern int pnx4008_channel_get_config(int, struct pnx4008_dma_config *);
+extern int pnx4008_dma_ch_enable(int);
+extern int pnx4008_dma_ch_disable(int);
+extern int pnx4008_dma_ch_enabled(int);
+extern void pnx4008_dma_split_head_entry(struct pnx4008_dma_config *,
+                                        struct pnx4008_dma_ch_ctrl *);
+extern void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll *,
+                                      struct pnx4008_dma_ch_ctrl *);
+
+#endif                         /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-pnx4008/entry-macro.S b/include/asm-arm/arch-pnx4008/entry-macro.S
new file mode 100644 (file)
index 0000000..c1c198e
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * include/asm-arm/arch-pnx4008/entry-macro.S
+ *
+ * Low-level IRQ helper macros for PNX4008-based platforms
+ *
+ * 2005-2006 (c) MontaVista Software, Inc.
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ * 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 "platform.h"
+
+#define IO_BASE         0xF0000000
+#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
+
+#define INTRC_MASK                     0x00
+#define INTRC_RAW_STAT                 0x04
+#define INTRC_STAT                     0x08
+#define INTRC_POLAR                    0x0C
+#define INTRC_ACT_TYPE                 0x10
+#define INTRC_TYPE                     0x14
+
+#define SIC1_BASE_INT   32
+#define SIC2_BASE_INT   64
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+/* decode the MIC interrupt numbers */
+               ldr     \base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
+               ldr     \irqstat, [\base, #INTRC_STAT]
+
+               cmp     \irqstat,#1<<16
+               movhs   \irqnr,#16
+               movlo   \irqnr,#0
+               movhs   \irqstat,\irqstat,lsr#16
+               cmp     \irqstat,#1<<8
+               addhs   \irqnr,\irqnr,#8
+               movhs   \irqstat,\irqstat,lsr#8
+               cmp     \irqstat,#1<<4
+               addhs   \irqnr,\irqnr,#4
+               movhs   \irqstat,\irqstat,lsr#4
+               cmp     \irqstat,#1<<2
+               addhs   \irqnr,\irqnr,#2
+               movhs   \irqstat,\irqstat,lsr#2
+               cmp     \irqstat,#1<<1
+               addhs   \irqnr,\irqnr,#1
+
+/* was there an interrupt ? if not then drop out with EQ status */
+               teq     \irqstat,#0
+               beq     1003f
+
+/* and now check for extended IRQ reasons */
+               cmp     \irqnr,#1
+               bls     1003f
+               cmp     \irqnr,#30
+               blo     1002f
+
+/* IRQ 31,30  : High priority cascade IRQ handle */
+/* read the correct SIC */
+/* decoding status after compare : eq is 30 (SIC1) , ne is 31 (SIC2) */
+/* set the base IRQ number */
+               ldreq   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+               moveq  \irqnr,#SIC1_BASE_INT
+               ldrne   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+               movne   \irqnr,#SIC2_BASE_INT
+               ldr     \irqstat, [\base, #INTRC_STAT]
+               ldr     \tmp,     [\base, #INTRC_TYPE]
+/* and with inverted mask : low priority interrupts  */
+               and     \irqstat,\irqstat,\tmp
+               b       1004f
+
+1003:
+/* IRQ 1,0  : Low priority cascade IRQ handle */
+/* read the correct SIC */
+/* decoding status after compare : eq is 1 (SIC2) , ne is 0 (SIC1)*/
+/* read the correct SIC */
+/* set the base IRQ number  */
+               ldrne   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+               movne   \irqnr,#SIC1_BASE_INT
+               ldreq   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+               moveq   \irqnr,#SIC2_BASE_INT
+               ldr     \irqstat, [\base, #INTRC_STAT]
+               ldr     \tmp,     [\base, #INTRC_TYPE]
+/* and with inverted mask : low priority interrupts  */
+               bic     \irqstat,\irqstat,\tmp
+
+1004:
+
+               cmp     \irqstat,#1<<16
+               addhs   \irqnr,\irqnr,#16
+               movhs   \irqstat,\irqstat,lsr#16
+               cmp     \irqstat,#1<<8
+               addhs   \irqnr,\irqnr,#8
+               movhs   \irqstat,\irqstat,lsr#8
+               cmp     \irqstat,#1<<4
+               addhs   \irqnr,\irqnr,#4
+               movhs   \irqstat,\irqstat,lsr#4
+               cmp     \irqstat,#1<<2
+               addhs   \irqnr,\irqnr,#2
+               movhs   \irqstat,\irqstat,lsr#2
+               cmp     \irqstat,#1<<1
+               addhs   \irqnr,\irqnr,#1
+
+
+/* is irqstat not zero */
+
+1002:
+/* we assert that irqstat is not equal to zero and return ne status if true*/
+               teq     \irqstat,#0
+1003:
+               .endm
+
+
+               .macro  irq_prio_table
+               .endm
+
+
diff --git a/include/asm-arm/arch-pnx4008/gpio.h b/include/asm-arm/arch-pnx4008/gpio.h
new file mode 100644 (file)
index 0000000..d01bf83
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * include/asm-arm/arch-pnx4008/gpio.h
+ *
+ * PNX4008 GPIO driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _PNX4008_GPIO_H_
+#define _PNX4008_GPIO_H_
+
+
+/* Block numbers */
+#define GPIO_IN                (0)
+#define GPIO_OUT               (0x100)
+#define GPIO_BID               (0x200)
+#define GPIO_RAM               (0x300)
+#define GPIO_MUX               (0x400)
+
+#define GPIO_TYPE_MASK(K) ((K) & 0x700)
+
+/* INPUT GPIOs */
+/* GPI */
+#define GPI_00         (GPIO_IN | 0)
+#define GPI_01         (GPIO_IN | 1)
+#define GPI_02         (GPIO_IN | 2)
+#define GPI_03                 (GPIO_IN | 3)
+#define GPI_04         (GPIO_IN | 4)
+#define GPI_05         (GPIO_IN | 5)
+#define GPI_06         (GPIO_IN | 6)
+#define GPI_07         (GPIO_IN | 7)
+#define GPI_08         (GPIO_IN | 8)
+#define GPI_09         (GPIO_IN | 9)
+#define U1_RX          (GPIO_IN | 15)
+#define U2_HTCS        (GPIO_IN | 16)
+#define U2_RX          (GPIO_IN | 17)
+#define U3_RX          (GPIO_IN | 18)
+#define U4_RX          (GPIO_IN | 19)
+#define U5_RX          (GPIO_IN | 20)
+#define U6_IRRX        (GPIO_IN | 21)
+#define U7_HCTS        (GPIO_IN | 22)
+#define U7_RX          (GPIO_IN | 23)
+/* MISC IN */
+#define SPI1_DATIN     (GPIO_IN | 25)
+#define DISP_SYNC      (GPIO_IN | 26)
+#define SPI2_DATIN     (GPIO_IN | 27)
+#define GPI_11         (GPIO_IN | 28)
+
+#define GPIO_IN_MASK   0x1eff83ff
+
+/* OUTPUT GPIOs */
+/* GPO */
+#define GPO_00         (GPIO_OUT | 0)
+#define GPO_01         (GPIO_OUT | 1)
+#define GPO_02         (GPIO_OUT | 2)
+#define GPO_03                 (GPIO_OUT | 3)
+#define GPO_04         (GPIO_OUT | 4)
+#define GPO_05         (GPIO_OUT | 5)
+#define GPO_06         (GPIO_OUT | 6)
+#define GPO_07         (GPIO_OUT | 7)
+#define GPO_08         (GPIO_OUT | 8)
+#define GPO_09         (GPIO_OUT | 9)
+#define GPO_10         (GPIO_OUT | 10)
+#define GPO_11                 (GPIO_OUT | 11)
+#define GPO_12         (GPIO_OUT | 12)
+#define GPO_13         (GPIO_OUT | 13)
+#define GPO_14         (GPIO_OUT | 14)
+#define GPO_15         (GPIO_OUT | 15)
+#define GPO_16         (GPIO_OUT | 16)
+#define GPO_17                 (GPIO_OUT | 17)
+#define GPO_18         (GPIO_OUT | 18)
+#define GPO_19         (GPIO_OUT | 19)
+#define GPO_20         (GPIO_OUT | 20)
+#define GPO_21         (GPIO_OUT | 21)
+#define GPO_22         (GPIO_OUT | 22)
+#define GPO_23         (GPIO_OUT | 23)
+
+#define GPIO_OUT_MASK   0xffffff
+
+/* BIDIRECTIONAL GPIOs */
+/* RAM pins */
+#define RAM_D19                (GPIO_RAM | 0)
+#define RAM_D20        (GPIO_RAM | 1)
+#define RAM_D21        (GPIO_RAM | 2)
+#define RAM_D22        (GPIO_RAM | 3)
+#define RAM_D23        (GPIO_RAM | 4)
+#define RAM_D24        (GPIO_RAM | 5)
+#define RAM_D25        (GPIO_RAM | 6)
+#define RAM_D26        (GPIO_RAM | 7)
+#define RAM_D27                (GPIO_RAM | 8)
+#define RAM_D28        (GPIO_RAM | 9)
+#define RAM_D29        (GPIO_RAM | 10)
+#define RAM_D30        (GPIO_RAM | 11)
+#define RAM_D31        (GPIO_RAM | 12)
+
+#define GPIO_RAM_MASK   0x1fff
+
+/* I/O pins */
+#define GPIO_00        (GPIO_BID | 25)
+#define GPIO_01        (GPIO_BID | 26)
+#define GPIO_02        (GPIO_BID | 27)
+#define GPIO_03        (GPIO_BID | 28)
+#define GPIO_04        (GPIO_BID | 29)
+#define GPIO_05        (GPIO_BID | 30)
+
+#define GPIO_BID_MASK   0x7e000000
+
+/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
+#define GPIO_SDRAM_SEL         (GPIO_MUX | 3)
+
+#define GPIO_MUX_MASK   0x8
+
+/* Extraction/assembly macros */
+#define GPIO_BIT_MASK(K) ((K) & 0x1F)
+#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
+#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
+#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
+#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
+#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
+#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+#define SE_USB_OTG_ATX_INT_N    19
+/*18 unused*/
+#define SE_DSP_GPIO4_INT        17
+#define SE_KEY_IRQ              16
+#define SE_DSP_SLAVEPORT_INT    15
+#define SE_DSP_GPIO1_INT        14
+#define SE_DSP_GPIO0_INT        13
+#define SE_DSP_AHB_INT          12
+/*11-6 unused*/
+#define SE_GPIO_05_INT          5
+#define SE_GPIO_04_INT          4
+#define SE_GPIO_03_INT          3
+#define SE_GPIO_02_INT          2
+#define SE_GPIO_01_INT          1
+#define SE_GPIO_00_INT          0
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern int pnx4008_gpio_register_pin(unsigned short pin);
+extern int pnx4008_gpio_unregister_pin(unsigned short pin);
+extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
+extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
+extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
+extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
+
+static inline void start_int_umask(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
+                    START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_mask(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
+                    ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_ack(u8 irq)
+{
+       __raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
+}
+
+static inline void start_int_set_falling_edge(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
+                    ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+static inline void start_int_set_rising_edge(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
+                    START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+#endif                         /* _PNX4008_GPIO_H_ */
diff --git a/include/asm-arm/arch-pnx4008/hardware.h b/include/asm-arm/arch-pnx4008/hardware.h
new file mode 100644 (file)
index 0000000..a441039
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/hardware.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc. <source@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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include <asm/arch/platform.h>
+
+/* Start of virtual addresses for IO devices */
+#define IO_BASE         0xF0000000
+
+/* This macro relies on fact that for all HW i/o addresses bits 20-23 are 0 */
+#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/io.h b/include/asm-arm/arch-pnx4008/io.h
new file mode 100644 (file)
index 0000000..29ee439
--- /dev/null
@@ -0,0 +1,21 @@
+
+/*
+ *  include/asm-arm/arch-pnx4008/io.h
+ *
+ * Author: Dmitry Chigirev <chigirev@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)                        ((void __iomem *)(a))
+#define __mem_pci(a)           (a)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/irq.h b/include/asm-arm/arch-pnx4008/irq.h
new file mode 100644 (file)
index 0000000..fabff5d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * include/asm-arm/arch-pnx4008/irq.h
+ *
+ * PNX4008 IRQ controller driver - header file
+ * this one is used in entry-arnv.S as well so it cannot contain C code
+ *
+ * Copyright (c) 2005 Philips Semiconductors
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#ifndef __PNX4008_IRQ_H__
+#define __PNX4008_IRQ_H__
+
+#define MIC_VA_BASE             IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
+#define SIC1_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+#define SIC2_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+
+/* Manual: Chapter 20, page 195 */
+
+#define INTC_BIT(irq) (1<< ((irq) & 0x1F))
+
+#define INTC_ER(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x0 + (((irq)&(0x3<<5))<<9)))
+#define INTC_RSR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x4 + (((irq)&(0x3<<5))<<9)))
+#define INTC_SR(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x8 + (((irq)&(0x3<<5))<<9)))
+#define INTC_APR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0xC + (((irq)&(0x3<<5))<<9)))
+#define INTC_ATR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x10 + (((irq)&(0x3<<5))<<9)))
+#define INTC_ITR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x14 + (((irq)&(0x3<<5))<<9)))
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern void __init pnx4008_init_irq(void);
+
+#endif /* __PNX4008_IRQ_H__ */
diff --git a/include/asm-arm/arch-pnx4008/irqs.h b/include/asm-arm/arch-pnx4008/irqs.h
new file mode 100644 (file)
index 0000000..13ec7ed
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * include/asm-arm/arch-pnx4008/irqs.h
+ *
+ * PNX4008 IRQ controller driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PNX4008_IRQS_h__
+#define __PNX4008_IRQS_h__
+
+#define NR_IRQS         96
+
+/*Manual: table 259, page 199*/
+
+/*SUB2 Interrupt Routing (SIC2)*/
+
+#define SIC2_BASE_INT   64
+
+#define CLK_SWITCH_ARM_INT 95  /*manual: Clkswitch ARM  */
+#define CLK_SWITCH_DSP_INT 94  /*manual: ClkSwitch DSP  */
+#define CLK_SWITCH_AUD_INT 93  /*manual: Clkswitch AUD  */
+#define GPI_06_INT         92
+#define GPI_05_INT         91
+#define GPI_04_INT         90
+#define GPI_03_INT         89
+#define GPI_02_INT         88
+#define GPI_01_INT         87
+#define GPI_00_INT         86
+#define BT_CLKREQ_INT      85
+#define SPI1_DATIN_INT     84
+#define U5_RX_INT          83
+#define SDIO_INT_N         82
+#define CAM_HS_INT         81
+#define CAM_VS_INT         80
+#define GPI_07_INT         79
+#define DISP_SYNC_INT      78
+#define DSP_INT8           77
+#define U7_HCTS_INT        76
+#define GPI_10_INT         75
+#define GPI_09_INT         74
+#define GPI_08_INT         73
+#define DSP_INT7           72
+#define U2_HCTS_INT        71
+#define SPI2_DATIN_INT     70
+#define GPIO_05_INT        69
+#define GPIO_04_INT        68
+#define GPIO_03_INT        67
+#define GPIO_02_INT        66
+#define GPIO_01_INT        65
+#define GPIO_00_INT        64
+
+/*Manual: table 258, page 198*/
+
+/*SUB1 Interrupt Routing (SIC1)*/
+
+#define SIC1_BASE_INT   32
+
+#define USB_I2C_INT        63
+#define USB_DEV_HP_INT     62
+#define USB_DEV_LP_INT     61
+#define USB_DEV_DMA_INT    60
+#define USB_HOST_INT       59
+#define USB_OTG_ATX_INT_N  58
+#define USB_OTG_TIMER_INT  57
+#define SW_INT             56
+#define SPI1_INT           55
+#define KEY_IRQ            54
+#define DSP_M_INT          53
+#define RTC_INT            52
+#define I2C_1_INT          51
+#define I2C_2_INT          50
+#define PLL1_LOCK_INT      49
+#define PLL2_LOCK_INT      48
+#define PLL3_LOCK_INT      47
+#define PLL4_LOCK_INT      46
+#define PLL5_LOCK_INT      45
+#define SPI2_INT           44
+#define DSP_INT1           43
+#define DSP_INT2           42
+#define DSP_TDM_INT2       41
+#define TS_AUX_INT         40
+#define TS_IRQ             39
+#define TS_P_INT           38
+#define UOUT1_TO_PAD_INT   37
+#define GPI_11_INT         36
+#define DSP_INT4           35
+#define JTAG_COMM_RX_INT   34
+#define JTAG_COMM_TX_INT   33
+#define DSP_INT3           32
+
+/*Manual: table 257, page 197*/
+
+/*MAIN Interrupt Routing*/
+
+#define MAIN_BASE_INT   0
+
+#define SUB2_FIQ_N         31  /*active low */
+#define SUB1_FIQ_N         30  /*active low */
+#define JPEG_INT           29
+#define DMA_INT            28
+#define MSTIMER_INT        27
+#define IIR1_INT           26
+#define IIR2_INT           25
+#define IIR7_INT           24
+#define DSP_TDM_INT0       23
+#define DSP_TDM_INT1       22
+#define DSP_P_INT          21
+#define DSP_INT0           20
+#define DUM_INT            19
+#define UOUT0_TO_PAD_INT   18
+#define MP4_ENC_INT        17
+#define MP4_DEC_INT        16
+#define SD0_INT            15
+#define MBX_INT            14
+#define SD1_INT            13
+#define MS_INT_N           12
+#define FLASH_INT          11 /*NAND*/
+#define IIR6_INT           10
+#define IIR5_INT           9
+#define IIR4_INT           8
+#define IIR3_INT           7
+#define WATCH_INT          6
+#define HSTIMER_INT        5
+#define ARCH_TIMER_IRQ     HSTIMER_INT
+#define CAM_INT            4
+#define PRNG_INT           3
+#define CRYPTO_INT         2
+#define SUB2_IRQ_N         1   /*active low */
+#define SUB1_IRQ_N         0   /*active low */
+
+#define PNX4008_IRQ_TYPES \
+{                                           /*IRQ #'s: */         \
+IRQT_LOW,  IRQT_LOW,  IRQT_LOW,  IRQT_HIGH, /*  0, 1, 2, 3 */     \
+IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  4, 5, 6, 7 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  8, 9,10,11 */     \
+IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 12,13,14,15 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 16,17,18,19 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 20,21,22,23 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 24,25,26,27 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 28,29,30,31 */     \
+IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, /* 32,33,34,35 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_FALLING, IRQT_HIGH, /* 36,37,38,39 */  \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 40,41,42,43 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 44,45,46,47 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 48,49,50,51 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 52,53,54,55 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, /* 56,57,58,59 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 60,61,62,63 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 64,65,66,67 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 68,69,70,71 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 72,73,74,75 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 76,77,78,79 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 80,81,82,83 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 84,85,86,87 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 88,89,90,91 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 92,93,94,95 */     \
+}
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+
+#endif /* __PNX4008_IRQS_h__ */
diff --git a/include/asm-arm/arch-pnx4008/memory.h b/include/asm-arm/arch-pnx4008/memory.h
new file mode 100644 (file)
index 0000000..0d8268a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/memory.h
+ *
+ * Copyright (c) 2005 Philips Semiconductors
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET     (0x80000000)
+
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET - PHYS_OFFSET)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/param.h b/include/asm-arm/arch-pnx4008/param.h
new file mode 100644 (file)
index 0000000..95d5f54
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define HZ 100
diff --git a/include/asm-arm/arch-pnx4008/platform.h b/include/asm-arm/arch-pnx4008/platform.h
new file mode 100644 (file)
index 0000000..485a365
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * include/asm-arm/arch-pnx4008/platfrom.h
+ *
+ * PNX4008 Base addresses - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+
+#ifndef __ASM_ARCH_PLATFORM_H__
+#define __ASM_ARCH_PLATFORM_H__
+
+#define PNX4008_IRAM_BASE              0x08000000
+#define PNX4008_IRAM_SIZE              0x00010000
+#define PNX4008_YUV_SLAVE_BASE         0x10000000
+#define PNX4008_DUM_SLAVE_BASE         0x18000000
+#define PNX4008_NDF_FLASH_BASE         0x20020000
+#define PNX4008_SPI1_BASE              0x20088000
+#define PNX4008_SPI2_BASE              0x20090000
+#define PNX4008_SD_CONFIG_BASE         0x20098000
+#define PNX4008_FLASH_DATA             0x200B0000
+#define PNX4008_MLC_FLASH_BASE         0x200B8000
+#define PNX4008_JPEG_CONFIG_BASE       0x300A0000
+#define PNX4008_DMA_CONFIG_BASE                0x31000000
+#define PNX4008_USB_CONFIG_BASE                0x31020000
+#define PNX4008_SDRAM_CFG_BASE         0x31080000
+#define PNX4008_AHB2FAB_BASE           0x40000000
+#define PNX4008_PWRMAN_BASE            0x40004000
+#define PNX4008_INTCTRLMIC_BASE                0x40008000
+#define PNX4008_INTCTRLSIC1_BASE       0x4000C000
+#define PNX4008_INTCTRLSIC2_BASE       0x40010000
+#define PNX4008_HSUART1_BASE           0x40014000
+#define PNX4008_HSUART2_BASE           0x40018000
+#define PNX4008_HSUART7_BASE           0x4001C000
+#define PNX4008_RTC_BASE               0x40024000
+#define PNX4008_PIO_BASE               0x40028000
+#define PNX4008_MSTIMER_BASE           0x40034000
+#define PNX4008_HSTIMER_BASE           0x40038000
+#define PNX4008_WDOG_BASE              0x4003C000
+#define PNX4008_DEBUG_BASE             0x40040000
+#define PNX4008_TOUCH1_BASE            0x40048000
+#define PNX4008_KEYSCAN_BASE           0x40050000
+#define PNX4008_UARTCTRL_BASE          0x40054000
+#define PNX4008_PWM_BASE               0x4005C000
+#define PNX4008_UART3_BASE             0x40080000
+#define PNX4008_UART4_BASE             0x40088000
+#define PNX4008_UART5_BASE             0x40090000
+#define PNX4008_UART6_BASE             0x40098000
+#define PNX4008_I2C1_BASE              0x400A0000
+#define PNX4008_I2C2_BASE              0x400A8000
+#define PNX4008_MAGICGATE_BASE         0x400B0000
+#define PNX4008_DUMCONF_BASE           0x400B8000
+#define PNX4008_DUM_MAINCFG_BASE               0x400BC000
+#define PNX4008_DSP_BASE               0x400C0000
+#define PNX4008_PROFCOUNTER_BASE       0x400C8000
+#define PNX4008_CRYPTO_BASE            0x400D0000
+#define PNX4008_CAMIFCONF_BASE         0x400D8000
+#define PNX4008_YUV2RGB_BASE           0x400E0000
+#define PNX4008_AUDIOCONFIG_BASE       0x400E8000
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/pm.h b/include/asm-arm/arch-pnx4008/pm.h
new file mode 100644 (file)
index 0000000..bac1634
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-pnx4008/pm.h
+ *
+ * PNX4008 Power Management Routiness - header file
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARCH_PNX4008_PM_H
+#define __ASM_ARCH_PNX4008_PM_H
+
+#ifndef __ASSEMBLER__
+#include "irq.h"
+#include "irqs.h"
+#include "clock.h"
+
+extern void pnx4008_pm_idle(void);
+extern void pnx4008_pm_suspend(void);
+extern unsigned int pnx4008_cpu_suspend_sz;
+extern void pnx4008_cpu_suspend(void);
+extern unsigned int pnx4008_cpu_standby_sz;
+extern void pnx4008_cpu_standby(void);
+
+extern int pnx4008_startup_pll(struct clk *);
+extern int pnx4008_shutdown_pll(struct clk *);
+
+#endif                         /* ASSEMBLER */
+#endif                         /* __ASM_ARCH_PNX4008_PM_H */
diff --git a/include/asm-arm/arch-pnx4008/system.h b/include/asm-arm/arch-pnx4008/system.h
new file mode 100644 (file)
index 0000000..6e3da70
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/system.h
+ *
+ * Copyright (C) 2003 Philips Semiconductors
+ * Copyright (C) 2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+
+static void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       cpu_reset(0);
+}
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/timex.h b/include/asm-arm/arch-pnx4008/timex.h
new file mode 100644 (file)
index 0000000..ee470a3
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * include/asm-arm/arch-pnx4008/timex.h
+ *
+ * PNX4008 timers header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PNX4008_TIMEX_H
+#define __PNX4008_TIMEX_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#define CLOCK_TICK_RATE                1000000
+
+#define TICKS2USECS(x) (x)
+
+/* MilliSecond Timer - Chapter 21 Page 202 */
+
+#define MSTIM_INT     IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
+#define MSTIM_CTRL    IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
+#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
+#define MSTIM_MCTRL   IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
+#define MSTIM_MATCH0  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
+#define MSTIM_MATCH1  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
+
+/* High Speed Timer - Chpater 22, Page 205 */
+
+#define HSTIM_INT     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
+#define HSTIM_CTRL    IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
+#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
+#define HSTIM_PMATCH  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
+#define HSTIM_PCOUNT  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
+#define HSTIM_MCTRL   IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
+#define HSTIM_MATCH0  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
+#define HSTIM_MATCH1  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
+#define HSTIM_MATCH2  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
+#define HSTIM_CCR     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
+#define HSTIM_CR0     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
+#define HSTIM_CR1     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
+
+/* IMPORTANT: both timers are UPCOUNTING */
+
+/* xSTIM_MCTRL bit definitions */
+#define MR0_INT        1
+#define RESET_COUNT0   (1<<1)
+#define STOP_COUNT0    (1<<2)
+#define MR1_INT        (1<<3)
+#define RESET_COUNT1   (1<<4)
+#define STOP_COUNT1    (1<<5)
+#define MR2_INT        (1<<6)
+#define RESET_COUNT2   (1<<7)
+#define STOP_COUNT2    (1<<8)
+
+/* xSTIM_CTRL bit definitions */
+#define COUNT_ENAB     1
+#define RESET_COUNT    (1<<1)
+#define DEBUG_EN       (1<<2)
+
+/* xSTIM_INT bit definitions */
+#define MATCH0_INT     1
+#define MATCH1_INT     (1<<1)
+#define MATCH2_INT     (1<<2)
+#define RTC_TICK0      (1<<4)
+#define RTC_TICK1      (1<<5)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/uncompress.h b/include/asm-arm/arch-pnx4008/uncompress.h
new file mode 100644 (file)
index 0000000..8fa4d24
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/uncompress.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 UART5_BASE 0x40090000
+
+#define UART5_DR    (*(volatile unsigned char *) (UART5_BASE))
+#define UART5_FR    (*(volatile unsigned char *) (UART5_BASE + 18))
+
+static __inline__ void putc(char c)
+{
+       while (UART5_FR & (1 << 5))
+               barrier();
+
+       UART5_DR = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-pnx4008/vmalloc.h b/include/asm-arm/arch-pnx4008/vmalloc.h
new file mode 100644 (file)
index 0000000..140d925
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-pnx4008/vmalloc.h
+ *
+ * Author: Vitaly Wool <source@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-pxa/trizeps4.h b/include/asm-arm/arch-pxa/trizeps4.h
new file mode 100644 (file)
index 0000000..641d0ec
--- /dev/null
@@ -0,0 +1,106 @@
+/************************************************************************
+ * Include file for TRIZEPS4 SoM and ConXS eval-board
+ * Copyright (c) Jürgen Schindele
+ * 2006
+ ************************************************************************/
+
+/*
+ * Includes/Defines
+ */
+#ifndef _TRIPEPS4_H_
+#define _TRIPEPS4_H_
+
+/* physical memory regions */
+#define TRIZEPS4_FLASH_PHYS    (PXA_CS0_PHYS)  /* Flash region */
+#define TRIZEPS4_DISK_PHYS     (PXA_CS1_PHYS)  /* Disk On Chip region */
+#define TRIZEPS4_ETH_PHYS      (PXA_CS2_PHYS)  /* Ethernet DM9000 region */
+#define TRIZEPS4_PIC_PHYS      (PXA_CS3_PHYS)  /* Logic chip on ConXS-Board */
+#define TRIZEPS4_SDRAM_BASE    0xa0000000      /* SDRAM region */
+
+#define TRIZEPS4_CFSR_PHYS     (PXA_CS3_PHYS)                  /* Logic chip on ConXS-Board CSFR register */
+#define TRIZEPS4_BOCR_PHYS     (PXA_CS3_PHYS+0x02000000)       /* Logic chip on ConXS-Board BOCR register */
+#define TRIZEPS4_IRCR_PHYS     (PXA_CS3_PHYS+0x02400000)       /* Logic chip on ConXS-Board IRCR register*/
+#define TRIZEPS4_UPSR_PHYS     (PXA_CS3_PHYS+0x02800000)       /* Logic chip on ConXS-Board UPSR register*/
+#define TRIZEPS4_DICR_PHYS     (PXA_CS3_PHYS+0x03800000)       /* Logic chip on ConXS-Board DICR register*/
+
+/* virtual memory regions */
+#define TRIZEPS4_DISK_VIRT     0xF0000000      /* Disk On Chip region */
+
+#define TRIZEPS4_PIC_VIRT      0xF0100000      /* not used */
+#define TRIZEPS4_CFSR_VIRT     0xF0100000
+#define TRIZEPS4_BOCR_VIRT     0xF0200000
+#define TRIZEPS4_DICR_VIRT     0xF0300000
+#define TRIZEPS4_IRCR_VIRT     0xF0400000
+#define TRIZEPS4_UPSR_VIRT     0xF0500000
+
+/* size of flash */
+#define TRIZEPS4_FLASH_SIZE    0x02000000      /* Flash size 32 MB */
+
+/* Ethernet Controller Davicom DM9000 */
+#define GPIO_DM9000            101
+#define TRIZEPS4_ETH_IRQ       IRQ_GPIO(GPIO_DM9000)
+
+/* UCB1400 audio / TS-controller */
+#define GPIO_UCB1400           1
+#define TRIZEPS4_UCB1400_IRQ   IRQ_GPIO(GPIO_UCB1400)
+
+/* PCMCIA socket Compact Flash */
+#define GPIO_PCD               11              /* PCMCIA Card Detect */
+#define TRIZEPS4_CD_IRQ                IRQ_GPIO(GPIO_PCD)
+#define GPIO_PRDY              13              /* READY / nINT */
+#define TRIZEPS4_READY_NINT    IRQ_GPIO(GPIO_PRDY)
+
+/* MMC socket */
+#define GPIO_MMC_DET           12
+#define TRIZEPS4_MMC_IRQ       IRQ_GPIO(GPIO_MMC_DET)
+
+/* LEDS using tx2 / rx2 */
+#define GPIO_SYS_BUSY_LED      46
+#define GPIO_HEARTBEAT_LED     47
+
+/* Off-module PIC on ConXS board */
+#define GPIO_PIC               0
+#define TRIZEPS4_PIC_IRQ       IRQ_GPIO(GPIO_PIC)
+
+#define CFSR_P2V(x)            ((x) - TRIZEPS4_CFSR_PHYS + TRIZEPS4_CFSR_VIRT)
+#define CFSR_V2P(x)            ((x) - TRIZEPS4_CFSR_VIRT + TRIZEPS4_CFSR_PHYS)
+
+#define BCR_P2V(x)             ((x) - TRIZEPS4_BOCR_PHYS + TRIZEPS4_BOCR_VIRT)
+#define BCR_V2P(x)             ((x) - TRIZEPS4_BOCR_VIRT + TRIZEPS4_BOCR_PHYS)
+
+#define DCR_P2V(x)             ((x) - TRIZEPS4_DICR_PHYS + TRIZEPS4_DICR_VIRT)
+#define DCR_V2P(x)             ((x) - TRIZEPS4_DICR_VIRT + TRIZEPS4_DICR_PHYS)
+
+#ifndef __ASSEMBLY__
+#define ConXS_CFSR             (*((volatile unsigned short *)CFSR_P2V(0x0C000000)))
+#define ConXS_BCR              (*((volatile unsigned short *)BCR_P2V(0x0E000000)))
+#define ConXS_DCR              (*((volatile unsigned short *)DCR_P2V(0x0F800000)))
+#else
+#define ConXS_CFSR             CFSR_P2V(0x0C000000)
+#define ConXS_BCR              BCR_P2V(0x0E000000)
+#define ConXS_DCR              DCR_P2V(0x0F800000)
+#endif
+
+#define ConXS_CFSR_BVD_MASK    0x0003
+#define ConXS_CFSR_BVD1                (1 << 0)
+#define ConXS_CFSR_BVD2                (1 << 1)
+#define ConXS_CFSR_VS_MASK     0x000C
+#define ConXS_CFSR_VS1         (1 << 2)
+#define ConXS_CFSR_VS2         (1 << 3)
+#define ConXS_CFSR_VS_5V       (0x3 << 2)
+#define ConXS_CFSR_VS_3V3      0x0
+
+#define ConXS_BCR_S0_POW_EN0   (1 << 0)
+#define ConXS_BCR_S0_POW_EN1   (1 << 1)
+#define ConXS_BCR_L_DISP       (1 << 4)
+#define ConXS_BCR_CF_BUF_EN    (1 << 5)
+#define ConXS_BCR_CF_RESET     (1 << 7)
+#define ConXS_BCR_S0_VCC_3V3   0x1
+#define ConXS_BCR_S0_VCC_5V0   0x2
+#define ConXS_BCR_S0_VPP_12V   0x4
+#define ConXS_BCR_S0_VPP_3V3   0x8
+
+#define ConXS_IRCR_MODE                (1 << 0)
+#define ConXS_IRCR_SD          (1 << 1)
+
+#endif /* _TRIPEPS4_H_ */
diff --git a/include/asm-arm/arch-s3c2410/regs-power.h b/include/asm-arm/arch-s3c2410/regs-power.h
new file mode 100644 (file)
index 0000000..6c319ea
--- /dev/null
@@ -0,0 +1,34 @@
+/* linux/include/asm/arch-s3c2410/regs-power.h
+ *
+ * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk>
+ *                   http://armlinux.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.
+ *
+ * S3C24XX power control register definitions
+*/
+
+#ifndef __ASM_ARM_REGS_PWR
+#define __ASM_ARM_REGS_PWR __FILE__
+
+#define S3C24XX_PWRREG(x) ((x) + S3C24XX_VA_CLKPWR)
+
+#define S3C2412_PWRMODECON     S3C24XX_PWRREG(0x20)
+#define S3C2412_PWRCFG         S3C24XX_PWRREG(0x24)
+
+#define S3C2412_PWRCFG_BATF_IGNORE             (0<<0)
+#define S3C2412_PWRCFG_BATF_SLEEP              (3<<0)
+#define S3C2412_PWRCFG_BATF_MASK               (3<<0)
+
+#define S3C2412_PWRCFG_STANDBYWFI_IGNORE       (0<<6)
+#define S3C2412_PWRCFG_STANDBYWFI_IDLE         (1<<6)
+#define S3C2412_PWRCFG_STANDBYWFI_STOP         (2<<6)
+#define S3C2412_PWRCFG_STANDBYWFI_SLEEP                (3<<6)
+#define S3C2412_PWRCFG_STANDBYWFI_MASK         (3<<6)
+
+#define S3C2412_PWRCFG_RTC_MASKIRQ             (1<<8)
+#define S3C2412_PWRCFG_NAND_NORST              (1<<9)
+
+#endif /* __ASM_ARM_REGS_PWR */
diff --git a/include/asm-arm/dyntick.h b/include/asm-arm/dyntick.h
new file mode 100644 (file)
index 0000000..19fab2d
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASMARM_DYNTICK_H
+#define _ASMARM_DYNTICK_H
+
+#include <asm/mach/time.h>
+
+#endif /* _ASMARM_DYNTICK_H */
diff --git a/include/asm-arm/hw_irq.h b/include/asm-arm/hw_irq.h
new file mode 100644 (file)
index 0000000..ea85697
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Nothing to see here yet
+ */
+#ifndef _ARCH_ARM_HW_IRQ_H
+#define _ARCH_ARM_HW_IRQ_H
+
+#include <asm/mach/irq.h>
+
+#if defined(CONFIG_NO_IDLE_HZ)
+# include <asm/dyntick.h>
+# define handle_dynamic_tick(action)                                   \
+       if (!(action->flags & IRQF_TIMER) && system_timer->dyn_tick) {  \
+               write_seqlock(&xtime_lock);                             \
+               if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)   \
+                       system_timer->dyn_tick->handler(irq, 0, regs);  \
+               write_sequnlock(&xtime_lock);                           \
+       }
+#endif
+
+#endif
diff --git a/include/asm-arm/mach/serial_at91.h b/include/asm-arm/mach/serial_at91.h
new file mode 100644 (file)
index 0000000..1290bb3
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  linux/include/asm-arm/mach/serial_at91.h
+ *
+ *  Based on serial_sa1100.h  by Nicolas Pitre
+ *
+ *  Copyright (C) 2002 ATMEL Rousset
+ *
+ *  Low level machine dependent UART functions.
+ */
+
+struct uart_port;
+
+/*
+ * This is a temporary structure for registering these
+ * functions; it is intended to be discarded after boot.
+ */
+struct at91_port_fns {
+       void    (*set_mctrl)(struct uart_port *, u_int);
+       u_int   (*get_mctrl)(struct uart_port *);
+       void    (*enable_ms)(struct uart_port *);
+       void    (*pm)(struct uart_port *, u_int, u_int);
+       int     (*set_wake)(struct uart_port *, u_int);
+       int     (*open)(struct uart_port *);
+       void    (*close)(struct uart_port *);
+};
+
+#if defined(CONFIG_SERIAL_AT91)
+void at91_register_uart_fns(struct at91_port_fns *fns);
+#else
+#define at91_register_uart_fns(fns) do { } while (0)
+#endif
+
+
diff --git a/include/asm-arm/page-nommu.h b/include/asm-arm/page-nommu.h
new file mode 100644 (file)
index 0000000..a1bcad0
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  linux/include/asm-arm/page-nommu.h
+ *
+ *  Copyright (C) 2004 Hyok S. Choi
+ *
+ * This program is free software; you can 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 _ASMARM_PAGE_NOMMU_H
+#define _ASMARM_PAGE_NOMMU_H
+
+#if !defined(CONFIG_SMALL_TASKS) && PAGE_SHIFT < 13
+#define KTHREAD_SIZE (8192)
+#else
+#define KTHREAD_SIZE PAGE_SIZE
+#endif
+#define get_user_page(vaddr)           __get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)     free_page(addr)
+
+#define clear_page(page)       memset((page), 0, PAGE_SIZE)
+#define copy_page(to,from)     memcpy((to), (from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr, pg)       clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t[2];
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)     ((x)[0])
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)        (x)
+#define __pgprot(x)     (x)
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
+#endif
diff --git a/include/asm-arm/pgtable-nommu.h b/include/asm-arm/pgtable-nommu.h
new file mode 100644 (file)
index 0000000..c1b264d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  linux/include/asm-arm/pgtable-nommu.h
+ *
+ *  Copyright (C) 1995-2002 Russell King
+ *  Copyright (C) 2004  Hyok S. Choi
+ *
+ * This program is free software; you can 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 _ASMARM_PGTABLE_NOMMU_H
+#define _ASMARM_PGTABLE_NOMMU_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/slab.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+/*
+ * Trivial page table functions.
+ */
+#define pgd_present(pgd)       (1)
+#define pgd_none(pgd)          (0)
+#define pgd_bad(pgd)           (0)
+#define pgd_clear(pgdp)
+#define kern_addr_valid(addr)  (1)
+#define        pmd_offset(a, b)        ((void *)0)
+/* FIXME */
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PGDIR_SHIFT            21
+
+#define PGDIR_SIZE             (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK             (~(PGDIR_SIZE-1))
+/* FIXME */
+
+#define PAGE_NONE      __pgprot(0)
+#define PAGE_SHARED    __pgprot(0)
+#define PAGE_COPY      __pgprot(0)
+#define PAGE_READONLY  __pgprot(0)
+#define PAGE_KERNEL    __pgprot(0)
+
+//extern void paging_init(struct meminfo *, struct machine_desc *);
+#define swapper_pg_dir ((pgd_t *) 0)
+
+#define __swp_type(x)          (0)
+#define __swp_offset(x)                (0)
+#define __swp_entry(typ,off)   ((swp_entry_t) { ((typ) | ((off) << 7)) })
+#define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
+
+
+typedef pte_t *pte_addr_t;
+
+static inline int pte_file(pte_t pte) { return 0; }
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+#define ZERO_PAGE(vaddr)       (virt_to_page(0))
+
+/*
+ * Mark the prot value as uncacheable and unbufferable.
+ */
+#define pgprot_noncached(prot) __pgprot(0)
+#define pgprot_writecombine(prot) __pgprot(0)
+
+
+/*
+ * These would be in other places but having them here reduces the diffs.
+ */
+extern unsigned int kobjsize(const void *objp);
+extern int is_in_rom(unsigned long);
+
+/*
+ * No page table caches to initialise.
+ */
+#define pgtable_cache_init()   do { } while (0)
+#define io_remap_page_range    remap_page_range
+#define io_remap_pfn_range     remap_pfn_range
+
+#define MK_IOSPACE_PFN(space, pfn)     (pfn)
+#define GET_IOSPACE(pfn)               0
+#define GET_PFN(pfn)                   (pfn)
+
+
+/*
+ * All 32bit addresses are effectively valid for vmalloc...
+ * Sort of meaningless for non-VM targets.
+ */
+#define        VMALLOC_START   0
+#define        VMALLOC_END     0xffffffff
+
+#define FIRST_USER_ADDRESS      (0)
+
+#else 
+
+/*
+ * dummy tlb and user structures.
+ */
+#define v3_tlb_fns     (0)
+#define v4_tlb_fns     (0)
+#define v4wb_tlb_fns   (0)
+#define v4wbi_tlb_fns  (0)
+#define v6_tlb_fns     (0)
+
+#define v3_user_fns    (0)
+#define v4_user_fns    (0)
+#define v4_mc_user_fns (0)
+#define v4wb_user_fns  (0)
+#define v4wt_user_fns  (0)
+#define v6_user_fns    (0)
+#define xscale_mc_user_fns (0)
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* _ASMARM_PGTABLE_H */
diff --git a/include/asm-arm/thread_notify.h b/include/asm-arm/thread_notify.h
new file mode 100644 (file)
index 0000000..8866e52
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  linux/include/asm-arm/thread_notify.h
+ *
+ *  Copyright (C) 2006 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASMARM_THREAD_NOTIFY_H
+#define ASMARM_THREAD_NOTIFY_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <linux/notifier.h>
+#include <asm/thread_info.h>
+
+static inline int thread_register_notifier(struct notifier_block *n)
+{
+       extern struct atomic_notifier_head thread_notify_head;
+       return atomic_notifier_chain_register(&thread_notify_head, n);
+}
+
+static inline void thread_unregister_notifier(struct notifier_block *n)
+{
+       extern struct atomic_notifier_head thread_notify_head;
+       atomic_notifier_chain_unregister(&thread_notify_head, n);
+}
+
+static inline void thread_notify(unsigned long rc, struct thread_info *thread)
+{
+       extern struct atomic_notifier_head thread_notify_head;
+       atomic_notifier_call_chain(&thread_notify_head, rc, thread);
+}
+
+#endif
+
+/*
+ * These are the reason codes for the thread notifier.
+ */
+#define THREAD_NOTIFY_FLUSH    0
+#define THREAD_NOTIFY_RELEASE  1
+#define THREAD_NOTIFY_SWITCH   2
+
+#endif
+#endif
diff --git a/include/asm-cris/Kbuild b/include/asm-cris/Kbuild
new file mode 100644 (file)
index 0000000..14498d5
--- /dev/null
@@ -0,0 +1,5 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += arch-v10/ arch-v32/
+
+unifdef-y += rs485.h
diff --git a/include/asm-cris/arch-v10/Kbuild b/include/asm-cris/arch-v10/Kbuild
new file mode 100644 (file)
index 0000000..d7f27dc
--- /dev/null
@@ -0,0 +1,2 @@
+header-y += ptrace.h
+header-y += user.h
diff --git a/include/asm-cris/arch-v32/Kbuild b/include/asm-cris/arch-v32/Kbuild
new file mode 100644 (file)
index 0000000..d7f27dc
--- /dev/null
@@ -0,0 +1,2 @@
+header-y += ptrace.h
+header-y += user.h
diff --git a/include/asm-frv/Kbuild b/include/asm-frv/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
new file mode 100644 (file)
index 0000000..3c06be3
--- /dev/null
@@ -0,0 +1,12 @@
+header-y += atomic.h
+header-y += errno-base.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ipc.h
+header-y += mman.h
+header-y += signal.h
+header-y += statfs.h
+
+unifdef-y += resource.h
+unifdef-y += siginfo.h
diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm
new file mode 100644 (file)
index 0000000..a84c3d8
--- /dev/null
@@ -0,0 +1,34 @@
+unifdef-y += a.out.h
+unifdef-y += auxvec.h
+unifdef-y += byteorder.h
+unifdef-y += errno.h
+unifdef-y += fcntl.h
+unifdef-y += ioctl.h
+unifdef-y += ioctls.h
+unifdef-y += ipcbuf.h
+unifdef-y += mman.h
+unifdef-y += msgbuf.h
+unifdef-y += param.h
+unifdef-y += poll.h
+unifdef-y += posix_types.h
+unifdef-y += ptrace.h
+unifdef-y += resource.h
+unifdef-y += sembuf.h
+unifdef-y += shmbuf.h
+unifdef-y += sigcontext.h
+unifdef-y += siginfo.h
+unifdef-y += signal.h
+unifdef-y += socket.h
+unifdef-y += sockios.h
+unifdef-y += stat.h
+unifdef-y += statfs.h
+unifdef-y += termbits.h
+unifdef-y += termios.h
+unifdef-y += types.h
+unifdef-y += unistd.h
+unifdef-y += user.h
+
+# These probably shouldn't be exported
+unifdef-y += shmparam.h
+unifdef-y += elf.h
+unifdef-y += page.h
diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h
new file mode 100644 (file)
index 0000000..5076455
--- /dev/null
@@ -0,0 +1,22 @@
+__NR_chmod,
+__NR_fchmod,
+#ifdef __NR_chown
+__NR_chown,
+__NR_fchown,
+__NR_lchown,
+#endif
+__NR_setxattr,
+__NR_lsetxattr,
+__NR_fsetxattr,
+__NR_removexattr,
+__NR_lremovexattr,
+__NR_fremovexattr,
+#ifdef __NR_fchownat
+__NR_fchownat,
+__NR_fchmodat,
+#endif
+#ifdef __NR_chown32
+__NR_chown32,
+__NR_fchown32,
+__NR_lchown32,
+#endif
diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h
new file mode 100644 (file)
index 0000000..6621bd8
--- /dev/null
@@ -0,0 +1,18 @@
+__NR_rename,
+__NR_mkdir,
+__NR_rmdir,
+#ifdef __NR_creat
+__NR_creat,
+#endif
+__NR_link,
+__NR_unlink,
+__NR_symlink,
+__NR_mknod,
+#ifdef __NR_mkdirat
+__NR_mkdirat,
+__NR_mknodat,
+__NR_unlinkat,
+__NR_renameat,
+__NR_linkat,
+__NR_symlinkat,
+#endif
diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_read.h
new file mode 100644 (file)
index 0000000..0e87464
--- /dev/null
@@ -0,0 +1,8 @@
+__NR_readlink,
+__NR_quotactl,
+__NR_listxattr,
+__NR_llistxattr,
+__NR_flistxattr,
+__NR_getxattr,
+__NR_lgetxattr,
+__NR_fgetxattr,
diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h
new file mode 100644 (file)
index 0000000..f10d367
--- /dev/null
@@ -0,0 +1,11 @@
+#include <asm-generic/audit_dir_write.h>
+__NR_acct,
+__NR_swapon,
+__NR_quotactl,
+__NR_truncate,
+#ifdef __NR_truncate64
+__NR_truncate64,
+#endif
+#ifdef __NR_bind
+__NR_bind,             /* bind can affect fs object only in one way... */
+#endif
diff --git a/include/asm-h8300/Kbuild b/include/asm-h8300/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-i386/Kbuild b/include/asm-i386/Kbuild
new file mode 100644 (file)
index 0000000..b75a348
--- /dev/null
@@ -0,0 +1,10 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += boot.h
+header-y += debugreg.h
+header-y += ldt.h
+header-y += ucontext.h
+
+unifdef-y += mtrr.h
+unifdef-y += setup.h
+unifdef-y += vm86.h
diff --git a/include/asm-i386/dwarf2.h b/include/asm-i386/dwarf2.h
new file mode 100644 (file)
index 0000000..5d1a8db
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _DWARF2_H
+#define _DWARF2_H
+
+#ifndef __ASSEMBLY__
+#warning "asm/dwarf2.h should be only included in pure assembly files"
+#endif
+
+/*
+   Macros for dwarf2 CFI unwind table entries.
+   See "as.info" for details on these pseudo ops. Unfortunately
+   they are only supported in very new binutils, so define them
+   away for older version.
+ */
+
+#ifdef CONFIG_UNWIND_INFO
+
+#define CFI_STARTPROC .cfi_startproc
+#define CFI_ENDPROC .cfi_endproc
+#define CFI_DEF_CFA .cfi_def_cfa
+#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register
+#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset
+#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
+#define CFI_OFFSET .cfi_offset
+#define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_REGISTER .cfi_register
+#define CFI_RESTORE .cfi_restore
+#define CFI_REMEMBER_STATE .cfi_remember_state
+#define CFI_RESTORE_STATE .cfi_restore_state
+#define CFI_UNDEFINED .cfi_undefined
+
+#else
+
+/* Due to the structure of pre-exisiting code, don't use assembler line
+   comment character # to ignore the arguments. Instead, use a dummy macro. */
+.macro ignore a=0, b=0, c=0, d=0
+.endm
+
+#define CFI_STARTPROC  ignore
+#define CFI_ENDPROC    ignore
+#define CFI_DEF_CFA    ignore
+#define CFI_DEF_CFA_REGISTER   ignore
+#define CFI_DEF_CFA_OFFSET     ignore
+#define CFI_ADJUST_CFA_OFFSET  ignore
+#define CFI_OFFSET     ignore
+#define CFI_REL_OFFSET ignore
+#define CFI_REGISTER   ignore
+#define CFI_RESTORE    ignore
+#define CFI_REMEMBER_STATE ignore
+#define CFI_RESTORE_STATE ignore
+#define CFI_UNDEFINED ignore
+
+#endif
+
+#endif
diff --git a/include/asm-i386/intel_arch_perfmon.h b/include/asm-i386/intel_arch_perfmon.h
new file mode 100644 (file)
index 0000000..134ea9c
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef X86_INTEL_ARCH_PERFMON_H
+#define X86_INTEL_ARCH_PERFMON_H 1
+
+#define MSR_ARCH_PERFMON_PERFCTR0              0xc1
+#define MSR_ARCH_PERFMON_PERFCTR1              0xc2
+
+#define MSR_ARCH_PERFMON_EVENTSEL0             0x186
+#define MSR_ARCH_PERFMON_EVENTSEL1             0x187
+
+#define ARCH_PERFMON_EVENTSEL0_ENABLE      (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_INT          (1 << 20)
+#define ARCH_PERFMON_EVENTSEL_OS           (1 << 17)
+#define ARCH_PERFMON_EVENTSEL_USR          (1 << 16)
+
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL  (0x3c)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK        (0x00 << 8)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0)
+
+#endif /* X86_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-i386/irqflags.h b/include/asm-i386/irqflags.h
new file mode 100644 (file)
index 0000000..e1bdb97
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * include/asm-i386/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__(
+               "pushfl ; popl %0"
+               : "=g" (flags)
+               : /* no input */
+       );
+
+       return flags;
+}
+
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+       __asm__ __volatile__(
+               "pushl %0 ; popfl"
+               : /* no output */
+               :"g" (flags)
+               :"memory", "cc"
+       );
+}
+
+static inline void raw_local_irq_disable(void)
+{
+       __asm__ __volatile__("cli" : : : "memory");
+}
+
+static inline void raw_local_irq_enable(void)
+{
+       __asm__ __volatile__("sti" : : : "memory");
+}
+
+/*
+ * Used in the idle loop; sti takes one instruction cycle
+ * to complete:
+ */
+static inline void raw_safe_halt(void)
+{
+       __asm__ __volatile__("sti; hlt" : : : "memory");
+}
+
+/*
+ * Used when interrupts are already enabled or to
+ * shutdown the processor:
+ */
+static inline void halt(void)
+{
+       __asm__ __volatile__("hlt": : :"memory");
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (1 << 9));
+}
+
+static inline int raw_irqs_disabled(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       return raw_irqs_disabled_flags(flags);
+}
+
+/*
+ * For spinlocks, etc:
+ */
+static inline unsigned long __raw_local_irq_save(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       raw_local_irq_disable();
+
+       return flags;
+}
+
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Do the CPU's IRQ-state tracing from assembly code. We call a
+ * C function, so save all the C-clobbered registers:
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+# define TRACE_IRQS_ON                         \
+       pushl %eax;                             \
+       pushl %ecx;                             \
+       pushl %edx;                             \
+       call trace_hardirqs_on;                 \
+       popl %edx;                              \
+       popl %ecx;                              \
+       popl %eax;
+
+# define TRACE_IRQS_OFF                                \
+       pushl %eax;                             \
+       pushl %ecx;                             \
+       pushl %edx;                             \
+       call trace_hardirqs_off;                \
+       popl %edx;                              \
+       popl %ecx;                              \
+       popl %eax;
+
+#else
+# define TRACE_IRQS_ON
+# define TRACE_IRQS_OFF
+#endif
+
+#endif
diff --git a/include/asm-i386/k8.h b/include/asm-i386/k8.h
new file mode 100644 (file)
index 0000000..dfd88a6
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-x86_64/k8.h>
diff --git a/include/asm-i386/mach-default/setup_arch.h b/include/asm-i386/mach-default/setup_arch.h
new file mode 100644 (file)
index 0000000..fb42099
--- /dev/null
@@ -0,0 +1,5 @@
+/* Hook to call BIOS initialisation function */
+
+/* no action for generic */
+
+#define ARCH_SETUP
diff --git a/include/asm-i386/mach-visws/setup_arch.h b/include/asm-i386/mach-visws/setup_arch.h
new file mode 100644 (file)
index 0000000..33f700e
--- /dev/null
@@ -0,0 +1,8 @@
+/* Hook to call BIOS initialisation function */
+
+extern unsigned long sgivwfb_mem_phys;
+extern unsigned long sgivwfb_mem_size;
+
+/* no action for visws */
+
+#define ARCH_SETUP
diff --git a/include/asm-i386/mach-voyager/setup_arch.h b/include/asm-i386/mach-voyager/setup_arch.h
new file mode 100644 (file)
index 0000000..84d01ad
--- /dev/null
@@ -0,0 +1,10 @@
+#include <asm/voyager.h>
+#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40))
+
+/* Hook to call BIOS initialisation function */
+
+/* for voyager, pass the voyager BIOS/SUS info area to the detection
+ * routines */
+
+#define ARCH_SETUP     voyager_detect(VOYAGER_BIOS_INFO);
+
diff --git a/include/asm-i386/mach-xen/asm/irqflags.h b/include/asm-i386/mach-xen/asm/irqflags.h
new file mode 100644 (file)
index 0000000..dc7fd07
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * include/asm-i386/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+unsigned long __raw_local_save_flags(void);
+void raw_local_irq_restore(unsigned long flags);
+void raw_local_irq_disable(void);
+void raw_local_irq_enable(void);
+
+/*
+ * Used in the idle loop; sti takes one instruction cycle
+ * to complete:
+ */
+void raw_safe_halt(void);
+
+/*
+ * Used when interrupts are already enabled or to
+ * shutdown the processor:
+ */
+void halt(void);
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return flags != 0;
+}
+
+int raw_irqs_disabled(void);
+
+/*
+ * For spinlocks, etc:
+ */
+unsigned long __raw_local_irq_save(void);
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Do the CPU's IRQ-state tracing from assembly code. We call a
+ * C function, so save all the C-clobbered registers:
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+# define TRACE_IRQS_ON                         \
+       pushl %eax;                             \
+       pushl %ecx;                             \
+       pushl %edx;                             \
+       call trace_hardirqs_on;                 \
+       popl %edx;                              \
+       popl %ecx;                              \
+       popl %eax;
+
+# define TRACE_IRQS_OFF                                \
+       pushl %eax;                             \
+       pushl %ecx;                             \
+       pushl %edx;                             \
+       call trace_hardirqs_off;                \
+       popl %edx;                              \
+       popl %ecx;                              \
+       popl %eax;
+
+#else
+# define TRACE_IRQS_ON
+# define TRACE_IRQS_OFF
+#endif
+
+#endif
diff --git a/include/asm-i386/mach-xen/asm/maddr.h b/include/asm-i386/mach-xen/asm/maddr.h
new file mode 100644 (file)
index 0000000..b467320
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef _I386_MADDR_H
+#define _I386_MADDR_H
+
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+#define INVALID_P2M_ENTRY      (~0UL)
+#define FOREIGN_FRAME_BIT      (1UL<<31)
+#define FOREIGN_FRAME(m)       ((m) | FOREIGN_FRAME_BIT)
+
+#ifdef CONFIG_XEN
+
+extern unsigned long *phys_to_machine_mapping;
+
+#undef machine_to_phys_mapping
+extern unsigned long *machine_to_phys_mapping;
+extern unsigned int   machine_to_phys_order;
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return pfn;
+       return phys_to_machine_mapping[(unsigned int)(pfn)] &
+               ~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return 1;
+       return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+       extern unsigned long max_mapnr;
+       unsigned long pfn;
+
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return mfn;
+
+       if (unlikely((mfn >> machine_to_phys_order) != 0))
+               return max_mapnr;
+
+       /* The array access can fail (e.g., device space beyond end of RAM). */
+       asm (
+               "1:     movl %1,%0\n"
+               "2:\n"
+               ".section .fixup,\"ax\"\n"
+               "3:     movl %2,%0\n"
+               "       jmp  2b\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .align 4\n"
+               "       .long 1b,3b\n"
+               ".previous"
+               : "=r" (pfn)
+               : "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) );
+
+       return pfn;
+}
+
+/*
+ * We detect special mappings in one of two ways:
+ *  1. If the MFN is an I/O page then Xen will set the m2p entry
+ *     to be outside our maximum possible pseudophys range.
+ *  2. If the MFN belongs to a different domain then we will certainly
+ *     not have MFN in our p2m table. Conversely, if the page is ours,
+ *     then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
+ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+       extern unsigned long max_mapnr;
+       unsigned long pfn = mfn_to_pfn(mfn);
+       if ((pfn < max_mapnr)
+           && !xen_feature(XENFEAT_auto_translated_physmap)
+           && (phys_to_machine_mapping[pfn] != mfn))
+               return max_mapnr; /* force !pfn_valid() */
+       return pfn;
+}
+
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+               BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+               return;
+       }
+       phys_to_machine_mapping[pfn] = mfn;
+}
+
+
+#else /* !CONFIG_XEN */
+
+#define pfn_to_mfn(pfn) (pfn)
+#define mfn_to_pfn(mfn) (mfn)
+#define mfn_to_local_pfn(mfn) (mfn)
+#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
+#define phys_to_machine_mapping_valid(pfn) (1)
+
+#endif /* !CONFIG_XEN */
+
+/* Definitions for machine and pseudophysical addresses. */
+#ifdef CONFIG_X86_PAE
+typedef unsigned long long paddr_t;
+typedef unsigned long long maddr_t;
+#else
+typedef unsigned long paddr_t;
+typedef unsigned long maddr_t;
+#endif
+
+static inline maddr_t phys_to_machine(paddr_t phys)
+{
+       maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+       machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+       return machine;
+}
+static inline paddr_t machine_to_phys(maddr_t machine)
+{
+       paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+       phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+       return phys;
+}
+
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)     (phys_to_machine(__pa(v)))
+#define virt_to_mfn(v)         (pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
+#define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+#ifdef CONFIG_X86_PAE
+static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+{
+       pte_t pte;
+
+       pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) | \
+                                       (pgprot_val(pgprot) >> 32);
+       pte.pte_high &= (__supported_pte_mask >> 32);
+       pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & \
+                                                       __supported_pte_mask;
+       return pte;
+}
+#else
+#define pfn_pte_ma(pfn, prot)  __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#endif
+
+#define __pte_ma(x)    ((pte_t) { (x) } )
+
+#endif /* _I386_MADDR_H */
diff --git a/include/asm-i386/mach-xen/asm/stacktrace.h b/include/asm-i386/mach-xen/asm/stacktrace.h
new file mode 100644 (file)
index 0000000..5eb9799
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_STACKTRACE_H
+#define _ASM_STACKTRACE_H 1
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+       void (*warning)(void *data, char *msg);
+       /* msg must contain %s for the symbol */
+       void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+       void (*address)(void *data, unsigned long address);
+       /* On negative return stop dumping */
+       int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
+               struct stacktrace_ops *ops, void *data);
+
+#endif
diff --git a/include/asm-i386/mach-xen/asm/timer.h b/include/asm-i386/mach-xen/asm/timer.h
new file mode 100644 (file)
index 0000000..aed1643
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _ASMi386_TIMER_H
+#define _ASMi386_TIMER_H
+#include <linux/init.h>
+#include <linux/pm.h>
+
+/**
+ * struct timer_ops - used to define a timer source
+ *
+ * @name: name of the timer.
+ * @init: Probes and initializes the timer. Takes clock= override 
+ *        string as an argument. Returns 0 on success, anything else
+ *        on failure.
+ * @mark_offset: called by the timer interrupt.
+ * @get_offset:  called by gettimeofday(). Returns the number of microseconds
+ *               since the last timer interupt.
+ * @monotonic_clock: returns the number of nanoseconds since the init of the
+ *                   timer.
+ * @delay: delays this many clock cycles.
+ */
+struct timer_opts {
+       char* name;
+       void (*mark_offset)(void);
+       unsigned long (*get_offset)(void);
+       unsigned long long (*monotonic_clock)(void);
+       void (*delay)(unsigned long);
+       unsigned long (*read_timer)(void);
+       int (*suspend)(pm_message_t state);
+       int (*resume)(void);
+};
+
+struct init_timer_opts {
+       int (*init)(char *override);
+       struct timer_opts *opts;
+};
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+extern struct timer_opts* __init select_timer(void);
+extern void clock_fallback(void);
+void setup_pit_timer(void);
+
+/* Modifiers for buggy PIT handling */
+
+extern int pit_latch_buggy;
+
+extern struct timer_opts *cur_timer;
+extern int timer_ack;
+
+/* list of externed timers */
+extern struct timer_opts timer_none;
+extern struct timer_opts timer_pit;
+extern struct init_timer_opts timer_pit_init;
+extern struct init_timer_opts timer_tsc_init;
+#ifdef CONFIG_X86_CYCLONE_TIMER
+extern struct init_timer_opts timer_cyclone_init;
+#endif
+
+extern unsigned long calibrate_tsc(void);
+extern unsigned long read_timer_tsc(void);
+extern void init_cpu_khz(void);
+extern int recalibrate_cpu_khz(void);
+#ifdef CONFIG_HPET_TIMER
+extern struct init_timer_opts timer_hpet_init;
+extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr);
+#endif
+
+#ifdef CONFIG_X86_PM_TIMER
+extern struct init_timer_opts timer_pmtmr_init;
+#endif
+#endif
diff --git a/include/asm-i386/mach-xen/setup_arch.h b/include/asm-i386/mach-xen/setup_arch.h
new file mode 100644 (file)
index 0000000..ad19957
--- /dev/null
@@ -0,0 +1,5 @@
+/* Hook to call BIOS initialisation function */
+
+#define ARCH_SETUP machine_specific_arch_setup();
+
+void __init machine_specific_arch_setup(void);
diff --git a/include/asm-i386/mce.h b/include/asm-i386/mce.h
new file mode 100644 (file)
index 0000000..7cc1a97
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_MCE
+extern void mcheck_init(struct cpuinfo_x86 *c);
+#else
+#define mcheck_init(c) do {} while(0)
+#endif
diff --git a/include/asm-i386/stacktrace.h b/include/asm-i386/stacktrace.h
new file mode 100644 (file)
index 0000000..7d1f6a5
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-x86_64/stacktrace.h>
diff --git a/include/asm-i386/tracehook.h b/include/asm-i386/tracehook.h
new file mode 100644 (file)
index 0000000..ca49dbf
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Tracing hooks, i386 CPU support
+ */
+
+#ifndef _ASM_TRACEHOOK_H
+#define _ASM_TRACEHOOK_H       1
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/*
+ * See linux/tracehook.h for the descriptions of what these need to do.
+ */
+
+#define ARCH_HAS_SINGLE_STEP   (1)
+
+/* These two are defined in arch/i386/kernel/ptrace.c.  */
+void tracehook_enable_single_step(struct task_struct *tsk);
+void tracehook_disable_single_step(struct task_struct *tsk);
+
+static inline int tracehook_single_step_enabled(struct task_struct *tsk)
+{
+       return test_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+}
+
+static inline void tracehook_enable_syscall_trace(struct task_struct *tsk)
+{
+       set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_disable_syscall_trace(struct task_struct *tsk)
+{
+       clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_abort_syscall(struct pt_regs *regs)
+{
+       regs->orig_eax = -1;
+}
+
+extern const struct utrace_regset_view utrace_i386_native;
+static inline const struct utrace_regset_view *
+utrace_native_view(struct task_struct *tsk)
+{
+       return &utrace_i386_native;
+}
+
+
+#endif
diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
new file mode 100644 (file)
index 0000000..c139331
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * linux/include/asm-i386/tsc.h
+ *
+ * i386 TSC related functions
+ */
+#ifndef _ASM_i386_TSC_H
+#define _ASM_i386_TSC_H
+
+#include <asm/processor.h>
+
+/*
+ * Standard way to access the cycle counter on i586+ CPUs.
+ * Currently only used on SMP.
+ *
+ * If you really have a SMP machine with i486 chips or older,
+ * compile for that, and this will just always return zero.
+ * That's ok, it just means that the nicer scheduling heuristics
+ * won't work for you.
+ *
+ * We only use the low 32 bits, and we'd simply better make sure
+ * that we reschedule before that wraps. Scheduling at least every
+ * four billion cycles just basically sounds like a good idea,
+ * regardless of how fast the machine is.
+ */
+typedef unsigned long long cycles_t;
+
+extern unsigned int cpu_khz;
+extern unsigned int tsc_khz;
+
+static inline cycles_t get_cycles(void)
+{
+       unsigned long long ret = 0;
+
+#ifndef CONFIG_X86_TSC
+       if (!cpu_has_tsc)
+               return 0;
+#endif
+
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
+       rdtscll(ret);
+#endif
+       return ret;
+}
+
+extern void tsc_init(void);
+extern void mark_tsc_unstable(void);
+
+#endif
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
new file mode 100644 (file)
index 0000000..f0ac399
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef _ASM_I386_UNWIND_H
+#define _ASM_I386_UNWIND_H
+
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *     Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ */
+
+#ifdef CONFIG_STACK_UNWIND
+
+#include <linux/sched.h>
+#include <asm/fixmap.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+struct unwind_frame_info
+{
+       struct pt_regs regs;
+       struct task_struct *task;
+};
+
+#define UNW_PC(frame)        (frame)->regs.eip
+#define UNW_SP(frame)        (frame)->regs.esp
+#ifdef CONFIG_FRAME_POINTER
+#define UNW_FP(frame)        (frame)->regs.ebp
+#define FRAME_RETADDR_OFFSET 4
+#define FRAME_LINK_OFFSET    0
+#define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
+#define STACK_TOP(tsk)       ((tsk)->thread.esp0)
+#else
+#define UNW_FP(frame) ((void)(frame), 0)
+#endif
+#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
+
+#define UNW_REGISTER_INFO \
+       PTREGS_INFO(eax), \
+       PTREGS_INFO(ecx), \
+       PTREGS_INFO(edx), \
+       PTREGS_INFO(ebx), \
+       PTREGS_INFO(esp), \
+       PTREGS_INFO(ebp), \
+       PTREGS_INFO(esi), \
+       PTREGS_INFO(edi), \
+       PTREGS_INFO(eip)
+
+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+                                            /*const*/ struct pt_regs *regs)
+{
+       if (user_mode_vm(regs))
+               info->regs = *regs;
+       else {
+               memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
+               info->regs.esp = (unsigned long)&regs->esp;
+               info->regs.xss = __KERNEL_DS;
+       }
+}
+
+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+{
+       memset(&info->regs, 0, sizeof(info->regs));
+       info->regs.eip = info->task->thread.eip;
+       info->regs.xcs = __KERNEL_CS;
+       __get_user(info->regs.ebp, (long *)info->task->thread.esp);
+       info->regs.esp = info->task->thread.esp;
+       info->regs.xss = __KERNEL_DS;
+       info->regs.xds = __USER_DS;
+       info->regs.xes = __USER_DS;
+}
+
+extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
+                                               asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                                          void *arg),
+                                               void *arg);
+
+static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+{
+#if 0 /* This can only work when selector register and EFLAGS saves/restores
+         are properly annotated (and tracked in UNW_REGISTER_INFO). */
+       return user_mode_vm(&info->regs);
+#else
+       return info->regs.eip < PAGE_OFFSET
+              || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
+                   && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
+              || info->regs.esp < PAGE_OFFSET;
+#endif
+}
+
+#else
+
+#define UNW_PC(frame) ((void)(frame), 0)
+#define UNW_SP(frame) ((void)(frame), 0)
+#define UNW_FP(frame) ((void)(frame), 0)
+
+static inline int arch_unw_user_mode(const void *info)
+{
+       return 0;
+}
+
+#endif
+
+#endif /* _ASM_I386_UNWIND_H */
diff --git a/include/asm-ia64/Kbuild b/include/asm-ia64/Kbuild
new file mode 100644 (file)
index 0000000..15818a1
--- /dev/null
@@ -0,0 +1,17 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += break.h
+header-y += fpu.h
+header-y += fpswa.h
+header-y += gcc_intrin.h
+header-y += ia64regs.h
+header-y += intel_intrin.h
+header-y += intrinsics.h
+header-y += perfmon_default_smpl.h
+header-y += ptrace_offsets.h
+header-y += rse.h
+header-y += setup.h
+header-y += ucontext.h
+
+unifdef-y += perfmon.h
+unifdef-y += ustack.h
diff --git a/include/asm-ia64/fixmap.h b/include/asm-ia64/fixmap.h
new file mode 100644 (file)
index 0000000..4b32a82
--- /dev/null
@@ -0,0 +1,2 @@
+#define clear_fixmap(x)        do {} while (0)
+#define        set_fixmap(x,y) do {} while (0)
diff --git a/include/asm-ia64/hypercall.h b/include/asm-ia64/hypercall.h
new file mode 100644 (file)
index 0000000..8375336
--- /dev/null
@@ -0,0 +1,423 @@
+/******************************************************************************
+ * hypercall.h
+ * 
+ * Linux-specific hypervisor handling.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_H__
+#define __HYPERCALL_H__
+
+#include <linux/string.h> /* memcpy() */
+
+#ifndef __HYPERVISOR_H__
+# error "please don't include this file directly"
+#endif
+
+/*
+ * Assembler stubs for hyper-calls.
+ */
+
+#define _hypercall0(type, name)                                        \
+({                                                             \
+       long __res;                                             \
+       __asm__ __volatile__ (";;\n"                            \
+                             "mov r2=%1\n"                     \
+                             "break 0x1000 ;;\n"               \
+                             "mov %0=r8 ;;\n"                  \
+                             : "=r" (__res)                    \
+                             : "J" (__HYPERVISOR_##name)       \
+                             : "r2","r8",                      \
+                               "memory" );                     \
+       (type)__res;                                            \
+})
+
+#define _hypercall1(type, name, a1)                            \
+({                                                             \
+       long __res;                                             \
+       __asm__ __volatile__ (";;\n"                            \
+                             "mov r14=%2\n"                    \
+                             "mov r2=%1\n"                     \
+                             "break 0x1000 ;;\n"               \
+                             "mov %0=r8 ;;\n"                  \
+                             : "=r" (__res)                    \
+                             : "J" (__HYPERVISOR_##name),      \
+                               "rI" ((unsigned long)(a1))      \
+                             : "r14","r2","r8",                \
+                               "memory" );                     \
+       (type)__res;                                            \
+})
+
+#define _hypercall2(type, name, a1, a2)                                \
+({                                                             \
+       long __res;                                             \
+       __asm__ __volatile__ (";;\n"                            \
+                             "mov r14=%2\n"                    \
+                             "mov r15=%3\n"                    \
+                             "mov r2=%1\n"                     \
+                             "break 0x1000 ;;\n"               \
+                             "mov %0=r8 ;;\n"                  \
+                             : "=r" (__res)                    \
+                             : "J" (__HYPERVISOR_##name),      \
+                               "rI" ((unsigned long)(a1)),     \
+                               "rI" ((unsigned long)(a2))      \
+                             : "r14","r15","r2","r8",          \
+                               "memory" );                     \
+       (type)__res;                                            \
+})
+
+#define _hypercall3(type, name, a1, a2, a3)                    \
+({                                                             \
+       long __res;                                             \
+       __asm__ __volatile__ (";;\n"                            \
+                             "mov r14=%2\n"                    \
+                             "mov r15=%3\n"                    \
+                             "mov r16=%4\n"                    \
+                             "mov r2=%1\n"                     \
+                             "break 0x1000 ;;\n"               \
+                             "mov %0=r8 ;;\n"                  \
+                             : "=r" (__res)                    \
+                             : "J" (__HYPERVISOR_##name),      \
+                               "rI" ((unsigned long)(a1)),     \
+                               "rI" ((unsigned long)(a2)),     \
+                               "rI" ((unsigned long)(a3))      \
+                             : "r14","r15","r16","r2","r8",    \
+                               "memory" );                     \
+       (type)__res;                                            \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4)                        \
+({                                                             \
+       long __res;                                             \
+       __asm__ __volatile__ (";;\n"                            \
+                             "mov r14=%2\n"                    \
+                             "mov r15=%3\n"                    \
+                             "mov r16=%4\n"                    \
+                             "mov r17=%5\n"                    \
+                             "mov r2=%1\n"                     \
+                             "break 0x1000 ;;\n"               \
+                             "mov %0=r8 ;;\n"                  \
+                             : "=r" (__res)                    \
+                             : "J" (__HYPERVISOR_##name),      \
+                               "rI" ((unsigned long)(a1)),     \
+                               "rI" ((unsigned long)(a2)),     \
+                               "rI" ((unsigned long)(a3)),     \
+                               "rI" ((unsigned long)(a4))      \
+                             : "r14","r15","r16","r2","r8",    \
+                               "r17","memory" );               \
+       (type)__res;                                            \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5)            \
+({                                                             \
+       long __res;                                             \
+       __asm__ __volatile__ (";;\n"                            \
+                             "mov r14=%2\n"                    \
+                             "mov r15=%3\n"                    \
+                             "mov r16=%4\n"                    \
+                             "mov r17=%5\n"                    \
+                             "mov r18=%6\n"                    \
+                             "mov r2=%1\n"                     \
+                             "break 0x1000 ;;\n"               \
+                             "mov %0=r8 ;;\n"                  \
+                             : "=r" (__res)                    \
+                             : "J" (__HYPERVISOR_##name),      \
+                               "rI" ((unsigned long)(a1)),     \
+                               "rI" ((unsigned long)(a2)),     \
+                               "rI" ((unsigned long)(a3)),     \
+                               "rI" ((unsigned long)(a4)),     \
+                               "rI" ((unsigned long)(a5))      \
+                             : "r14","r15","r16","r2","r8",    \
+                               "r17","r18","memory" );         \
+       (type)__res;                                            \
+})
+
+static inline int
+HYPERVISOR_sched_op_compat(
+    int cmd, unsigned long arg)
+{
+       return _hypercall2(int, sched_op_compat, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_sched_op(
+       int cmd, void *arg)
+{
+       return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline long
+HYPERVISOR_set_timer_op(
+    u64 timeout)
+{
+    unsigned long timeout_hi = (unsigned long)(timeout>>32);
+    unsigned long timeout_lo = (unsigned long)timeout;
+    return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+}
+
+static inline int
+HYPERVISOR_dom0_op(
+    dom0_op_t *dom0_op)
+{
+    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
+    return _hypercall1(int, dom0_op, dom0_op);
+}
+
+static inline int
+HYPERVISOR_multicall(
+    void *call_list, int nr_calls)
+{
+    return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+//XXX xen/ia64 copy_from_guest() is broken.
+//    This is a temporal work around until it is fixed.
+static inline int
+____HYPERVISOR_memory_op(
+    unsigned int cmd, void *arg)
+{
+    return _hypercall2(int, memory_op, cmd, arg);
+}
+
+#include <xen/interface/memory.h>
+#ifdef CONFIG_VMX_GUEST
+# define ia64_xenmem_reservation_op(op, xmr) (0)
+#else
+int ia64_xenmem_reservation_op(unsigned long op,
+                  struct xen_memory_reservation* reservation__);
+#endif
+static inline int
+HYPERVISOR_memory_op(
+    unsigned int cmd, void *arg)
+{
+    switch (cmd) {
+    case XENMEM_increase_reservation:
+    case XENMEM_decrease_reservation:
+    case XENMEM_populate_physmap:
+        return ia64_xenmem_reservation_op(cmd, 
+                                          (struct xen_memory_reservation*)arg);
+    default:
+        return ____HYPERVISOR_memory_op(cmd, arg);
+    }
+    /* NOTREACHED */
+}
+
+static inline int
+HYPERVISOR_event_channel_op(
+    int cmd, void *arg)
+{
+    int rc = _hypercall2(int, event_channel_op, cmd, arg);
+    if (unlikely(rc == -ENOSYS)) {
+        struct evtchn_op op;
+        op.cmd = cmd;
+        memcpy(&op.u, arg, sizeof(op.u));
+        rc = _hypercall1(int, event_channel_op_compat, &op);
+    }
+    return rc;
+}
+
+static inline int
+HYPERVISOR_acm_op(
+       unsigned int cmd, void *arg)
+{
+    return _hypercall2(int, acm_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_xen_version(
+    int cmd, void *arg)
+{
+    return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_console_io(
+    int cmd, int count, char *str)
+{
+    return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+HYPERVISOR_physdev_op(
+    int cmd, void *arg)
+{
+    int rc = _hypercall2(int, physdev_op, cmd, arg);
+    if (unlikely(rc == -ENOSYS)) {
+        struct physdev_op op;
+        op.cmd = cmd;
+        memcpy(&op.u, arg, sizeof(op.u));
+        rc = _hypercall1(int, physdev_op_compat, &op);
+    }
+    return rc;
+}
+
+//XXX __HYPERVISOR_grant_table_op is used for this hypercall constant.
+static inline int
+____HYPERVISOR_grant_table_op(
+    unsigned int cmd, void *uop, unsigned int count,
+    unsigned long pa1, unsigned long pa2)
+{
+    return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2);
+}
+
+int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+
+static inline int
+HYPERVISOR_vcpu_op(
+       int cmd, int vcpuid, void *extra_args)
+{
+    return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+}
+
+extern int HYPERVISOR_suspend(unsigned long srec);
+
+static inline unsigned long
+HYPERVISOR_hvm_op(
+       int cmd, void *arg)
+{
+       return _hypercall2(unsigned long, hvm_op, cmd, arg);
+}
+
+static inline int
+HYPERVISOR_callback_op(
+       int cmd, void *arg)
+{
+       return _hypercall2(int, callback_op, cmd, arg);
+}
+
+extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
+static inline void exit_idle(void) {}
+#define do_IRQ(irq, regs) ({                   \
+       irq_enter();                            \
+       __do_IRQ((irq), (regs));                \
+       irq_exit();                             \
+})
+
+#include <linux/err.h>
+#ifdef CONFIG_XEN
+#include <asm/xen/privop.h>
+#endif /* CONFIG_XEN */
+
+static inline unsigned long
+__HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
+{
+       return _hypercall3(unsigned long, ia64_dom0vp_op,
+                          IA64_DOM0VP_ioremap, ioaddr, size);
+}
+
+static inline unsigned long
+HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
+{
+       unsigned long ret = ioaddr;
+       if (is_running_on_xen()) {
+               ret = __HYPERVISOR_ioremap(ioaddr, size);
+               if (unlikely(ret == -ENOSYS))
+                       panic("hypercall %s failed with %ld. "
+                             "Please check Xen and Linux config mismatch\n",
+                             __func__, -ret);
+               else if (unlikely(IS_ERR_VALUE(ret)))
+                       ret = ioaddr;
+       }
+       return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_phystomach(unsigned long gpfn)
+{
+       return _hypercall2(unsigned long, ia64_dom0vp_op,
+                          IA64_DOM0VP_phystomach, gpfn);
+}
+
+static inline unsigned long
+HYPERVISOR_phystomach(unsigned long gpfn)
+{
+       unsigned long ret = gpfn;
+       if (is_running_on_xen()) {
+               ret = __HYPERVISOR_phystomach(gpfn);
+       }
+       return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_machtophys(unsigned long mfn)
+{
+       return _hypercall2(unsigned long, ia64_dom0vp_op,
+                          IA64_DOM0VP_machtophys, mfn);
+}
+
+static inline unsigned long
+HYPERVISOR_machtophys(unsigned long mfn)
+{
+       unsigned long ret = mfn;
+       if (is_running_on_xen()) {
+               ret = __HYPERVISOR_machtophys(mfn);
+       }
+       return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
+{
+       return _hypercall3(unsigned long, ia64_dom0vp_op,
+                          IA64_DOM0VP_zap_physmap, gpfn, extent_order);
+}
+
+static inline unsigned long
+HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
+{
+       unsigned long ret = 0;
+       if (is_running_on_xen()) {
+               ret = __HYPERVISOR_zap_physmap(gpfn, extent_order);
+       }
+       return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
+                        unsigned long flags, domid_t domid)
+{
+       return _hypercall5(unsigned long, ia64_dom0vp_op,
+                          IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid);
+}
+
+static inline unsigned long
+HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
+                      unsigned long flags, domid_t domid)
+{
+       unsigned long ret = 0;
+       BUG_ON(!is_running_on_xen());//XXX
+       if (is_running_on_xen()) {
+               ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
+       }
+       return ret;
+}
+
+// for balloon driver
+#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
+
+#endif /* __HYPERCALL_H__ */
diff --git a/include/asm-ia64/hypervisor.h b/include/asm-ia64/hypervisor.h
new file mode 100644 (file)
index 0000000..3c190ae
--- /dev/null
@@ -0,0 +1,218 @@
+/******************************************************************************
+ * hypervisor.h
+ * 
+ * Linux-specific hypervisor handling.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERVISOR_H__
+#define __HYPERVISOR_H__
+
+#ifdef CONFIG_XEN
+extern int running_on_xen;
+#define is_running_on_xen()                    (running_on_xen)
+#else /* CONFIG_XEN */
+# ifdef CONFIG_VMX_GUEST
+#  define is_running_on_xen()                  (1)
+# else /* CONFIG_VMX_GUEST */
+#  define is_running_on_xen()                  (0)
+#  define HYPERVISOR_ioremap(offset, size)     (offset)
+# endif /* CONFIG_VMX_GUEST */
+#endif /* CONFIG_XEN */
+
+#if defined(CONFIG_XEN) || defined(CONFIG_VMX_GUEST)
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/dom0_ops.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/sched.h>
+#include <asm/hypercall.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+extern shared_info_t *HYPERVISOR_shared_info;
+extern start_info_t *xen_start_info;
+
+void force_evtchn_callback(void);
+
+#ifndef CONFIG_VMX_GUEST
+/* Turn jiffies into Xen system time. XXX Implement me. */
+#define jiffies_to_st(j)       0
+
+static inline int
+HYPERVISOR_yield(
+       void)
+{
+       int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
+
+       return rc;
+}
+
+static inline int
+HYPERVISOR_block(
+       void)
+{
+       int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
+
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
+
+       return rc;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+       unsigned int reason)
+{
+       struct sched_shutdown sched_shutdown = {
+               .reason = reason
+       };
+
+       int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
+
+       return rc;
+}
+
+static inline int
+HYPERVISOR_poll(
+       evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
+{
+       struct sched_poll sched_poll = {
+               .nr_ports = nr_ports,
+               .timeout = jiffies_to_st(timeout)
+       };
+
+       int rc;
+
+       set_xen_guest_handle(sched_poll.ports, ports);
+       rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
+       if (rc == -ENOSYS)
+               rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
+
+       return rc;
+}
+
+#include <asm/hypercall.h>
+
+// for drivers/xen/privcmd/privcmd.c
+#define machine_to_phys_mapping 0
+struct vm_area_struct;
+int direct_remap_pfn_range(struct vm_area_struct *vma,
+                          unsigned long address,
+                          unsigned long mfn,
+                          unsigned long size,
+                          pgprot_t prot,
+                          domid_t  domid);
+struct file;
+int privcmd_mmap(struct file * file, struct vm_area_struct * vma);
+#define HAVE_ARCH_PRIVCMD_MMAP
+
+// for drivers/xen/balloon/balloon.c
+#ifdef CONFIG_XEN_SCRUB_PAGES
+#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
+#else
+#define scrub_pages(_p,_n) ((void)0)
+#endif
+#define        pte_mfn(_x)     pte_pfn(_x)
+#define phys_to_machine_mapping_valid(_x)      (1)
+
+#endif /* !CONFIG_VMX_GUEST */
+
+#define __pte_ma(_x)   ((pte_t) {(_x)})        /* unmodified use */
+#define pfn_pte_ma(_x,_y)      __pte_ma(0)     /* unmodified use */
+
+#ifndef CONFIG_VMX_GUEST
+int __xen_create_contiguous_region(unsigned long vstart, unsigned int order, unsigned int address_bits);
+static inline int
+xen_create_contiguous_region(unsigned long vstart,
+                             unsigned int order, unsigned int address_bits)
+{
+       int ret = 0;
+       if (is_running_on_xen()) {
+               ret = __xen_create_contiguous_region(vstart, order,
+                                                    address_bits);
+       }
+       return ret;
+}
+
+void __xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
+static inline void
+xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+       if (is_running_on_xen())
+               __xen_destroy_contiguous_region(vstart, order);
+}
+
+#endif /* !CONFIG_VMX_GUEST */
+
+// for netfront.c, netback.c
+#define MULTI_UVMFLAGS_INDEX 0 //XXX any value
+
+static inline void
+MULTI_update_va_mapping(
+       multicall_entry_t *mcl, unsigned long va,
+       pte_t new_val, unsigned long flags)
+{
+       mcl->op = __HYPERVISOR_update_va_mapping;
+       mcl->result = 0;
+}
+
+static inline void
+MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd,
+       void *uop, unsigned int count)
+{
+       mcl->op = __HYPERVISOR_grant_table_op;
+       mcl->args[0] = cmd;
+       mcl->args[1] = (unsigned long)uop;
+       mcl->args[2] = count;
+}
+
+// for debug
+asmlinkage int xprintk(const char *fmt, ...);
+#define xprintd(fmt, ...)      xprintk("%s:%d " fmt, __func__, __LINE__, \
+                                       ##__VA_ARGS__)
+
+#endif /* CONFIG_XEN || CONFIG_VMX_GUEST */
+
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN)
+#else
+#define is_initial_xendomain() 0
+#endif
+
+#endif /* __HYPERVISOR_H__ */
diff --git a/include/asm-ia64/maddr.h b/include/asm-ia64/maddr.h
new file mode 100644 (file)
index 0000000..55c6f94
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef _ASM_IA64_MADDR_H
+#define _ASM_IA64_MADDR_H
+
+#include <linux/kernel.h>
+#include <asm/hypervisor.h>
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+#ifdef CONFIG_XEN
+
+#define INVALID_P2M_ENTRY       (~0UL)
+
+/* XXX xen page size != page size */
+static inline unsigned long
+pfn_to_mfn_for_dma(unsigned long pfn)
+{
+       unsigned long mfn;
+       mfn = HYPERVISOR_phystomach(pfn);
+       BUG_ON(mfn == 0); // XXX
+       BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX
+       BUG_ON(mfn == INVALID_MFN);
+       return mfn;
+}
+
+static inline unsigned long
+phys_to_machine_for_dma(unsigned long phys)
+{
+       unsigned long machine =
+                     pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT;
+       machine |= (phys & ~PAGE_MASK);
+       return machine;
+}
+
+static inline unsigned long
+mfn_to_pfn_for_dma(unsigned long mfn)
+{
+       unsigned long pfn;
+       pfn = HYPERVISOR_machtophys(mfn);
+       BUG_ON(pfn == 0);
+       //BUG_ON(pfn == INVALID_M2P_ENTRY);
+       return pfn;
+}
+
+static inline unsigned long
+machine_to_phys_for_dma(unsigned long machine)
+{
+       unsigned long phys =
+                     mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT;
+       phys |= (machine & ~PAGE_MASK);
+       return phys;
+}
+
+static inline unsigned long
+mfn_to_local_pfn(unsigned long mfn)
+{
+       extern unsigned long max_mapnr;
+       unsigned long pfn = mfn_to_pfn_for_dma(mfn);
+       if (!pfn_valid(pfn))
+               return INVALID_P2M_ENTRY;
+       return pfn;
+}
+
+#else /* !CONFIG_XEN */
+
+#define pfn_to_mfn_for_dma(pfn) (pfn)
+#define mfn_to_pfn_for_dma(mfn) (mfn)
+#define phys_to_machine_for_dma(phys) (phys)
+#define machine_to_phys_for_dma(machine) (machine)
+#define mfn_to_local_pfn(mfn) (mfn)
+
+#endif /* !CONFIG_XEN */
+
+/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */
+#define FOREIGN_FRAME(m)        (INVALID_P2M_ENTRY)
+
+#define mfn_to_pfn(mfn) (mfn)
+#define pfn_to_mfn(pfn) (pfn)
+
+#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT))
+#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT)
+#define virt_to_machine(virt) __pa(virt) // for tpmfront.c
+
+#define set_phys_to_machine(pfn, mfn) do { } while (0)
+#ifdef CONFIG_VMX_GUEST
+extern void xen_machphys_update(unsigned long mfn, unsigned long pfn);
+#else /* CONFIG_VMX_GUEST */
+#define xen_machphys_update(mfn, pfn) do { } while (0)
+#endif /* CONFIG_VMX_GUEST */
+
+typedef unsigned long maddr_t; // to compile netback, netfront
+
+#endif /* _ASM_IA64_MADDR_H */
diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h
new file mode 100644 (file)
index 0000000..28c1e88
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _ASM_IA64_PRIVOP_H
+#define _ASM_IA64_PRIVOP_H
+
+/*
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Dan Magenheimer <dan.magenheimer@hp.com>
+ *
+ */
+
+#ifdef CONFIG_XEN
+#include <asm/xen/privop.h>
+#endif
+
+#ifndef __ASSEMBLY
+
+#ifndef IA64_PARAVIRTUALIZED
+
+#define ia64_getreg                    __ia64_getreg
+#define ia64_setreg                    __ia64_setreg
+#define ia64_hint                      __ia64_hint
+#define ia64_thash                     __ia64_thash
+#define ia64_itci                      __ia64_itci
+#define ia64_itcd                      __ia64_itcd
+#define ia64_itri                      __ia64_itri
+#define ia64_itrd                      __ia64_itrd
+#define ia64_tpa                       __ia64_tpa
+#define ia64_set_ibr                   __ia64_set_ibr
+#define ia64_set_pkr                   __ia64_set_pkr
+#define ia64_set_pmc                   __ia64_set_pmc
+#define ia64_set_pmd                   __ia64_set_pmd
+#define ia64_set_rr                    __ia64_set_rr
+#define ia64_get_cpuid                 __ia64_get_cpuid
+#define ia64_get_ibr                   __ia64_get_ibr
+#define ia64_get_pkr                   __ia64_get_pkr
+#define ia64_get_pmc                   __ia64_get_pmc
+#define ia64_get_pmd                   __ia64_get_pmd
+#define ia64_get_rr                    __ia64_get_rr
+#define ia64_fc                                __ia64_fc
+#define ia64_ssm                       __ia64_ssm
+#define ia64_rsm                       __ia64_rsm
+#define ia64_ptce                      __ia64_ptce
+#define ia64_ptcga                     __ia64_ptcga
+#define ia64_ptcl                      __ia64_ptcl
+#define ia64_ptri                      __ia64_ptri
+#define ia64_ptrd                      __ia64_ptrd
+#define ia64_get_psr_i                 __ia64_get_psr_i
+#define ia64_intrin_local_irq_restore  __ia64_intrin_local_irq_restore
+#define ia64_pal_halt_light            __ia64_pal_halt_light
+#define ia64_leave_kernel              __ia64_leave_kernel
+#define ia64_leave_syscall             __ia64_leave_syscall
+#define ia64_trace_syscall             __ia64_trace_syscall
+#define ia64_switch_to                 __ia64_switch_to
+#define ia64_pal_call_static           __ia64_pal_call_static
+
+#endif /* !IA64_PARAVIRTUALIZED */
+
+#endif /* !__ASSEMBLY */
+
+#endif /* _ASM_IA64_PRIVOP_H */
diff --git a/include/asm-ia64/synch_bitops.h b/include/asm-ia64/synch_bitops.h
new file mode 100644 (file)
index 0000000..21b7f8c
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __XEN_SYNCH_BITOPS_H__
+#define __XEN_SYNCH_BITOPS_H__
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ * Heavily modified to provide guaranteed strong synchronisation
+ * when communicating with Xen or other guest OSes running on other CPUs.
+ */
+
+#define ADDR (*(volatile long *) addr)
+
+static __inline__ void synch_set_bit(int nr, volatile void * addr)
+{
+       set_bit(nr, addr);
+}
+
+static __inline__ void synch_clear_bit(int nr, volatile void * addr)
+{
+       clear_bit(nr, addr);
+}
+
+static __inline__ void synch_change_bit(int nr, volatile void * addr)
+{
+       change_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
+{
+    return test_and_set_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+    return test_and_clear_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_change_bit(int nr, volatile void * addr)
+{
+    return test_and_change_bit(nr, addr);
+}
+
+static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
+{
+    return test_bit(nr, addr);
+}
+
+static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
+{
+    return test_bit(nr, addr);
+}
+
+#define synch_cmpxchg  ia64_cmpxchg4_acq
+
+#define synch_test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ synch_const_test_bit((nr),(addr)) : \
+ synch_var_test_bit((nr),(addr)))
+
+#define synch_cmpxchg_subword synch_cmpxchg
+
+#endif /* __XEN_SYNCH_BITOPS_H__ */
diff --git a/include/asm-ia64/tracehook.h b/include/asm-ia64/tracehook.h
new file mode 100644 (file)
index 0000000..ffea943
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C)2006 Intel Co
+ *     Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *     and Bibo Mao <bibo.mao@intel.com> adapted from i386.
+ *
+ *     Tracing hooks, ia64 CPU support
+ */
+
+#ifndef _ASM_TRACEHOOK_H
+#define _ASM_TRACEHOOK_H       1
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/*
+ * See linux/tracehook.h for the descriptions of what these need to do.
+ */
+
+#define ARCH_HAS_SINGLE_STEP   (1)
+#define ARCH_HAS_BLOCK_STEP    (1)
+
+static inline void tracehook_enable_single_step(struct task_struct *tsk)
+{
+       struct pt_regs *pt = task_pt_regs(tsk);
+       ia64_psr(pt)->ss = 1;
+}
+
+static inline void tracehook_disable_single_step(struct task_struct *tsk)
+{
+       struct pt_regs *pt = task_pt_regs(tsk);
+       ia64_psr(pt)->ss = 0;
+}
+
+static inline void tracehook_enable_block_step(struct task_struct *tsk)
+{
+       struct pt_regs *pt = task_pt_regs(tsk);
+       ia64_psr(pt)->tb = 1;
+}
+
+static inline void tracehook_disable_block_step(struct task_struct *tsk)
+{
+       struct pt_regs *pt = task_pt_regs(tsk);
+       ia64_psr(pt)->tb = 0;
+}
+
+static inline void tracehook_enable_syscall_trace(struct task_struct *tsk)
+{
+       set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_disable_syscall_trace(struct task_struct *tsk)
+{
+       clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline int tracehook_single_step_enabled(struct task_struct *tsk)
+{
+       struct pt_regs *pt = task_pt_regs(tsk);
+       return ia64_psr(pt)->ss;
+}
+
+static inline void tracehook_abort_syscall(struct pt_regs *regs)
+{
+       regs->r15 = -1L;
+}
+
+extern const struct utrace_regset_view utrace_ia64_native;
+static inline const struct utrace_regset_view *
+utrace_native_view(struct task_struct *tsk)
+{
+#if 0 //CONFIG_IA32_SUPPORT
+       extern const struct utrace_regset_view utrace_ia32_view;
+
+       struct pt_regs *pt = task_pt_regs(tsk);
+       if (pt->cr_ipsr & IA64_PSR_IS)
+               return &utrace_ia32_view;
+#endif
+       return &utrace_ia64_native;
+}
+
+#endif
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
new file mode 100644 (file)
index 0000000..073b3a2
--- /dev/null
@@ -0,0 +1,304 @@
+#ifndef _ASM_IA64_XEN_PRIVOP_H
+#define _ASM_IA64_XEN_PRIVOP_H
+
+/*
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Dan Magenheimer <dan.magenheimer@hp.com>
+ *
+ * Paravirtualizations of privileged operations for Xen/ia64
+ *
+ */
+
+
+#include <xen/interface/arch-ia64.h>
+
+#define IA64_PARAVIRTUALIZED
+
+#if 0
+#undef XSI_BASE
+/* At 1 MB, before per-cpu space but still addressable using addl instead
+   of movl. */
+#define XSI_BASE                               0xfffffffffff00000
+#endif
+
+/* Address of mapped regs.  */
+#define XMAPPEDREGS_BASE               (XSI_BASE + XSI_SIZE)
+
+#ifdef __ASSEMBLY__
+#define        XEN_HYPER_RFI                   break HYPERPRIVOP_RFI
+#define        XEN_HYPER_RSM_PSR_DT            break HYPERPRIVOP_RSM_DT
+#define        XEN_HYPER_SSM_PSR_DT            break HYPERPRIVOP_SSM_DT
+#define        XEN_HYPER_COVER                 break HYPERPRIVOP_COVER
+#define        XEN_HYPER_ITC_D                 break HYPERPRIVOP_ITC_D
+#define        XEN_HYPER_ITC_I                 break HYPERPRIVOP_ITC_I
+#define        XEN_HYPER_SSM_I                 break HYPERPRIVOP_SSM_I
+#define        XEN_HYPER_GET_IVR               break HYPERPRIVOP_GET_IVR
+#define        XEN_HYPER_GET_TPR               break HYPERPRIVOP_GET_TPR
+#define        XEN_HYPER_SET_TPR               break HYPERPRIVOP_SET_TPR
+#define        XEN_HYPER_EOI                   break HYPERPRIVOP_EOI
+#define        XEN_HYPER_SET_ITM               break HYPERPRIVOP_SET_ITM
+#define        XEN_HYPER_THASH                 break HYPERPRIVOP_THASH
+#define        XEN_HYPER_PTC_GA                break HYPERPRIVOP_PTC_GA
+#define        XEN_HYPER_ITR_D                 break HYPERPRIVOP_ITR_D
+#define        XEN_HYPER_GET_RR                break HYPERPRIVOP_GET_RR
+#define        XEN_HYPER_SET_RR                break HYPERPRIVOP_SET_RR
+#define        XEN_HYPER_SET_KR                break HYPERPRIVOP_SET_KR
+#define        XEN_HYPER_FC                    break HYPERPRIVOP_FC
+#define        XEN_HYPER_GET_CPUID             break HYPERPRIVOP_GET_CPUID
+#define        XEN_HYPER_GET_PMD               break HYPERPRIVOP_GET_PMD
+#define        XEN_HYPER_GET_EFLAG             break HYPERPRIVOP_GET_EFLAG
+#define        XEN_HYPER_SET_EFLAG             break HYPERPRIVOP_SET_EFLAG
+#define        XEN_HYPER_RSM_BE                break HYPERPRIVOP_RSM_BE
+#define        XEN_HYPER_GET_PSR               break HYPERPRIVOP_GET_PSR
+
+#define XSI_IFS                        (XSI_BASE + XSI_IFS_OFS)
+#define XSI_PRECOVER_IFS       (XSI_BASE + XSI_PRECOVER_IFS_OFS)
+#define XSI_INCOMPL_REGFR      (XSI_BASE + XSI_INCOMPL_REGFR_OFS)
+#define XSI_IFA                        (XSI_BASE + XSI_IFA_OFS)
+#define XSI_ISR                        (XSI_BASE + XSI_ISR_OFS)
+#define XSI_IIM                        (XSI_BASE + XSI_IIM_OFS)
+#define XSI_ITIR               (XSI_BASE + XSI_ITIR_OFS)
+#define XSI_PSR_I_ADDR         (XSI_BASE + XSI_PSR_I_ADDR_OFS)
+#define XSI_PSR_IC             (XSI_BASE + XSI_PSR_IC_OFS)
+#define XSI_IPSR               (XSI_BASE + XSI_IPSR_OFS)
+#define XSI_IIP                        (XSI_BASE + XSI_IIP_OFS)
+#define XSI_BANK1_R16          (XSI_BASE + XSI_BANK1_R16_OFS)
+#define XSI_BANKNUM            (XSI_BASE + XSI_BANKNUM_OFS)
+#define XSI_IHA                        (XSI_BASE + XSI_IHA_OFS)
+#endif
+
+#ifndef __ASSEMBLY__
+#define        XEN_HYPER_SSM_I         asm("break %0" : : "i" (HYPERPRIVOP_SSM_I))
+#define        XEN_HYPER_GET_IVR       asm("break %0" : : "i" (HYPERPRIVOP_GET_IVR))
+
+/************************************************/
+/* Instructions paravirtualized for correctness */
+/************************************************/
+
+/* "fc" and "thash" are privilege-sensitive instructions, meaning they
+ *  may have different semantics depending on whether they are executed
+ *  at PL0 vs PL!=0.  When paravirtualized, these instructions mustn't
+ *  be allowed to execute directly, lest incorrect semantics result. */
+extern unsigned long xen_fc(unsigned long addr);
+#define ia64_fc(addr)                  xen_fc((unsigned long)(addr))
+extern unsigned long xen_thash(unsigned long addr);
+#define ia64_thash(addr)               xen_thash((unsigned long)(addr))
+/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
+ * is not currently used (though it may be in a long-format VHPT system!)
+ * and the semantics of cover only change if psr.ic is off which is very
+ * rare (and currently non-existent outside of assembly code */
+
+/* There are also privilege-sensitive registers.  These registers are
+ * readable at any privilege level but only writable at PL0. */
+extern unsigned long xen_get_cpuid(int index);
+#define        ia64_get_cpuid(i)               xen_get_cpuid(i)
+extern unsigned long xen_get_pmd(int index);
+#define        ia64_get_pmd(i)                 xen_get_pmd(i)
+extern unsigned long xen_get_eflag(void);      /* see xen_ia64_getreg */
+extern void xen_set_eflag(unsigned long);      /* see xen_ia64_setreg */
+
+/************************************************/
+/* Instructions paravirtualized for performance */
+/************************************************/
+
+/* Xen uses memory-mapped virtual privileged registers for access to many
+ * performance-sensitive privileged registers.  Some, like the processor
+ * status register (psr), are broken up into multiple memory locations.
+ * Others, like "pend", are abstractions based on privileged registers.
+ * "Pend" is guaranteed to be set if reading cr.ivr would return a
+ * (non-spurious) interrupt. */
+#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE)
+#define XSI_PSR_I                      \
+       (*XEN_MAPPEDREGS->interrupt_mask_addr)
+#define xen_get_virtual_psr_i()                \
+       (!XSI_PSR_I)
+#define xen_set_virtual_psr_i(_val)    \
+       ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; })
+#define xen_set_virtual_psr_ic(_val)   \
+       ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; })
+#define xen_get_virtual_pend()         (XEN_MAPPEDREGS->pending_interruption)
+
+/* Hyperprivops are "break" instructions with a well-defined API.
+ * In particular, the virtual psr.ic bit must be off; in this way
+ * it is guaranteed to never conflict with a linux break instruction.
+ * Normally, this is done in a xen stub but this one is frequent enough
+ * that we inline it */
+#define xen_hyper_ssm_i()                                              \
+({                                                                     \
+       xen_set_virtual_psr_i(0);                                       \
+       xen_set_virtual_psr_ic(0);                                      \
+       XEN_HYPER_SSM_I;                                                \
+})
+
+/* turning off interrupts can be paravirtualized simply by writing
+ * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */
+#define xen_rsm_i()    xen_set_virtual_psr_i(0)
+
+/* turning on interrupts is a bit more complicated.. write to the
+ * memory-mapped virtual psr.i bit first (to avoid race condition),
+ * then if any interrupts were pending, we have to execute a hyperprivop
+ * to ensure the pending interrupt gets delivered; else we're done! */
+#define xen_ssm_i()                                                    \
+({                                                                     \
+       int old = xen_get_virtual_psr_i();                              \
+       xen_set_virtual_psr_i(1);                                       \
+       if (!old && xen_get_virtual_pend()) xen_hyper_ssm_i();          \
+})
+
+#define xen_ia64_intrin_local_irq_restore(x)                           \
+{                                                                      \
+     if (is_running_on_xen()) {                                                \
+       if ((x) & IA64_PSR_I) { xen_ssm_i(); }                          \
+       else { xen_rsm_i(); }                                           \
+    }                                                                  \
+    else __ia64_intrin_local_irq_restore((x));                         \
+}
+
+#define        xen_get_psr_i()                                                 \
+(                                                                      \
+       (is_running_on_xen()) ?                                         \
+               (xen_get_virtual_psr_i() ? IA64_PSR_I : 0)              \
+               : __ia64_get_psr_i()                                    \
+)
+
+#define xen_ia64_ssm(mask)                                             \
+{                                                                      \
+       if ((mask)==IA64_PSR_I) {                                       \
+               if (is_running_on_xen()) { xen_ssm_i(); }                       \
+               else { __ia64_ssm(mask); }                              \
+       }                                                               \
+       else { __ia64_ssm(mask); }                                      \
+}
+
+#define xen_ia64_rsm(mask)                                             \
+{                                                                      \
+       if ((mask)==IA64_PSR_I) {                                       \
+               if (is_running_on_xen()) { xen_rsm_i(); }                       \
+               else { __ia64_rsm(mask); }                              \
+       }                                                               \
+       else { __ia64_rsm(mask); }                                      \
+}
+
+
+/* Although all privileged operations can be left to trap and will
+ * be properly handled by Xen, some are frequent enough that we use
+ * hyperprivops for performance. */
+
+extern unsigned long xen_get_ivr(void);
+extern unsigned long xen_get_tpr(void);
+extern void xen_set_itm(unsigned long);
+extern void xen_set_tpr(unsigned long);
+extern void xen_eoi(void);
+extern void xen_set_rr(unsigned long index, unsigned long val);
+extern unsigned long xen_get_rr(unsigned long index);
+extern void xen_set_kr(unsigned long index, unsigned long val);
+extern void xen_ptcga(unsigned long addr, unsigned long size);
+
+/* Note: It may look wrong to test for is_running_on_xen() in each case.
+ * However regnum is always a constant so, as written, the compiler
+ * eliminates the switch statement, whereas is_running_on_xen() must be
+ * tested dynamically. */
+#define xen_ia64_getreg(regnum)                                                \
+({                                                                     \
+       __u64 ia64_intri_res;                                           \
+                                                                       \
+       switch(regnum) {                                                \
+       case _IA64_REG_CR_IVR:                                          \
+               ia64_intri_res = (is_running_on_xen()) ?                        \
+                       xen_get_ivr() :                                 \
+                       __ia64_getreg(regnum);                          \
+               break;                                                  \
+       case _IA64_REG_CR_TPR:                                          \
+               ia64_intri_res = (is_running_on_xen()) ?                        \
+                       xen_get_tpr() :                                 \
+                       __ia64_getreg(regnum);                          \
+               break;                                                  \
+       case _IA64_REG_AR_EFLAG:                                        \
+               ia64_intri_res = (is_running_on_xen()) ?                        \
+                       xen_get_eflag() :                               \
+                       __ia64_getreg(regnum);                          \
+               break;                                                  \
+       default:                                                        \
+               ia64_intri_res = __ia64_getreg(regnum);                 \
+               break;                                                  \
+       }                                                               \
+       ia64_intri_res;                                                 \
+})
+
+#define xen_ia64_setreg(regnum,val)                                    \
+({                                                                     \
+       switch(regnum) {                                                \
+       case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7:                     \
+               (is_running_on_xen()) ?                                 \
+                       xen_set_kr((regnum-_IA64_REG_AR_KR0), val) :    \
+                       __ia64_setreg(regnum,val);                      \
+               break;                                                  \
+       case _IA64_REG_CR_ITM:                                          \
+               (is_running_on_xen()) ?                                 \
+                       xen_set_itm(val) :                              \
+                       __ia64_setreg(regnum,val);                      \
+               break;                                                  \
+       case _IA64_REG_CR_TPR:                                          \
+               (is_running_on_xen()) ?                                 \
+                       xen_set_tpr(val) :                              \
+                       __ia64_setreg(regnum,val);                      \
+               break;                                                  \
+       case _IA64_REG_CR_EOI:                                          \
+               (is_running_on_xen()) ?                                 \
+                       xen_eoi() :                                     \
+                       __ia64_setreg(regnum,val);                      \
+               break;                                                  \
+       case _IA64_REG_AR_EFLAG:                                        \
+               (is_running_on_xen()) ?                                 \
+                       xen_set_eflag(val) :                            \
+                       __ia64_setreg(regnum,val);                      \
+               break;                                                  \
+       default:                                                        \
+               __ia64_setreg(regnum,val);                              \
+               break;                                                  \
+       }                                                               \
+})
+
+#define ia64_ssm                       xen_ia64_ssm
+#define ia64_rsm                       xen_ia64_rsm
+#define ia64_intrin_local_irq_restore  xen_ia64_intrin_local_irq_restore
+#define        ia64_ptcga                      xen_ptcga
+#define        ia64_set_rr(index,val)          xen_set_rr(index,val)
+#define        ia64_get_rr(index)              xen_get_rr(index)
+#define ia64_getreg                    xen_ia64_getreg
+#define ia64_setreg                    xen_ia64_setreg
+#define        ia64_get_psr_i                  xen_get_psr_i
+
+/* the remainder of these are not performance-sensitive so its
+ * OK to not paravirtualize and just take a privop trap and emulate */
+#define ia64_hint                      __ia64_hint
+#define ia64_set_pmd                   __ia64_set_pmd
+#define ia64_itci                      __ia64_itci
+#define ia64_itcd                      __ia64_itcd
+#define ia64_itri                      __ia64_itri
+#define ia64_itrd                      __ia64_itrd
+#define ia64_tpa                       __ia64_tpa
+#define ia64_set_ibr                   __ia64_set_ibr
+#define ia64_set_pkr                   __ia64_set_pkr
+#define ia64_set_pmc                   __ia64_set_pmc
+#define ia64_get_ibr                   __ia64_get_ibr
+#define ia64_get_pkr                   __ia64_get_pkr
+#define ia64_get_pmc                   __ia64_get_pmc
+#define ia64_ptce                      __ia64_ptce
+#define ia64_ptcl                      __ia64_ptcl
+#define ia64_ptri                      __ia64_ptri
+#define ia64_ptrd                      __ia64_ptrd
+
+#endif /* !__ASSEMBLY__ */
+
+/* these routines utilize privilege-sensitive or performance-sensitive
+ * privileged instructions so the code must be replaced with
+ * paravirtualized versions */
+#define ia64_pal_halt_light            xen_pal_halt_light
+#define        ia64_leave_kernel               xen_leave_kernel
+#define        ia64_leave_syscall              xen_leave_syscall
+#define        ia64_trace_syscall              xen_trace_syscall
+#define        ia64_switch_to                  xen_switch_to
+#define        ia64_pal_call_static            xen_pal_call_static
+
+#endif /* _ASM_IA64_XEN_PRIVOP_H */
diff --git a/include/asm-m32r/Kbuild b/include/asm-m32r/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-m68k/Kbuild b/include/asm-m68k/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-m68knommu/Kbuild b/include/asm-m68knommu/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-m68knommu/m532xsim.h b/include/asm-m68knommu/m532xsim.h
new file mode 100644 (file)
index 0000000..1835fd2
--- /dev/null
@@ -0,0 +1,2238 @@
+/****************************************************************************/
+
+/*
+ *     m532xsim.h -- ColdFire 5329 registers
+ */
+
+/****************************************************************************/
+#ifndef        m532xsim_h
+#define        m532xsim_h
+/****************************************************************************/
+
+#define MCF_REG32(x) (*(volatile unsigned long  *)(x))
+#define MCF_REG16(x) (*(volatile unsigned short *)(x))
+#define MCF_REG08(x) (*(volatile unsigned char  *)(x))
+
+#define MCFINT_VECBASE      64
+#define MCFINT_UART0        26          /* Interrupt number for UART0 */
+#define MCFINT_UART1        27          /* Interrupt number for UART1 */
+
+#define MCF_WTM_WCR    MCF_REG16(0xFC098000)
+
+/*
+ *     Define the 532x SIM register set addresses.
+ */
+#define        MCFSIM_IPRL             0xFC048004
+#define        MCFSIM_IPRH             0xFC048000
+#define        MCFSIM_IPR              MCFSIM_IPRL
+#define        MCFSIM_IMRL             0xFC04800C
+#define        MCFSIM_IMRH             0xFC048008
+#define        MCFSIM_IMR              MCFSIM_IMRL
+#define        MCFSIM_ICR0             0xFC048040      
+#define        MCFSIM_ICR1             0xFC048041      
+#define        MCFSIM_ICR2             0xFC048042      
+#define        MCFSIM_ICR3             0xFC048043      
+#define        MCFSIM_ICR4             0xFC048044      
+#define        MCFSIM_ICR5             0xFC048045      
+#define        MCFSIM_ICR6             0xFC048046      
+#define        MCFSIM_ICR7             0xFC048047      
+#define        MCFSIM_ICR8             0xFC048048      
+#define        MCFSIM_ICR9             0xFC048049      
+#define        MCFSIM_ICR10            0xFC04804A
+#define        MCFSIM_ICR11            0xFC04804B
+
+/*
+ *     Some symbol defines for the above...
+ */
+#define        MCFSIM_SWDICR           MCFSIM_ICR0     /* Watchdog timer ICR */
+#define        MCFSIM_TIMER1ICR        MCFSIM_ICR1     /* Timer 1 ICR */
+#define        MCFSIM_TIMER2ICR        MCFSIM_ICR2     /* Timer 2 ICR */
+#define        MCFSIM_UART1ICR         MCFSIM_ICR4     /* UART 1 ICR */
+#define        MCFSIM_UART2ICR         MCFSIM_ICR5     /* UART 2 ICR */
+#define        MCFSIM_DMA0ICR          MCFSIM_ICR6     /* DMA 0 ICR */
+#define        MCFSIM_DMA1ICR          MCFSIM_ICR7     /* DMA 1 ICR */
+#define        MCFSIM_DMA2ICR          MCFSIM_ICR8     /* DMA 2 ICR */
+#define        MCFSIM_DMA3ICR          MCFSIM_ICR9     /* DMA 3 ICR */
+
+
+#define        MCFSIM_IMR_MASKALL      0xFFFFFFFF      /* All SIM intr sources */
+
+#define MCFSIM_IMR_SIMR0       0xFC04801C
+#define MCFSIM_IMR_SIMR1       0xFC04C01C
+#define MCFSIM_IMR_CIMR0       0xFC04801D
+#define MCFSIM_IMR_CIMR1       0xFC04C01D
+
+#define MCFSIM_ICR_TIMER1      (0xFC048040+32)
+#define MCFSIM_ICR_TIMER2      (0xFC048040+33)
+
+
+/*
+ *     Macro to set IMR register. It is 32 bits on the 5307.
+ */
+#define        mcf_getimr()            \
+       *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
+
+#define        mcf_setimr(imr)         \
+       *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
+
+#define        mcf_getipr()            \
+       *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
+
+#define        mcf_getiprl()           \
+       *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRL))
+
+#define        mcf_getiprh()           \
+       *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRH))
+
+
+#define mcf_enable_irq0(irq)           \
+       *((volatile unsigned char*) (MCFSIM_IMR_CIMR0)) = (irq);
+
+#define mcf_enable_irq1(irq)           \
+       *((volatile unsigned char*) (MCFSIM_IMR_CIMR1)) = (irq);
+
+#define mcf_disable_irq0(irq)          \
+       *((volatile unsigned char*) (MCFSIM_IMR_SIMR0)) = (irq);
+
+#define mcf_disable_irq1(irq)          \
+       *((volatile unsigned char*) (MCFSIM_IMR_SIMR1)) = (irq);
+
+/*
+ *     Define the Cache register flags.
+ */
+#define        CACR_EC                 (1<<31)
+#define        CACR_ESB                (1<<29)
+#define        CACR_DPI                (1<<28)
+#define        CACR_HLCK               (1<<27)
+#define        CACR_CINVA              (1<<24)
+#define        CACR_DNFB               (1<<10)
+#define        CACR_DCM_WTHRU          (0<<8)
+#define        CACR_DCM_WBACK          (1<<8)
+#define        CACR_DCM_OFF_PRE        (2<<8)
+#define        CACR_DCM_OFF_IMP        (3<<8)
+#define        CACR_DW                 (1<<5)
+
+#define        ACR_BASE_POS            24
+#define        ACR_MASK_POS            16
+#define        ACR_ENABLE              (1<<15)
+#define        ACR_USER                (0<<13)
+#define        ACR_SUPER               (1<<13)
+#define        ACR_ANY                 (2<<13)
+#define        ACR_CM_WTHRU            (0<<5)
+#define        ACR_CM_WBACK            (1<<5)
+#define        ACR_CM_OFF_PRE          (2<<5)
+#define        ACR_CM_OFF_IMP          (3<<5)
+#define        ACR_WPROTECT            (1<<2)
+
+/*********************************************************************
+ *
+ * Inter-IC (I2C) Module
+ *
+ *********************************************************************/
+
+/* Read/Write access macros for general use */
+#define MCF532x_I2C_I2ADR       (volatile u8 *) (0xFC058000) // Address 
+#define MCF532x_I2C_I2FDR       (volatile u8 *) (0xFC058004) // Freq Divider
+#define MCF532x_I2C_I2CR        (volatile u8 *) (0xFC058008) // Control
+#define MCF532x_I2C_I2SR        (volatile u8 *) (0xFC05800C) // Status
+#define MCF532x_I2C_I2DR        (volatile u8 *) (0xFC058010) // Data I/O
+
+/* Bit level definitions and macros */
+#define MCF532x_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
+
+#define MCF532x_I2C_I2FDR_IC(x)                         (((x)&0x3F))
+
+#define MCF532x_I2C_I2CR_IEN    (0x80) // I2C enable
+#define MCF532x_I2C_I2CR_IIEN   (0x40)  // interrupt enable
+#define MCF532x_I2C_I2CR_MSTA   (0x20)  // master/slave mode
+#define MCF532x_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
+#define MCF532x_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
+#define MCF532x_I2C_I2CR_RSTA   (0x04)  // repeat start
+
+#define MCF532x_I2C_I2SR_ICF    (0x80)  // data transfer bit
+#define MCF532x_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
+#define MCF532x_I2C_I2SR_IBB    (0x20)  // I2C bus busy
+#define MCF532x_I2C_I2SR_IAL    (0x10)  // aribitration lost
+#define MCF532x_I2C_I2SR_SRW    (0x04)  // slave read/write
+#define MCF532x_I2C_I2SR_IIF    (0x02)  // I2C interrupt
+#define MCF532x_I2C_I2SR_RXAK   (0x01)  // received acknowledge
+
+#define MCF532x_PAR_FECI2C     (volatile u8 *) (0xFC0A4053)
+
+
+/*
+ *     The M5329EVB board needs a help getting its devices initialized 
+ *     at kernel start time if dBUG doesn't set it up (for example 
+ *     it is not used), so we need to do it manually.
+ */
+#ifdef __ASSEMBLER__
+.macro m5329EVB_setup
+       movel   #0xFC098000, %a7
+       movel   #0x0, (%a7)
+#define CORE_SRAM      0x80000000      
+#define CORE_SRAM_SIZE 0x8000
+       movel   #CORE_SRAM, %d0
+       addl    #0x221, %d0
+       movec   %d0,%RAMBAR1
+       movel   #CORE_SRAM, %sp
+       addl    #CORE_SRAM_SIZE, %sp
+       jsr     sysinit
+.endm
+#define        PLATFORM_SETUP  m5329EVB_setup
+
+#endif /* __ASSEMBLER__ */
+
+/*********************************************************************
+ *
+ * Chip Configuration Module (CCM)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_CCM_CCR               MCF_REG16(0xFC0A0004)
+#define MCF_CCM_RCON              MCF_REG16(0xFC0A0008)
+#define MCF_CCM_CIR               MCF_REG16(0xFC0A000A)
+#define MCF_CCM_MISCCR            MCF_REG16(0xFC0A0010)
+#define MCF_CCM_CDR               MCF_REG16(0xFC0A0012)
+#define MCF_CCM_UHCSR             MCF_REG16(0xFC0A0014)
+#define MCF_CCM_UOCSR             MCF_REG16(0xFC0A0016)
+
+/* Bit definitions and macros for MCF_CCM_CCR */
+#define MCF_CCM_CCR_RESERVED      (0x0001)
+#define MCF_CCM_CCR_PLL_MODE      (0x0003)
+#define MCF_CCM_CCR_OSC_MODE      (0x0005)
+#define MCF_CCM_CCR_BOOTPS(x)     (((x)&0x0003)<<3|0x0001)
+#define MCF_CCM_CCR_LOAD          (0x0021)
+#define MCF_CCM_CCR_LIMP          (0x0041)
+#define MCF_CCM_CCR_CSC(x)        (((x)&0x0003)<<8|0x0001)
+
+/* Bit definitions and macros for MCF_CCM_RCON */
+#define MCF_CCM_RCON_RESERVED     (0x0001)
+#define MCF_CCM_RCON_PLL_MODE     (0x0003)
+#define MCF_CCM_RCON_OSC_MODE     (0x0005)
+#define MCF_CCM_RCON_BOOTPS(x)    (((x)&0x0003)<<3|0x0001)
+#define MCF_CCM_RCON_LOAD         (0x0021)
+#define MCF_CCM_RCON_LIMP         (0x0041)
+#define MCF_CCM_RCON_CSC(x)       (((x)&0x0003)<<8|0x0001)
+
+/* Bit definitions and macros for MCF_CCM_CIR */
+#define MCF_CCM_CIR_PRN(x)        (((x)&0x003F)<<0)
+#define MCF_CCM_CIR_PIN(x)        (((x)&0x03FF)<<6)
+
+/* Bit definitions and macros for MCF_CCM_MISCCR */
+#define MCF_CCM_MISCCR_USBSRC     (0x0001)
+#define MCF_CCM_MISCCR_USBDIV     (0x0002)
+#define MCF_CCM_MISCCR_SSI_SRC    (0x0010)
+#define MCF_CCM_MISCCR_TIM_DMA   (0x0020)
+#define MCF_CCM_MISCCR_SSI_PUS    (0x0040)
+#define MCF_CCM_MISCCR_SSI_PUE    (0x0080)
+#define MCF_CCM_MISCCR_LCD_CHEN   (0x0100)
+#define MCF_CCM_MISCCR_LIMP       (0x1000)
+#define MCF_CCM_MISCCR_PLL_LOCK   (0x2000)
+
+/* Bit definitions and macros for MCF_CCM_CDR */
+#define MCF_CCM_CDR_SSIDIV(x)     (((x)&0x000F)<<0)
+#define MCF_CCM_CDR_LPDIV(x)      (((x)&0x000F)<<8)
+
+/* Bit definitions and macros for MCF_CCM_UHCSR */
+#define MCF_CCM_UHCSR_XPDE        (0x0001)
+#define MCF_CCM_UHCSR_UHMIE       (0x0002)
+#define MCF_CCM_UHCSR_WKUP        (0x0004)
+#define MCF_CCM_UHCSR_PORTIND(x)  (((x)&0x0003)<<14)
+
+/* Bit definitions and macros for MCF_CCM_UOCSR */
+#define MCF_CCM_UOCSR_XPDE        (0x0001)
+#define MCF_CCM_UOCSR_UOMIE       (0x0002)
+#define MCF_CCM_UOCSR_WKUP        (0x0004)
+#define MCF_CCM_UOCSR_PWRFLT      (0x0008)
+#define MCF_CCM_UOCSR_SEND        (0x0010)
+#define MCF_CCM_UOCSR_VVLD        (0x0020)
+#define MCF_CCM_UOCSR_BVLD        (0x0040)
+#define MCF_CCM_UOCSR_AVLD        (0x0080)
+#define MCF_CCM_UOCSR_DPPU        (0x0100)
+#define MCF_CCM_UOCSR_DCR_VBUS    (0x0200)
+#define MCF_CCM_UOCSR_CRG_VBUS    (0x0400)
+#define MCF_CCM_UOCSR_DRV_VBUS    (0x0800)
+#define MCF_CCM_UOCSR_DMPD        (0x1000)
+#define MCF_CCM_UOCSR_DPPD        (0x2000)
+#define MCF_CCM_UOCSR_PORTIND(x)  (((x)&0x0003)<<14)
+
+/*********************************************************************
+ *
+ * DMA Timers (DTIM)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_DTIM0_DTMR           MCF_REG16(0xFC070000)
+#define MCF_DTIM0_DTXMR          MCF_REG08(0xFC070002)
+#define MCF_DTIM0_DTER           MCF_REG08(0xFC070003)
+#define MCF_DTIM0_DTRR           MCF_REG32(0xFC070004)
+#define MCF_DTIM0_DTCR           MCF_REG32(0xFC070008)
+#define MCF_DTIM0_DTCN           MCF_REG32(0xFC07000C)
+#define MCF_DTIM1_DTMR           MCF_REG16(0xFC074000)
+#define MCF_DTIM1_DTXMR          MCF_REG08(0xFC074002)
+#define MCF_DTIM1_DTER           MCF_REG08(0xFC074003)
+#define MCF_DTIM1_DTRR           MCF_REG32(0xFC074004)
+#define MCF_DTIM1_DTCR           MCF_REG32(0xFC074008)
+#define MCF_DTIM1_DTCN           MCF_REG32(0xFC07400C)
+#define MCF_DTIM2_DTMR           MCF_REG16(0xFC078000)
+#define MCF_DTIM2_DTXMR          MCF_REG08(0xFC078002)
+#define MCF_DTIM2_DTER           MCF_REG08(0xFC078003)
+#define MCF_DTIM2_DTRR           MCF_REG32(0xFC078004)
+#define MCF_DTIM2_DTCR           MCF_REG32(0xFC078008)
+#define MCF_DTIM2_DTCN           MCF_REG32(0xFC07800C)
+#define MCF_DTIM3_DTMR           MCF_REG16(0xFC07C000)
+#define MCF_DTIM3_DTXMR          MCF_REG08(0xFC07C002)
+#define MCF_DTIM3_DTER           MCF_REG08(0xFC07C003)
+#define MCF_DTIM3_DTRR           MCF_REG32(0xFC07C004)
+#define MCF_DTIM3_DTCR           MCF_REG32(0xFC07C008)
+#define MCF_DTIM3_DTCN           MCF_REG32(0xFC07C00C)
+#define MCF_DTIM_DTMR(x)         MCF_REG16(0xFC070000+((x)*0x4000))
+#define MCF_DTIM_DTXMR(x)        MCF_REG08(0xFC070002+((x)*0x4000))
+#define MCF_DTIM_DTER(x)         MCF_REG08(0xFC070003+((x)*0x4000))
+#define MCF_DTIM_DTRR(x)         MCF_REG32(0xFC070004+((x)*0x4000))
+#define MCF_DTIM_DTCR(x)         MCF_REG32(0xFC070008+((x)*0x4000))
+#define MCF_DTIM_DTCN(x)         MCF_REG32(0xFC07000C+((x)*0x4000))
+
+/* Bit definitions and macros for MCF_DTIM_DTMR */
+#define MCF_DTIM_DTMR_RST        (0x0001)
+#define MCF_DTIM_DTMR_CLK(x)     (((x)&0x0003)<<1)
+#define MCF_DTIM_DTMR_FRR        (0x0008)
+#define MCF_DTIM_DTMR_ORRI       (0x0010)
+#define MCF_DTIM_DTMR_OM         (0x0020)
+#define MCF_DTIM_DTMR_CE(x)      (((x)&0x0003)<<6)
+#define MCF_DTIM_DTMR_PS(x)      (((x)&0x00FF)<<8)
+#define MCF_DTIM_DTMR_CE_ANY     (0x00C0)
+#define MCF_DTIM_DTMR_CE_FALL    (0x0080)
+#define MCF_DTIM_DTMR_CE_RISE    (0x0040)
+#define MCF_DTIM_DTMR_CE_NONE    (0x0000)
+#define MCF_DTIM_DTMR_CLK_DTIN   (0x0006)
+#define MCF_DTIM_DTMR_CLK_DIV16  (0x0004)
+#define MCF_DTIM_DTMR_CLK_DIV1   (0x0002)
+#define MCF_DTIM_DTMR_CLK_STOP   (0x0000)
+
+/* Bit definitions and macros for MCF_DTIM_DTXMR */
+#define MCF_DTIM_DTXMR_MODE16    (0x01)
+#define MCF_DTIM_DTXMR_DMAEN     (0x80)
+
+/* Bit definitions and macros for MCF_DTIM_DTER */
+#define MCF_DTIM_DTER_CAP        (0x01)
+#define MCF_DTIM_DTER_REF        (0x02)
+
+/* Bit definitions and macros for MCF_DTIM_DTRR */
+#define MCF_DTIM_DTRR_REF(x)     (((x)&0xFFFFFFFF)<<0)
+
+/* Bit definitions and macros for MCF_DTIM_DTCR */
+#define MCF_DTIM_DTCR_CAP(x)     (((x)&0xFFFFFFFF)<<0)
+
+/* Bit definitions and macros for MCF_DTIM_DTCN */
+#define MCF_DTIM_DTCN_CNT(x)     (((x)&0xFFFFFFFF)<<0)
+
+/*********************************************************************
+ *
+ * FlexBus Chip Selects (FBCS)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_FBCS0_CSAR         MCF_REG32(0xFC008000)
+#define MCF_FBCS0_CSMR         MCF_REG32(0xFC008004)
+#define MCF_FBCS0_CSCR         MCF_REG32(0xFC008008)
+#define MCF_FBCS1_CSAR         MCF_REG32(0xFC00800C)
+#define MCF_FBCS1_CSMR         MCF_REG32(0xFC008010)
+#define MCF_FBCS1_CSCR         MCF_REG32(0xFC008014)
+#define MCF_FBCS2_CSAR         MCF_REG32(0xFC008018)
+#define MCF_FBCS2_CSMR         MCF_REG32(0xFC00801C)
+#define MCF_FBCS2_CSCR         MCF_REG32(0xFC008020)
+#define MCF_FBCS3_CSAR         MCF_REG32(0xFC008024)
+#define MCF_FBCS3_CSMR         MCF_REG32(0xFC008028)
+#define MCF_FBCS3_CSCR         MCF_REG32(0xFC00802C)
+#define MCF_FBCS4_CSAR         MCF_REG32(0xFC008030)
+#define MCF_FBCS4_CSMR         MCF_REG32(0xFC008034)
+#define MCF_FBCS4_CSCR         MCF_REG32(0xFC008038)
+#define MCF_FBCS5_CSAR         MCF_REG32(0xFC00803C)
+#define MCF_FBCS5_CSMR         MCF_REG32(0xFC008040)
+#define MCF_FBCS5_CSCR         MCF_REG32(0xFC008044)
+#define MCF_FBCS_CSAR(x)       MCF_REG32(0xFC008000+((x)*0x00C))
+#define MCF_FBCS_CSMR(x)       MCF_REG32(0xFC008004+((x)*0x00C))
+#define MCF_FBCS_CSCR(x)       MCF_REG32(0xFC008008+((x)*0x00C))
+
+/* Bit definitions and macros for MCF_FBCS_CSAR */
+#define MCF_FBCS_CSAR_BA(x)    ((x)&0xFFFF0000)
+
+/* Bit definitions and macros for MCF_FBCS_CSMR */
+#define MCF_FBCS_CSMR_V                (0x00000001)
+#define MCF_FBCS_CSMR_WP       (0x00000100)
+#define MCF_FBCS_CSMR_BAM(x)   (((x)&0x0000FFFF)<<16)
+#define MCF_FBCS_CSMR_BAM_4G   (0xFFFF0000)
+#define MCF_FBCS_CSMR_BAM_2G   (0x7FFF0000)
+#define MCF_FBCS_CSMR_BAM_1G   (0x3FFF0000)
+#define MCF_FBCS_CSMR_BAM_1024M        (0x3FFF0000)
+#define MCF_FBCS_CSMR_BAM_512M (0x1FFF0000)
+#define MCF_FBCS_CSMR_BAM_256M (0x0FFF0000)
+#define MCF_FBCS_CSMR_BAM_128M (0x07FF0000)
+#define MCF_FBCS_CSMR_BAM_64M  (0x03FF0000)
+#define MCF_FBCS_CSMR_BAM_32M  (0x01FF0000)
+#define MCF_FBCS_CSMR_BAM_16M  (0x00FF0000)
+#define MCF_FBCS_CSMR_BAM_8M   (0x007F0000)
+#define MCF_FBCS_CSMR_BAM_4M   (0x003F0000)
+#define MCF_FBCS_CSMR_BAM_2M   (0x001F0000)
+#define MCF_FBCS_CSMR_BAM_1M   (0x000F0000)
+#define MCF_FBCS_CSMR_BAM_1024K        (0x000F0000)
+#define MCF_FBCS_CSMR_BAM_512K (0x00070000)
+#define MCF_FBCS_CSMR_BAM_256K (0x00030000)
+#define MCF_FBCS_CSMR_BAM_128K (0x00010000)
+#define MCF_FBCS_CSMR_BAM_64K  (0x00000000)
+
+/* Bit definitions and macros for MCF_FBCS_CSCR */
+#define MCF_FBCS_CSCR_BSTW     (0x00000008)
+#define MCF_FBCS_CSCR_BSTR     (0x00000010)
+#define MCF_FBCS_CSCR_BEM      (0x00000020)
+#define MCF_FBCS_CSCR_PS(x)    (((x)&0x00000003)<<6)
+#define MCF_FBCS_CSCR_AA       (0x00000100)
+#define MCF_FBCS_CSCR_SBM      (0x00000200)
+#define MCF_FBCS_CSCR_WS(x)    (((x)&0x0000003F)<<10)
+#define MCF_FBCS_CSCR_WRAH(x)  (((x)&0x00000003)<<16)
+#define MCF_FBCS_CSCR_RDAH(x)  (((x)&0x00000003)<<18)
+#define MCF_FBCS_CSCR_ASET(x)  (((x)&0x00000003)<<20)
+#define MCF_FBCS_CSCR_SWSEN    (0x00800000)
+#define MCF_FBCS_CSCR_SWS(x)   (((x)&0x0000003F)<<26)
+#define MCF_FBCS_CSCR_PS_8     (0x0040)
+#define MCF_FBCS_CSCR_PS_16    (0x0080)
+#define MCF_FBCS_CSCR_PS_32    (0x0000)
+
+/*********************************************************************
+ *
+ * General Purpose I/O (GPIO)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_GPIO_PODR_FECH             MCF_REG08(0xFC0A4000)
+#define MCF_GPIO_PODR_FECL             MCF_REG08(0xFC0A4001)
+#define MCF_GPIO_PODR_SSI              MCF_REG08(0xFC0A4002)
+#define MCF_GPIO_PODR_BUSCTL           MCF_REG08(0xFC0A4003)
+#define MCF_GPIO_PODR_BE               MCF_REG08(0xFC0A4004)
+#define MCF_GPIO_PODR_CS               MCF_REG08(0xFC0A4005)
+#define MCF_GPIO_PODR_PWM              MCF_REG08(0xFC0A4006)
+#define MCF_GPIO_PODR_FECI2C           MCF_REG08(0xFC0A4007)
+#define MCF_GPIO_PODR_UART             MCF_REG08(0xFC0A4009)
+#define MCF_GPIO_PODR_QSPI             MCF_REG08(0xFC0A400A)
+#define MCF_GPIO_PODR_TIMER            MCF_REG08(0xFC0A400B)
+#define MCF_GPIO_PODR_LCDDATAH         MCF_REG08(0xFC0A400D)
+#define MCF_GPIO_PODR_LCDDATAM         MCF_REG08(0xFC0A400E)
+#define MCF_GPIO_PODR_LCDDATAL         MCF_REG08(0xFC0A400F)
+#define MCF_GPIO_PODR_LCDCTLH          MCF_REG08(0xFC0A4010)
+#define MCF_GPIO_PODR_LCDCTLL          MCF_REG08(0xFC0A4011)
+#define MCF_GPIO_PDDR_FECH             MCF_REG08(0xFC0A4014)
+#define MCF_GPIO_PDDR_FECL             MCF_REG08(0xFC0A4015)
+#define MCF_GPIO_PDDR_SSI              MCF_REG08(0xFC0A4016)
+#define MCF_GPIO_PDDR_BUSCTL           MCF_REG08(0xFC0A4017)
+#define MCF_GPIO_PDDR_BE               MCF_REG08(0xFC0A4018)
+#define MCF_GPIO_PDDR_CS               MCF_REG08(0xFC0A4019)
+#define MCF_GPIO_PDDR_PWM              MCF_REG08(0xFC0A401A)
+#define MCF_GPIO_PDDR_FECI2C           MCF_REG08(0xFC0A401B)
+#define MCF_GPIO_PDDR_UART             MCF_REG08(0xFC0A401C)
+#define MCF_GPIO_PDDR_QSPI             MCF_REG08(0xFC0A401E)
+#define MCF_GPIO_PDDR_TIMER            MCF_REG08(0xFC0A401F)
+#define MCF_GPIO_PDDR_LCDDATAH         MCF_REG08(0xFC0A4021)
+#define MCF_GPIO_PDDR_LCDDATAM         MCF_REG08(0xFC0A4022)
+#define MCF_GPIO_PDDR_LCDDATAL         MCF_REG08(0xFC0A4023)
+#define MCF_GPIO_PDDR_LCDCTLH          MCF_REG08(0xFC0A4024)
+#define MCF_GPIO_PDDR_LCDCTLL          MCF_REG08(0xFC0A4025)
+#define MCF_GPIO_PPDSDR_FECH           MCF_REG08(0xFC0A4028)
+#define MCF_GPIO_PPDSDR_FECL           MCF_REG08(0xFC0A4029)
+#define MCF_GPIO_PPDSDR_SSI            MCF_REG08(0xFC0A402A)
+#define MCF_GPIO_PPDSDR_BUSCTL         MCF_REG08(0xFC0A402B)
+#define MCF_GPIO_PPDSDR_BE             MCF_REG08(0xFC0A402C)
+#define MCF_GPIO_PPDSDR_CS             MCF_REG08(0xFC0A402D)
+#define MCF_GPIO_PPDSDR_PWM            MCF_REG08(0xFC0A402E)
+#define MCF_GPIO_PPDSDR_FECI2C         MCF_REG08(0xFC0A402F)
+#define MCF_GPIO_PPDSDR_UART           MCF_REG08(0xFC0A4031)
+#define MCF_GPIO_PPDSDR_QSPI           MCF_REG08(0xFC0A4032)
+#define MCF_GPIO_PPDSDR_TIMER          MCF_REG08(0xFC0A4033)
+#define MCF_GPIO_PPDSDR_LCDDATAH       MCF_REG08(0xFC0A4035)
+#define MCF_GPIO_PPDSDR_LCDDATAM       MCF_REG08(0xFC0A4036)
+#define MCF_GPIO_PPDSDR_LCDDATAL       MCF_REG08(0xFC0A4037)
+#define MCF_GPIO_PPDSDR_LCDCTLH                MCF_REG08(0xFC0A4038)
+#define MCF_GPIO_PPDSDR_LCDCTLL                MCF_REG08(0xFC0A4039)
+#define MCF_GPIO_PCLRR_FECH            MCF_REG08(0xFC0A403C)
+#define MCF_GPIO_PCLRR_FECL            MCF_REG08(0xFC0A403D)
+#define MCF_GPIO_PCLRR_SSI             MCF_REG08(0xFC0A403E)
+#define MCF_GPIO_PCLRR_BUSCTL          MCF_REG08(0xFC0A403F)
+#define MCF_GPIO_PCLRR_BE              MCF_REG08(0xFC0A4040)
+#define MCF_GPIO_PCLRR_CS              MCF_REG08(0xFC0A4041)
+#define MCF_GPIO_PCLRR_PWM             MCF_REG08(0xFC0A4042)
+#define MCF_GPIO_PCLRR_FECI2C          MCF_REG08(0xFC0A4043)
+#define MCF_GPIO_PCLRR_UART            MCF_REG08(0xFC0A4045)
+#define MCF_GPIO_PCLRR_QSPI            MCF_REG08(0xFC0A4046)
+#define MCF_GPIO_PCLRR_TIMER           MCF_REG08(0xFC0A4047)
+#define MCF_GPIO_PCLRR_LCDDATAH                MCF_REG08(0xFC0A4049)
+#define MCF_GPIO_PCLRR_LCDDATAM                MCF_REG08(0xFC0A404A)
+#define MCF_GPIO_PCLRR_LCDDATAL                MCF_REG08(0xFC0A404B)
+#define MCF_GPIO_PCLRR_LCDCTLH         MCF_REG08(0xFC0A404C)
+#define MCF_GPIO_PCLRR_LCDCTLL         MCF_REG08(0xFC0A404D)
+#define MCF_GPIO_PAR_FEC               MCF_REG08(0xFC0A4050)
+#define MCF_GPIO_PAR_PWM               MCF_REG08(0xFC0A4051)
+#define MCF_GPIO_PAR_BUSCTL            MCF_REG08(0xFC0A4052)
+#define MCF_GPIO_PAR_FECI2C            MCF_REG08(0xFC0A4053)
+#define MCF_GPIO_PAR_BE                        MCF_REG08(0xFC0A4054)
+#define MCF_GPIO_PAR_CS                        MCF_REG08(0xFC0A4055)
+#define MCF_GPIO_PAR_SSI               MCF_REG16(0xFC0A4056)
+#define MCF_GPIO_PAR_UART              MCF_REG16(0xFC0A4058)
+#define MCF_GPIO_PAR_QSPI              MCF_REG16(0xFC0A405A)
+#define MCF_GPIO_PAR_TIMER             MCF_REG08(0xFC0A405C)
+#define MCF_GPIO_PAR_LCDDATA           MCF_REG08(0xFC0A405D)
+#define MCF_GPIO_PAR_LCDCTL            MCF_REG16(0xFC0A405E)
+#define MCF_GPIO_PAR_IRQ               MCF_REG16(0xFC0A4060)
+#define MCF_GPIO_MSCR_FLEXBUS          MCF_REG08(0xFC0A4064)
+#define MCF_GPIO_MSCR_SDRAM            MCF_REG08(0xFC0A4065)
+#define MCF_GPIO_DSCR_I2C              MCF_REG08(0xFC0A4068)
+#define MCF_GPIO_DSCR_PWM              MCF_REG08(0xFC0A4069)
+#define MCF_GPIO_DSCR_FEC              MCF_REG08(0xFC0A406A)
+#define MCF_GPIO_DSCR_UART             MCF_REG08(0xFC0A406B)
+#define MCF_GPIO_DSCR_QSPI             MCF_REG08(0xFC0A406C)
+#define MCF_GPIO_DSCR_TIMER            MCF_REG08(0xFC0A406D)
+#define MCF_GPIO_DSCR_SSI              MCF_REG08(0xFC0A406E)
+#define MCF_GPIO_DSCR_LCD              MCF_REG08(0xFC0A406F)
+#define MCF_GPIO_DSCR_DEBUG            MCF_REG08(0xFC0A4070)
+#define MCF_GPIO_DSCR_CLKRST           MCF_REG08(0xFC0A4071)
+#define MCF_GPIO_DSCR_IRQ              MCF_REG08(0xFC0A4072)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_FECH */
+#define MCF_GPIO_PODR_FECH_PODR_FECH0              (0x01)
+#define MCF_GPIO_PODR_FECH_PODR_FECH1              (0x02)
+#define MCF_GPIO_PODR_FECH_PODR_FECH2              (0x04)
+#define MCF_GPIO_PODR_FECH_PODR_FECH3              (0x08)
+#define MCF_GPIO_PODR_FECH_PODR_FECH4              (0x10)
+#define MCF_GPIO_PODR_FECH_PODR_FECH5              (0x20)
+#define MCF_GPIO_PODR_FECH_PODR_FECH6              (0x40)
+#define MCF_GPIO_PODR_FECH_PODR_FECH7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_FECL */
+#define MCF_GPIO_PODR_FECL_PODR_FECL0              (0x01)
+#define MCF_GPIO_PODR_FECL_PODR_FECL1              (0x02)
+#define MCF_GPIO_PODR_FECL_PODR_FECL2              (0x04)
+#define MCF_GPIO_PODR_FECL_PODR_FECL3              (0x08)
+#define MCF_GPIO_PODR_FECL_PODR_FECL4              (0x10)
+#define MCF_GPIO_PODR_FECL_PODR_FECL5              (0x20)
+#define MCF_GPIO_PODR_FECL_PODR_FECL6              (0x40)
+#define MCF_GPIO_PODR_FECL_PODR_FECL7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_SSI */
+#define MCF_GPIO_PODR_SSI_PODR_SSI0                (0x01)
+#define MCF_GPIO_PODR_SSI_PODR_SSI1                (0x02)
+#define MCF_GPIO_PODR_SSI_PODR_SSI2                (0x04)
+#define MCF_GPIO_PODR_SSI_PODR_SSI3                (0x08)
+#define MCF_GPIO_PODR_SSI_PODR_SSI4                (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_BUSCTL */
+#define MCF_GPIO_PODR_BUSCTL_POSDR_BUSCTL0         (0x01)
+#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL1          (0x02)
+#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL2          (0x04)
+#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_BE */
+#define MCF_GPIO_PODR_BE_PODR_BE0                  (0x01)
+#define MCF_GPIO_PODR_BE_PODR_BE1                  (0x02)
+#define MCF_GPIO_PODR_BE_PODR_BE2                  (0x04)
+#define MCF_GPIO_PODR_BE_PODR_BE3                  (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_CS */
+#define MCF_GPIO_PODR_CS_PODR_CS1                  (0x02)
+#define MCF_GPIO_PODR_CS_PODR_CS2                  (0x04)
+#define MCF_GPIO_PODR_CS_PODR_CS3                  (0x08)
+#define MCF_GPIO_PODR_CS_PODR_CS4                  (0x10)
+#define MCF_GPIO_PODR_CS_PODR_CS5                  (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_PWM */
+#define MCF_GPIO_PODR_PWM_PODR_PWM2                (0x04)
+#define MCF_GPIO_PODR_PWM_PODR_PWM3                (0x08)
+#define MCF_GPIO_PODR_PWM_PODR_PWM4                (0x10)
+#define MCF_GPIO_PODR_PWM_PODR_PWM5                (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_FECI2C */
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C0          (0x01)
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C1          (0x02)
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C2          (0x04)
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_UART */
+#define MCF_GPIO_PODR_UART_PODR_UART0              (0x01)
+#define MCF_GPIO_PODR_UART_PODR_UART1              (0x02)
+#define MCF_GPIO_PODR_UART_PODR_UART2              (0x04)
+#define MCF_GPIO_PODR_UART_PODR_UART3              (0x08)
+#define MCF_GPIO_PODR_UART_PODR_UART4              (0x10)
+#define MCF_GPIO_PODR_UART_PODR_UART5              (0x20)
+#define MCF_GPIO_PODR_UART_PODR_UART6              (0x40)
+#define MCF_GPIO_PODR_UART_PODR_UART7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_QSPI */
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI0              (0x01)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI1              (0x02)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI2              (0x04)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI3              (0x08)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI4              (0x10)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_TIMER */
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER0            (0x01)
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER1            (0x02)
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER2            (0x04)
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER3            (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAH */
+#define MCF_GPIO_PODR_LCDDATAH_PODR_LCDDATAH0      (0x01)
+#define MCF_GPIO_PODR_LCDDATAH_PODR_LCDDATAH1      (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAM */
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM0      (0x01)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM1      (0x02)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM2      (0x04)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM3      (0x08)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM4      (0x10)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM5      (0x20)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM6      (0x40)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAL */
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL0      (0x01)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL1      (0x02)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL2      (0x04)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL3      (0x08)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL4      (0x10)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL5      (0x20)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL6      (0x40)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDCTLH */
+#define MCF_GPIO_PODR_LCDCTLH_PODR_LCDCTLH0        (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDCTLL */
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL0        (0x01)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL1        (0x02)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL2        (0x04)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL3        (0x08)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL4        (0x10)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL5        (0x20)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL6        (0x40)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL7        (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_FECH */
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH0              (0x01)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH1              (0x02)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH2              (0x04)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH3              (0x08)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH4              (0x10)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH5              (0x20)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH6              (0x40)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_FECL */
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL0              (0x01)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL1              (0x02)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL2              (0x04)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL3              (0x08)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL4              (0x10)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL5              (0x20)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL6              (0x40)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_SSI */
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI0                (0x01)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI1                (0x02)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI2                (0x04)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI3                (0x08)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI4                (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_BUSCTL */
+#define MCF_GPIO_PDDR_BUSCTL_POSDR_BUSCTL0         (0x01)
+#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL1          (0x02)
+#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL2          (0x04)
+#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_BE */
+#define MCF_GPIO_PDDR_BE_PDDR_BE0                  (0x01)
+#define MCF_GPIO_PDDR_BE_PDDR_BE1                  (0x02)
+#define MCF_GPIO_PDDR_BE_PDDR_BE2                  (0x04)
+#define MCF_GPIO_PDDR_BE_PDDR_BE3                  (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_CS */
+#define MCF_GPIO_PDDR_CS_PDDR_CS1                  (0x02)
+#define MCF_GPIO_PDDR_CS_PDDR_CS2                  (0x04)
+#define MCF_GPIO_PDDR_CS_PDDR_CS3                  (0x08)
+#define MCF_GPIO_PDDR_CS_PDDR_CS4                  (0x10)
+#define MCF_GPIO_PDDR_CS_PDDR_CS5                  (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_PWM */
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM2                (0x04)
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM3                (0x08)
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM4                (0x10)
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM5                (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_FECI2C */
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0          (0x01)
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1          (0x02)
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C2          (0x04)
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_UART */
+#define MCF_GPIO_PDDR_UART_PDDR_UART0              (0x01)
+#define MCF_GPIO_PDDR_UART_PDDR_UART1              (0x02)
+#define MCF_GPIO_PDDR_UART_PDDR_UART2              (0x04)
+#define MCF_GPIO_PDDR_UART_PDDR_UART3              (0x08)
+#define MCF_GPIO_PDDR_UART_PDDR_UART4              (0x10)
+#define MCF_GPIO_PDDR_UART_PDDR_UART5              (0x20)
+#define MCF_GPIO_PDDR_UART_PDDR_UART6              (0x40)
+#define MCF_GPIO_PDDR_UART_PDDR_UART7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_QSPI */
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI0              (0x01)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI1              (0x02)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI2              (0x04)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI3              (0x08)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI4              (0x10)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_TIMER */
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER0            (0x01)
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER1            (0x02)
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER2            (0x04)
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER3            (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAH */
+#define MCF_GPIO_PDDR_LCDDATAH_PDDR_LCDDATAH0      (0x01)
+#define MCF_GPIO_PDDR_LCDDATAH_PDDR_LCDDATAH1      (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAM */
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM0      (0x01)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM1      (0x02)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM2      (0x04)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM3      (0x08)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM4      (0x10)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM5      (0x20)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM6      (0x40)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAL */
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL0      (0x01)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL1      (0x02)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL2      (0x04)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL3      (0x08)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL4      (0x10)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL5      (0x20)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL6      (0x40)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDCTLH */
+#define MCF_GPIO_PDDR_LCDCTLH_PDDR_LCDCTLH0        (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDCTLL */
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL0        (0x01)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL1        (0x02)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL2        (0x04)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL3        (0x08)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL4        (0x10)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL5        (0x20)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL6        (0x40)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL7        (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECH */
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH0          (0x01)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH1          (0x02)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH2          (0x04)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH3          (0x08)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH4          (0x10)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH5          (0x20)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH6          (0x40)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH7          (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECL */
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL0          (0x01)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL1          (0x02)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL2          (0x04)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL3          (0x08)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL4          (0x10)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL5          (0x20)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL6          (0x40)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL7          (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_SSI */
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI0            (0x01)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI1            (0x02)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI2            (0x04)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI3            (0x08)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI4            (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_BUSCTL */
+#define MCF_GPIO_PPDSDR_BUSCTL_POSDR_BUSCTL0       (0x01)
+#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL1      (0x02)
+#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL2      (0x04)
+#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL3      (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_BE */
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE0              (0x01)
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE1              (0x02)
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE2              (0x04)
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE3              (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_CS */
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS1              (0x02)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS2              (0x04)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS3              (0x08)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS4              (0x10)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_PWM */
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM2            (0x04)
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM3            (0x08)
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM4            (0x10)
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM5            (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECI2C */
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C0      (0x01)
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C1      (0x02)
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C2      (0x04)
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C3      (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_UART */
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART0          (0x01)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART1          (0x02)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART2          (0x04)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART3          (0x08)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART4          (0x10)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART5          (0x20)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART6          (0x40)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART7          (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_QSPI */
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI0          (0x01)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI1          (0x02)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI2          (0x04)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI3          (0x08)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI4          (0x10)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI5          (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_TIMER */
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER0        (0x01)
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER1        (0x02)
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER2        (0x04)
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER3        (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAH */
+#define MCF_GPIO_PPDSDR_LCDDATAH_PPDSDR_LCDDATAH0  (0x01)
+#define MCF_GPIO_PPDSDR_LCDDATAH_PPDSDR_LCDDATAH1  (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAM */
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM0  (0x01)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM1  (0x02)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM2  (0x04)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM3  (0x08)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM4  (0x10)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM5  (0x20)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM6  (0x40)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM7  (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAL */
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL0  (0x01)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL1  (0x02)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL2  (0x04)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL3  (0x08)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL4  (0x10)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL5  (0x20)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL6  (0x40)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL7  (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDCTLH */
+#define MCF_GPIO_PPDSDR_LCDCTLH_PPDSDR_LCDCTLH0    (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDCTLL */
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL0    (0x01)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL1    (0x02)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL2    (0x04)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL3    (0x08)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL4    (0x10)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL5    (0x20)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL6    (0x40)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL7    (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_FECH */
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH0            (0x01)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH1            (0x02)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH2            (0x04)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH3            (0x08)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH4            (0x10)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH5            (0x20)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH6            (0x40)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH7            (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_FECL */
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL0            (0x01)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL1            (0x02)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL2            (0x04)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL3            (0x08)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL4            (0x10)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL5            (0x20)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL6            (0x40)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL7            (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_SSI */
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI0              (0x01)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI1              (0x02)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI2              (0x04)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI3              (0x08)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI4              (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_BUSCTL */
+#define MCF_GPIO_PCLRR_BUSCTL_POSDR_BUSCTL0        (0x01)
+#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL1        (0x02)
+#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL2        (0x04)
+#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL3        (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_BE */
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE0                (0x01)
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE1                (0x02)
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE2                (0x04)
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE3                (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_CS */
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS1                (0x02)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS2                (0x04)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS3                (0x08)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS4                (0x10)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS5                (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_PWM */
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM2              (0x04)
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM3              (0x08)
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM4              (0x10)
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_FECI2C */
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C0        (0x01)
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C1        (0x02)
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C2        (0x04)
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C3        (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_UART */
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART0            (0x01)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART1            (0x02)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART2            (0x04)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART3            (0x08)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART4            (0x10)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART5            (0x20)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART6            (0x40)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART7            (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_QSPI */
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI0            (0x01)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI1            (0x02)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI2            (0x04)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI3            (0x08)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI4            (0x10)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI5            (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_TIMER */
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER0          (0x01)
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER1          (0x02)
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER2          (0x04)
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAH */
+#define MCF_GPIO_PCLRR_LCDDATAH_PCLRR_LCDDATAH0    (0x01)
+#define MCF_GPIO_PCLRR_LCDDATAH_PCLRR_LCDDATAH1    (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAM */
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM0    (0x01)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM1    (0x02)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM2    (0x04)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM3    (0x08)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM4    (0x10)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM5    (0x20)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM6    (0x40)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM7    (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAL */
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL0    (0x01)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL1    (0x02)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL2    (0x04)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL3    (0x08)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL4    (0x10)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL5    (0x20)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL6    (0x40)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL7    (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDCTLH */
+#define MCF_GPIO_PCLRR_LCDCTLH_PCLRR_LCDCTLH0      (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDCTLL */
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL0      (0x01)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL1      (0x02)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL2      (0x04)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL3      (0x08)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL4      (0x10)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL5      (0x20)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL6      (0x40)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_FEC */
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII(x)            (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W(x)             (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_GPIO           (0x00)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_URTS1          (0x04)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC            (0x0C)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_GPIO          (0x00)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_UART          (0x01)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC           (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_PWM */
+#define MCF_GPIO_PAR_PWM_PAR_PWM1(x)               (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_PWM_PAR_PWM3(x)               (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_PWM_PAR_PWM5                  (0x10)
+#define MCF_GPIO_PAR_PWM_PAR_PWM7                  (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_BUSCTL */
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS(x)              (((x)&0x03)<<3)
+#define MCF_GPIO_PAR_BUSCTL_PAR_RWB                (0x20)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TA                 (0x40)
+#define MCF_GPIO_PAR_BUSCTL_PAR_OE                 (0x80)
+#define MCF_GPIO_PAR_BUSCTL_PAR_OE_GPIO            (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_OE_OE              (0x80)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TA_GPIO            (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TA_TA              (0x40)
+#define MCF_GPIO_PAR_BUSCTL_PAR_RWB_GPIO           (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_RWB_RWB            (0x20)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS_GPIO            (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS_DACK0           (0x10)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS_TS              (0x18)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_FECI2C */
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA(x)             (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL(x)             (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO(x)            (((x)&0x03)<<4)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC(x)             (((x)&0x03)<<6)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_GPIO           (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_UTXD2          (0x40)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_SCL            (0x80)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC           (0xC0)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_GPIO          (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_URXD2         (0x10)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_SDA           (0x20)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO         (0x30)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL_GPIO           (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2          (0x04)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL_SCL            (0x0C)
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA_GPIO           (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2          (0x02)
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA_SDA            (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_BE */
+#define MCF_GPIO_PAR_BE_PAR_BE0                    (0x01)
+#define MCF_GPIO_PAR_BE_PAR_BE1                    (0x02)
+#define MCF_GPIO_PAR_BE_PAR_BE2                    (0x04)
+#define MCF_GPIO_PAR_BE_PAR_BE3                    (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_CS */
+#define MCF_GPIO_PAR_CS_PAR_CS1                    (0x02)
+#define MCF_GPIO_PAR_CS_PAR_CS2                    (0x04)
+#define MCF_GPIO_PAR_CS_PAR_CS3                    (0x08)
+#define MCF_GPIO_PAR_CS_PAR_CS4                    (0x10)
+#define MCF_GPIO_PAR_CS_PAR_CS5                    (0x20)
+#define MCF_GPIO_PAR_CS_PAR_CS_CS1_GPIO            (0x00)
+#define MCF_GPIO_PAR_CS_PAR_CS_CS1_SDCS1           (0x01)
+#define MCF_GPIO_PAR_CS_PAR_CS_CS1_CS1             (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_SSI */
+#define MCF_GPIO_PAR_SSI_PAR_MCLK                  (0x0080)
+#define MCF_GPIO_PAR_SSI_PAR_TXD(x)                (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_SSI_PAR_RXD(x)                (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_SSI_PAR_FS(x)                 (((x)&0x0003)<<12)
+#define MCF_GPIO_PAR_SSI_PAR_BCLK(x)               (((x)&0x0003)<<14)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_UART */
+#define MCF_GPIO_PAR_UART_PAR_UTXD0                (0x0001)
+#define MCF_GPIO_PAR_UART_PAR_URXD0                (0x0002)
+#define MCF_GPIO_PAR_UART_PAR_URTS0                (0x0004)
+#define MCF_GPIO_PAR_UART_PAR_UCTS0                (0x0008)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1(x)             (((x)&0x0003)<<4)
+#define MCF_GPIO_PAR_UART_PAR_URXD1(x)             (((x)&0x0003)<<6)
+#define MCF_GPIO_PAR_UART_PAR_URTS1(x)             (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1(x)             (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_SSI_BCLK       (0x0800)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_ULPI_D7        (0x0400)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_UCTS1          (0x0C00)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_SSI_FS         (0x0200)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_ULPI_D6        (0x0100)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_URTS1          (0x0300)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_SSI_RXD        (0x0080)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_ULPI_D5        (0x0040)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_URXD1          (0x00C0)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_SSI_TXD        (0x0020)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_ULPI_D4        (0x0010)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_UTXD1          (0x0030)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_QSPI */
+#define MCF_GPIO_PAR_QSPI_PAR_SCK(x)               (((x)&0x0003)<<4)
+#define MCF_GPIO_PAR_QSPI_PAR_DOUT(x)              (((x)&0x0003)<<6)
+#define MCF_GPIO_PAR_QSPI_PAR_DIN(x)               (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_QSPI_PAR_PCS0(x)              (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_QSPI_PAR_PCS1(x)              (((x)&0x0003)<<12)
+#define MCF_GPIO_PAR_QSPI_PAR_PCS2(x)              (((x)&0x0003)<<14)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_TIMER */
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0(x)             (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1(x)             (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2(x)             (((x)&0x03)<<4)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3(x)             (((x)&0x03)<<6)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_TOUT3          (0x80)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_URXD2          (0x40)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_TIN3           (0xC0)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_TOUT2          (0x20)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_UTXD2          (0x10)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_TIN2           (0x30)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_TOUT1          (0x08)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_DACK1          (0x04)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_TIN1           (0x0C)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_TOUT0          (0x02)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_DREQ0          (0x01)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_TIN0           (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_LCDDATA */
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD7_0(x)          (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD15_8(x)         (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD16(x)           (((x)&0x03)<<4)
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD17(x)           (((x)&0x03)<<6)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_LCDCTL */
+#define MCF_GPIO_PAR_LCDCTL_PAR_CLS                (0x0001)
+#define MCF_GPIO_PAR_LCDCTL_PAR_PS                 (0x0002)
+#define MCF_GPIO_PAR_LCDCTL_PAR_REV                (0x0004)
+#define MCF_GPIO_PAR_LCDCTL_PAR_SPL_SPR            (0x0008)
+#define MCF_GPIO_PAR_LCDCTL_PAR_CONTRAST           (0x0010)
+#define MCF_GPIO_PAR_LCDCTL_PAR_LSCLK              (0x0020)
+#define MCF_GPIO_PAR_LCDCTL_PAR_LP_HSYNC           (0x0040)
+#define MCF_GPIO_PAR_LCDCTL_PAR_FLM_VSYNC          (0x0080)
+#define MCF_GPIO_PAR_LCDCTL_PAR_ACD_OE             (0x0100)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_IRQ */
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ1(x)               (((x)&0x0003)<<4)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ2(x)               (((x)&0x0003)<<6)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ4(x)               (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ5(x)               (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ6(x)               (((x)&0x0003)<<12)
+
+/* Bit definitions and macros for MCF_GPIO_MSCR_FLEXBUS */
+#define MCF_GPIO_MSCR_FLEXBUS_MSCR_ADDRCTL(x)      (((x)&0x03)<<0)
+#define MCF_GPIO_MSCR_FLEXBUS_MSCR_DLOWER(x)       (((x)&0x03)<<2)
+#define MCF_GPIO_MSCR_FLEXBUS_MSCR_DUPPER(x)       (((x)&0x03)<<4)
+
+/* Bit definitions and macros for MCF_GPIO_MSCR_SDRAM */
+#define MCF_GPIO_MSCR_SDRAM_MSCR_SDRAM(x)          (((x)&0x03)<<0)
+#define MCF_GPIO_MSCR_SDRAM_MSCR_SDCLK(x)          (((x)&0x03)<<2)
+#define MCF_GPIO_MSCR_SDRAM_MSCR_SDCLKB(x)         (((x)&0x03)<<4)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_I2C */
+#define MCF_GPIO_DSCR_I2C_I2C_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_PWM */
+#define MCF_GPIO_DSCR_PWM_PWM_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_FEC */
+#define MCF_GPIO_DSCR_FEC_FEC_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_UART */
+#define MCF_GPIO_DSCR_UART_UART0_DSE(x)            (((x)&0x03)<<0)
+#define MCF_GPIO_DSCR_UART_UART1_DSE(x)            (((x)&0x03)<<2)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_QSPI */
+#define MCF_GPIO_DSCR_QSPI_QSPI_DSE(x)             (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_TIMER */
+#define MCF_GPIO_DSCR_TIMER_TIMER_DSE(x)           (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_SSI */
+#define MCF_GPIO_DSCR_SSI_SSI_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_LCD */
+#define MCF_GPIO_DSCR_LCD_LCD_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_DEBUG */
+#define MCF_GPIO_DSCR_DEBUG_DEBUG_DSE(x)           (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_CLKRST */
+#define MCF_GPIO_DSCR_CLKRST_CLKRST_DSE(x)         (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_IRQ */
+#define MCF_GPIO_DSCR_IRQ_IRQ_DSE(x)               (((x)&0x03)<<0)
+
+/*********************************************************************
+ *
+ * Interrupt Controller (INTC)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_INTC0_IPRH             MCF_REG32(0xFC048000)
+#define MCF_INTC0_IPRL             MCF_REG32(0xFC048004)
+#define MCF_INTC0_IMRH             MCF_REG32(0xFC048008)
+#define MCF_INTC0_IMRL             MCF_REG32(0xFC04800C)
+#define MCF_INTC0_INTFRCH          MCF_REG32(0xFC048010)
+#define MCF_INTC0_INTFRCL          MCF_REG32(0xFC048014)
+#define MCF_INTC0_ICONFIG          MCF_REG16(0xFC04801A)
+#define MCF_INTC0_SIMR             MCF_REG08(0xFC04801C)
+#define MCF_INTC0_CIMR             MCF_REG08(0xFC04801D)
+#define MCF_INTC0_CLMASK           MCF_REG08(0xFC04801E)
+#define MCF_INTC0_SLMASK           MCF_REG08(0xFC04801F)
+#define MCF_INTC0_ICR0             MCF_REG08(0xFC048040)
+#define MCF_INTC0_ICR1             MCF_REG08(0xFC048041)
+#define MCF_INTC0_ICR2             MCF_REG08(0xFC048042)
+#define MCF_INTC0_ICR3             MCF_REG08(0xFC048043)
+#define MCF_INTC0_ICR4             MCF_REG08(0xFC048044)
+#define MCF_INTC0_ICR5             MCF_REG08(0xFC048045)
+#define MCF_INTC0_ICR6             MCF_REG08(0xFC048046)
+#define MCF_INTC0_ICR7             MCF_REG08(0xFC048047)
+#define MCF_INTC0_ICR8             MCF_REG08(0xFC048048)
+#define MCF_INTC0_ICR9             MCF_REG08(0xFC048049)
+#define MCF_INTC0_ICR10            MCF_REG08(0xFC04804A)
+#define MCF_INTC0_ICR11            MCF_REG08(0xFC04804B)
+#define MCF_INTC0_ICR12            MCF_REG08(0xFC04804C)
+#define MCF_INTC0_ICR13            MCF_REG08(0xFC04804D)
+#define MCF_INTC0_ICR14            MCF_REG08(0xFC04804E)
+#define MCF_INTC0_ICR15            MCF_REG08(0xFC04804F)
+#define MCF_INTC0_ICR16            MCF_REG08(0xFC048050)
+#define MCF_INTC0_ICR17            MCF_REG08(0xFC048051)
+#define MCF_INTC0_ICR18            MCF_REG08(0xFC048052)
+#define MCF_INTC0_ICR19            MCF_REG08(0xFC048053)
+#define MCF_INTC0_ICR20            MCF_REG08(0xFC048054)
+#define MCF_INTC0_ICR21            MCF_REG08(0xFC048055)
+#define MCF_INTC0_ICR22            MCF_REG08(0xFC048056)
+#define MCF_INTC0_ICR23            MCF_REG08(0xFC048057)
+#define MCF_INTC0_ICR24            MCF_REG08(0xFC048058)
+#define MCF_INTC0_ICR25            MCF_REG08(0xFC048059)
+#define MCF_INTC0_ICR26            MCF_REG08(0xFC04805A)
+#define MCF_INTC0_ICR27            MCF_REG08(0xFC04805B)
+#define MCF_INTC0_ICR28            MCF_REG08(0xFC04805C)
+#define MCF_INTC0_ICR29            MCF_REG08(0xFC04805D)
+#define MCF_INTC0_ICR30            MCF_REG08(0xFC04805E)
+#define MCF_INTC0_ICR31            MCF_REG08(0xFC04805F)
+#define MCF_INTC0_ICR32            MCF_REG08(0xFC048060)
+#define MCF_INTC0_ICR33            MCF_REG08(0xFC048061)
+#define MCF_INTC0_ICR34            MCF_REG08(0xFC048062)
+#define MCF_INTC0_ICR35            MCF_REG08(0xFC048063)
+#define MCF_INTC0_ICR36            MCF_REG08(0xFC048064)
+#define MCF_INTC0_ICR37            MCF_REG08(0xFC048065)
+#define MCF_INTC0_ICR38            MCF_REG08(0xFC048066)
+#define MCF_INTC0_ICR39            MCF_REG08(0xFC048067)
+#define MCF_INTC0_ICR40            MCF_REG08(0xFC048068)
+#define MCF_INTC0_ICR41            MCF_REG08(0xFC048069)
+#define MCF_INTC0_ICR42            MCF_REG08(0xFC04806A)
+#define MCF_INTC0_ICR43            MCF_REG08(0xFC04806B)
+#define MCF_INTC0_ICR44            MCF_REG08(0xFC04806C)
+#define MCF_INTC0_ICR45            MCF_REG08(0xFC04806D)
+#define MCF_INTC0_ICR46            MCF_REG08(0xFC04806E)
+#define MCF_INTC0_ICR47            MCF_REG08(0xFC04806F)
+#define MCF_INTC0_ICR48            MCF_REG08(0xFC048070)
+#define MCF_INTC0_ICR49            MCF_REG08(0xFC048071)
+#define MCF_INTC0_ICR50            MCF_REG08(0xFC048072)
+#define MCF_INTC0_ICR51            MCF_REG08(0xFC048073)
+#define MCF_INTC0_ICR52            MCF_REG08(0xFC048074)
+#define MCF_INTC0_ICR53            MCF_REG08(0xFC048075)
+#define MCF_INTC0_ICR54            MCF_REG08(0xFC048076)
+#define MCF_INTC0_ICR55            MCF_REG08(0xFC048077)
+#define MCF_INTC0_ICR56            MCF_REG08(0xFC048078)
+#define MCF_INTC0_ICR57            MCF_REG08(0xFC048079)
+#define MCF_INTC0_ICR58            MCF_REG08(0xFC04807A)
+#define MCF_INTC0_ICR59            MCF_REG08(0xFC04807B)
+#define MCF_INTC0_ICR60            MCF_REG08(0xFC04807C)
+#define MCF_INTC0_ICR61            MCF_REG08(0xFC04807D)
+#define MCF_INTC0_ICR62            MCF_REG08(0xFC04807E)
+#define MCF_INTC0_ICR63            MCF_REG08(0xFC04807F)
+#define MCF_INTC0_ICR(x)           MCF_REG08(0xFC048040+((x)*0x001))
+#define MCF_INTC0_SWIACK           MCF_REG08(0xFC0480E0)
+#define MCF_INTC0_L1IACK           MCF_REG08(0xFC0480E4)
+#define MCF_INTC0_L2IACK           MCF_REG08(0xFC0480E8)
+#define MCF_INTC0_L3IACK           MCF_REG08(0xFC0480EC)
+#define MCF_INTC0_L4IACK           MCF_REG08(0xFC0480F0)
+#define MCF_INTC0_L5IACK           MCF_REG08(0xFC0480F4)
+#define MCF_INTC0_L6IACK           MCF_REG08(0xFC0480F8)
+#define MCF_INTC0_L7IACK           MCF_REG08(0xFC0480FC)
+#define MCF_INTC0_LIACK(x)         MCF_REG08(0xFC0480E4+((x)*0x004))
+#define MCF_INTC1_IPRH             MCF_REG32(0xFC04C000)
+#define MCF_INTC1_IPRL             MCF_REG32(0xFC04C004)
+#define MCF_INTC1_IMRH             MCF_REG32(0xFC04C008)
+#define MCF_INTC1_IMRL             MCF_REG32(0xFC04C00C)
+#define MCF_INTC1_INTFRCH          MCF_REG32(0xFC04C010)
+#define MCF_INTC1_INTFRCL          MCF_REG32(0xFC04C014)
+#define MCF_INTC1_ICONFIG          MCF_REG16(0xFC04C01A)
+#define MCF_INTC1_SIMR             MCF_REG08(0xFC04C01C)
+#define MCF_INTC1_CIMR             MCF_REG08(0xFC04C01D)
+#define MCF_INTC1_CLMASK           MCF_REG08(0xFC04C01E)
+#define MCF_INTC1_SLMASK           MCF_REG08(0xFC04C01F)
+#define MCF_INTC1_ICR0             MCF_REG08(0xFC04C040)
+#define MCF_INTC1_ICR1             MCF_REG08(0xFC04C041)
+#define MCF_INTC1_ICR2             MCF_REG08(0xFC04C042)
+#define MCF_INTC1_ICR3             MCF_REG08(0xFC04C043)
+#define MCF_INTC1_ICR4             MCF_REG08(0xFC04C044)
+#define MCF_INTC1_ICR5             MCF_REG08(0xFC04C045)
+#define MCF_INTC1_ICR6             MCF_REG08(0xFC04C046)
+#define MCF_INTC1_ICR7             MCF_REG08(0xFC04C047)
+#define MCF_INTC1_ICR8             MCF_REG08(0xFC04C048)
+#define MCF_INTC1_ICR9             MCF_REG08(0xFC04C049)
+#define MCF_INTC1_ICR10            MCF_REG08(0xFC04C04A)
+#define MCF_INTC1_ICR11            MCF_REG08(0xFC04C04B)
+#define MCF_INTC1_ICR12            MCF_REG08(0xFC04C04C)
+#define MCF_INTC1_ICR13            MCF_REG08(0xFC04C04D)
+#define MCF_INTC1_ICR14            MCF_REG08(0xFC04C04E)
+#define MCF_INTC1_ICR15            MCF_REG08(0xFC04C04F)
+#define MCF_INTC1_ICR16            MCF_REG08(0xFC04C050)
+#define MCF_INTC1_ICR17            MCF_REG08(0xFC04C051)
+#define MCF_INTC1_ICR18            MCF_REG08(0xFC04C052)
+#define MCF_INTC1_ICR19            MCF_REG08(0xFC04C053)
+#define MCF_INTC1_ICR20            MCF_REG08(0xFC04C054)
+#define MCF_INTC1_ICR21            MCF_REG08(0xFC04C055)
+#define MCF_INTC1_ICR22            MCF_REG08(0xFC04C056)
+#define MCF_INTC1_ICR23            MCF_REG08(0xFC04C057)
+#define MCF_INTC1_ICR24            MCF_REG08(0xFC04C058)
+#define MCF_INTC1_ICR25            MCF_REG08(0xFC04C059)
+#define MCF_INTC1_ICR26            MCF_REG08(0xFC04C05A)
+#define MCF_INTC1_ICR27            MCF_REG08(0xFC04C05B)
+#define MCF_INTC1_ICR28            MCF_REG08(0xFC04C05C)
+#define MCF_INTC1_ICR29            MCF_REG08(0xFC04C05D)
+#define MCF_INTC1_ICR30            MCF_REG08(0xFC04C05E)
+#define MCF_INTC1_ICR31            MCF_REG08(0xFC04C05F)
+#define MCF_INTC1_ICR32            MCF_REG08(0xFC04C060)
+#define MCF_INTC1_ICR33            MCF_REG08(0xFC04C061)
+#define MCF_INTC1_ICR34            MCF_REG08(0xFC04C062)
+#define MCF_INTC1_ICR35            MCF_REG08(0xFC04C063)
+#define MCF_INTC1_ICR36            MCF_REG08(0xFC04C064)
+#define MCF_INTC1_ICR37            MCF_REG08(0xFC04C065)
+#define MCF_INTC1_ICR38            MCF_REG08(0xFC04C066)
+#define MCF_INTC1_ICR39            MCF_REG08(0xFC04C067)
+#define MCF_INTC1_ICR40            MCF_REG08(0xFC04C068)
+#define MCF_INTC1_ICR41            MCF_REG08(0xFC04C069)
+#define MCF_INTC1_ICR42            MCF_REG08(0xFC04C06A)
+#define MCF_INTC1_ICR43            MCF_REG08(0xFC04C06B)
+#define MCF_INTC1_ICR44            MCF_REG08(0xFC04C06C)
+#define MCF_INTC1_ICR45            MCF_REG08(0xFC04C06D)
+#define MCF_INTC1_ICR46            MCF_REG08(0xFC04C06E)
+#define MCF_INTC1_ICR47            MCF_REG08(0xFC04C06F)
+#define MCF_INTC1_ICR48            MCF_REG08(0xFC04C070)
+#define MCF_INTC1_ICR49            MCF_REG08(0xFC04C071)
+#define MCF_INTC1_ICR50            MCF_REG08(0xFC04C072)
+#define MCF_INTC1_ICR51            MCF_REG08(0xFC04C073)
+#define MCF_INTC1_ICR52            MCF_REG08(0xFC04C074)
+#define MCF_INTC1_ICR53            MCF_REG08(0xFC04C075)
+#define MCF_INTC1_ICR54            MCF_REG08(0xFC04C076)
+#define MCF_INTC1_ICR55            MCF_REG08(0xFC04C077)
+#define MCF_INTC1_ICR56            MCF_REG08(0xFC04C078)
+#define MCF_INTC1_ICR57            MCF_REG08(0xFC04C079)
+#define MCF_INTC1_ICR58            MCF_REG08(0xFC04C07A)
+#define MCF_INTC1_ICR59            MCF_REG08(0xFC04C07B)
+#define MCF_INTC1_ICR60            MCF_REG08(0xFC04C07C)
+#define MCF_INTC1_ICR61            MCF_REG08(0xFC04C07D)
+#define MCF_INTC1_ICR62            MCF_REG08(0xFC04C07E)
+#define MCF_INTC1_ICR63            MCF_REG08(0xFC04C07F)
+#define MCF_INTC1_ICR(x)           MCF_REG08(0xFC04C040+((x)*0x001))
+#define MCF_INTC1_SWIACK           MCF_REG08(0xFC04C0E0)
+#define MCF_INTC1_L1IACK           MCF_REG08(0xFC04C0E4)
+#define MCF_INTC1_L2IACK           MCF_REG08(0xFC04C0E8)
+#define MCF_INTC1_L3IACK           MCF_REG08(0xFC04C0EC)
+#define MCF_INTC1_L4IACK           MCF_REG08(0xFC04C0F0)
+#define MCF_INTC1_L5IACK           MCF_REG08(0xFC04C0F4)
+#define MCF_INTC1_L6IACK           MCF_REG08(0xFC04C0F8)
+#define MCF_INTC1_L7IACK           MCF_REG08(0xFC04C0FC)
+#define MCF_INTC1_LIACK(x)         MCF_REG08(0xFC04C0E4+((x)*0x004))
+#define MCF_INTC_IPRH(x)           MCF_REG32(0xFC048000+((x)*0x4000))
+#define MCF_INTC_IPRL(x)           MCF_REG32(0xFC048004+((x)*0x4000))
+#define MCF_INTC_IMRH(x)           MCF_REG32(0xFC048008+((x)*0x4000))
+#define MCF_INTC_IMRL(x)           MCF_REG32(0xFC04800C+((x)*0x4000))
+#define MCF_INTC_INTFRCH(x)        MCF_REG32(0xFC048010+((x)*0x4000))
+#define MCF_INTC_INTFRCL(x)        MCF_REG32(0xFC048014+((x)*0x4000))
+#define MCF_INTC_ICONFIG(x)        MCF_REG16(0xFC04801A+((x)*0x4000))
+#define MCF_INTC_SIMR(x)           MCF_REG08(0xFC04801C+((x)*0x4000))
+#define MCF_INTC_CIMR(x)           MCF_REG08(0xFC04801D+((x)*0x4000))
+#define MCF_INTC_CLMASK(x)         MCF_REG08(0xFC04801E+((x)*0x4000))
+#define MCF_INTC_SLMASK(x)         MCF_REG08(0xFC04801F+((x)*0x4000))
+#define MCF_INTC_ICR0(x)           MCF_REG08(0xFC048040+((x)*0x4000))
+#define MCF_INTC_ICR1(x)           MCF_REG08(0xFC048041+((x)*0x4000))
+#define MCF_INTC_ICR2(x)           MCF_REG08(0xFC048042+((x)*0x4000))
+#define MCF_INTC_ICR3(x)           MCF_REG08(0xFC048043+((x)*0x4000))
+#define MCF_INTC_ICR4(x)           MCF_REG08(0xFC048044+((x)*0x4000))
+#define MCF_INTC_ICR5(x)           MCF_REG08(0xFC048045+((x)*0x4000))
+#define MCF_INTC_ICR6(x)           MCF_REG08(0xFC048046+((x)*0x4000))
+#define MCF_INTC_ICR7(x)           MCF_REG08(0xFC048047+((x)*0x4000))
+#define MCF_INTC_ICR8(x)           MCF_REG08(0xFC048048+((x)*0x4000))
+#define MCF_INTC_ICR9(x)           MCF_REG08(0xFC048049+((x)*0x4000))
+#define MCF_INTC_ICR10(x)          MCF_REG08(0xFC04804A+((x)*0x4000))
+#define MCF_INTC_ICR11(x)          MCF_REG08(0xFC04804B+((x)*0x4000))
+#define MCF_INTC_ICR12(x)          MCF_REG08(0xFC04804C+((x)*0x4000))
+#define MCF_INTC_ICR13(x)          MCF_REG08(0xFC04804D+((x)*0x4000))
+#define MCF_INTC_ICR14(x)          MCF_REG08(0xFC04804E+((x)*0x4000))
+#define MCF_INTC_ICR15(x)          MCF_REG08(0xFC04804F+((x)*0x4000))
+#define MCF_INTC_ICR16(x)          MCF_REG08(0xFC048050+((x)*0x4000))
+#define MCF_INTC_ICR17(x)          MCF_REG08(0xFC048051+((x)*0x4000))
+#define MCF_INTC_ICR18(x)          MCF_REG08(0xFC048052+((x)*0x4000))
+#define MCF_INTC_ICR19(x)          MCF_REG08(0xFC048053+((x)*0x4000))
+#define MCF_INTC_ICR20(x)          MCF_REG08(0xFC048054+((x)*0x4000))
+#define MCF_INTC_ICR21(x)          MCF_REG08(0xFC048055+((x)*0x4000))
+#define MCF_INTC_ICR22(x)          MCF_REG08(0xFC048056+((x)*0x4000))
+#define MCF_INTC_ICR23(x)          MCF_REG08(0xFC048057+((x)*0x4000))
+#define MCF_INTC_ICR24(x)          MCF_REG08(0xFC048058+((x)*0x4000))
+#define MCF_INTC_ICR25(x)          MCF_REG08(0xFC048059+((x)*0x4000))
+#define MCF_INTC_ICR26(x)          MCF_REG08(0xFC04805A+((x)*0x4000))
+#define MCF_INTC_ICR27(x)          MCF_REG08(0xFC04805B+((x)*0x4000))
+#define MCF_INTC_ICR28(x)          MCF_REG08(0xFC04805C+((x)*0x4000))
+#define MCF_INTC_ICR29(x)          MCF_REG08(0xFC04805D+((x)*0x4000))
+#define MCF_INTC_ICR30(x)          MCF_REG08(0xFC04805E+((x)*0x4000))
+#define MCF_INTC_ICR31(x)          MCF_REG08(0xFC04805F+((x)*0x4000))
+#define MCF_INTC_ICR32(x)          MCF_REG08(0xFC048060+((x)*0x4000))
+#define MCF_INTC_ICR33(x)          MCF_REG08(0xFC048061+((x)*0x4000))
+#define MCF_INTC_ICR34(x)          MCF_REG08(0xFC048062+((x)*0x4000))
+#define MCF_INTC_ICR35(x)          MCF_REG08(0xFC048063+((x)*0x4000))
+#define MCF_INTC_ICR36(x)          MCF_REG08(0xFC048064+((x)*0x4000))
+#define MCF_INTC_ICR37(x)          MCF_REG08(0xFC048065+((x)*0x4000))
+#define MCF_INTC_ICR38(x)          MCF_REG08(0xFC048066+((x)*0x4000))
+#define MCF_INTC_ICR39(x)          MCF_REG08(0xFC048067+((x)*0x4000))
+#define MCF_INTC_ICR40(x)          MCF_REG08(0xFC048068+((x)*0x4000))
+#define MCF_INTC_ICR41(x)          MCF_REG08(0xFC048069+((x)*0x4000))
+#define MCF_INTC_ICR42(x)          MCF_REG08(0xFC04806A+((x)*0x4000))
+#define MCF_INTC_ICR43(x)          MCF_REG08(0xFC04806B+((x)*0x4000))
+#define MCF_INTC_ICR44(x)          MCF_REG08(0xFC04806C+((x)*0x4000))
+#define MCF_INTC_ICR45(x)          MCF_REG08(0xFC04806D+((x)*0x4000))
+#define MCF_INTC_ICR46(x)          MCF_REG08(0xFC04806E+((x)*0x4000))
+#define MCF_INTC_ICR47(x)          MCF_REG08(0xFC04806F+((x)*0x4000))
+#define MCF_INTC_ICR48(x)          MCF_REG08(0xFC048070+((x)*0x4000))
+#define MCF_INTC_ICR49(x)          MCF_REG08(0xFC048071+((x)*0x4000))
+#define MCF_INTC_ICR50(x)          MCF_REG08(0xFC048072+((x)*0x4000))
+#define MCF_INTC_ICR51(x)          MCF_REG08(0xFC048073+((x)*0x4000))
+#define MCF_INTC_ICR52(x)          MCF_REG08(0xFC048074+((x)*0x4000))
+#define MCF_INTC_ICR53(x)          MCF_REG08(0xFC048075+((x)*0x4000))
+#define MCF_INTC_ICR54(x)          MCF_REG08(0xFC048076+((x)*0x4000))
+#define MCF_INTC_ICR55(x)          MCF_REG08(0xFC048077+((x)*0x4000))
+#define MCF_INTC_ICR56(x)          MCF_REG08(0xFC048078+((x)*0x4000))
+#define MCF_INTC_ICR57(x)          MCF_REG08(0xFC048079+((x)*0x4000))
+#define MCF_INTC_ICR58(x)          MCF_REG08(0xFC04807A+((x)*0x4000))
+#define MCF_INTC_ICR59(x)          MCF_REG08(0xFC04807B+((x)*0x4000))
+#define MCF_INTC_ICR60(x)          MCF_REG08(0xFC04807C+((x)*0x4000))
+#define MCF_INTC_ICR61(x)          MCF_REG08(0xFC04807D+((x)*0x4000))
+#define MCF_INTC_ICR62(x)          MCF_REG08(0xFC04807E+((x)*0x4000))
+#define MCF_INTC_ICR63(x)          MCF_REG08(0xFC04807F+((x)*0x4000))
+#define MCF_INTC_SWIACK(x)         MCF_REG08(0xFC0480E0+((x)*0x4000))
+#define MCF_INTC_L1IACK(x)         MCF_REG08(0xFC0480E4+((x)*0x4000))
+#define MCF_INTC_L2IACK(x)         MCF_REG08(0xFC0480E8+((x)*0x4000))
+#define MCF_INTC_L3IACK(x)         MCF_REG08(0xFC0480EC+((x)*0x4000))
+#define MCF_INTC_L4IACK(x)         MCF_REG08(0xFC0480F0+((x)*0x4000))
+#define MCF_INTC_L5IACK(x)         MCF_REG08(0xFC0480F4+((x)*0x4000))
+#define MCF_INTC_L6IACK(x)         MCF_REG08(0xFC0480F8+((x)*0x4000))
+#define MCF_INTC_L7IACK(x)         MCF_REG08(0xFC0480FC+((x)*0x4000))
+
+/* Bit definitions and macros for MCF_INTC_IPRH */
+#define MCF_INTC_IPRH_INT32        (0x00000001)
+#define MCF_INTC_IPRH_INT33        (0x00000002)
+#define MCF_INTC_IPRH_INT34        (0x00000004)
+#define MCF_INTC_IPRH_INT35        (0x00000008)
+#define MCF_INTC_IPRH_INT36        (0x00000010)
+#define MCF_INTC_IPRH_INT37        (0x00000020)
+#define MCF_INTC_IPRH_INT38        (0x00000040)
+#define MCF_INTC_IPRH_INT39        (0x00000080)
+#define MCF_INTC_IPRH_INT40        (0x00000100)
+#define MCF_INTC_IPRH_INT41        (0x00000200)
+#define MCF_INTC_IPRH_INT42        (0x00000400)
+#define MCF_INTC_IPRH_INT43        (0x00000800)
+#define MCF_INTC_IPRH_INT44        (0x00001000)
+#define MCF_INTC_IPRH_INT45        (0x00002000)
+#define MCF_INTC_IPRH_INT46        (0x00004000)
+#define MCF_INTC_IPRH_INT47        (0x00008000)
+#define MCF_INTC_IPRH_INT48        (0x00010000)
+#define MCF_INTC_IPRH_INT49        (0x00020000)
+#define MCF_INTC_IPRH_INT50        (0x00040000)
+#define MCF_INTC_IPRH_INT51        (0x00080000)
+#define MCF_INTC_IPRH_INT52        (0x00100000)
+#define MCF_INTC_IPRH_INT53        (0x00200000)
+#define MCF_INTC_IPRH_INT54        (0x00400000)
+#define MCF_INTC_IPRH_INT55        (0x00800000)
+#define MCF_INTC_IPRH_INT56        (0x01000000)
+#define MCF_INTC_IPRH_INT57        (0x02000000)
+#define MCF_INTC_IPRH_INT58        (0x04000000)
+#define MCF_INTC_IPRH_INT59        (0x08000000)
+#define MCF_INTC_IPRH_INT60        (0x10000000)
+#define MCF_INTC_IPRH_INT61        (0x20000000)
+#define MCF_INTC_IPRH_INT62        (0x40000000)
+#define MCF_INTC_IPRH_INT63        (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_IPRL */
+#define MCF_INTC_IPRL_INT0         (0x00000001)
+#define MCF_INTC_IPRL_INT1         (0x00000002)
+#define MCF_INTC_IPRL_INT2         (0x00000004)
+#define MCF_INTC_IPRL_INT3         (0x00000008)
+#define MCF_INTC_IPRL_INT4         (0x00000010)
+#define MCF_INTC_IPRL_INT5         (0x00000020)
+#define MCF_INTC_IPRL_INT6         (0x00000040)
+#define MCF_INTC_IPRL_INT7         (0x00000080)
+#define MCF_INTC_IPRL_INT8         (0x00000100)
+#define MCF_INTC_IPRL_INT9         (0x00000200)
+#define MCF_INTC_IPRL_INT10        (0x00000400)
+#define MCF_INTC_IPRL_INT11        (0x00000800)
+#define MCF_INTC_IPRL_INT12        (0x00001000)
+#define MCF_INTC_IPRL_INT13        (0x00002000)
+#define MCF_INTC_IPRL_INT14        (0x00004000)
+#define MCF_INTC_IPRL_INT15        (0x00008000)
+#define MCF_INTC_IPRL_INT16        (0x00010000)
+#define MCF_INTC_IPRL_INT17        (0x00020000)
+#define MCF_INTC_IPRL_INT18        (0x00040000)
+#define MCF_INTC_IPRL_INT19        (0x00080000)
+#define MCF_INTC_IPRL_INT20        (0x00100000)
+#define MCF_INTC_IPRL_INT21        (0x00200000)
+#define MCF_INTC_IPRL_INT22        (0x00400000)
+#define MCF_INTC_IPRL_INT23        (0x00800000)
+#define MCF_INTC_IPRL_INT24        (0x01000000)
+#define MCF_INTC_IPRL_INT25        (0x02000000)
+#define MCF_INTC_IPRL_INT26        (0x04000000)
+#define MCF_INTC_IPRL_INT27        (0x08000000)
+#define MCF_INTC_IPRL_INT28        (0x10000000)
+#define MCF_INTC_IPRL_INT29        (0x20000000)
+#define MCF_INTC_IPRL_INT30        (0x40000000)
+#define MCF_INTC_IPRL_INT31        (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_IMRH */
+#define MCF_INTC_IMRH_INT_MASK32   (0x00000001)
+#define MCF_INTC_IMRH_INT_MASK33   (0x00000002)
+#define MCF_INTC_IMRH_INT_MASK34   (0x00000004)
+#define MCF_INTC_IMRH_INT_MASK35   (0x00000008)
+#define MCF_INTC_IMRH_INT_MASK36   (0x00000010)
+#define MCF_INTC_IMRH_INT_MASK37   (0x00000020)
+#define MCF_INTC_IMRH_INT_MASK38   (0x00000040)
+#define MCF_INTC_IMRH_INT_MASK39   (0x00000080)
+#define MCF_INTC_IMRH_INT_MASK40   (0x00000100)
+#define MCF_INTC_IMRH_INT_MASK41   (0x00000200)
+#define MCF_INTC_IMRH_INT_MASK42   (0x00000400)
+#define MCF_INTC_IMRH_INT_MASK43   (0x00000800)
+#define MCF_INTC_IMRH_INT_MASK44   (0x00001000)
+#define MCF_INTC_IMRH_INT_MASK45   (0x00002000)
+#define MCF_INTC_IMRH_INT_MASK46   (0x00004000)
+#define MCF_INTC_IMRH_INT_MASK47   (0x00008000)
+#define MCF_INTC_IMRH_INT_MASK48   (0x00010000)
+#define MCF_INTC_IMRH_INT_MASK49   (0x00020000)
+#define MCF_INTC_IMRH_INT_MASK50   (0x00040000)
+#define MCF_INTC_IMRH_INT_MASK51   (0x00080000)
+#define MCF_INTC_IMRH_INT_MASK52   (0x00100000)
+#define MCF_INTC_IMRH_INT_MASK53   (0x00200000)
+#define MCF_INTC_IMRH_INT_MASK54   (0x00400000)
+#define MCF_INTC_IMRH_INT_MASK55   (0x00800000)
+#define MCF_INTC_IMRH_INT_MASK56   (0x01000000)
+#define MCF_INTC_IMRH_INT_MASK57   (0x02000000)
+#define MCF_INTC_IMRH_INT_MASK58   (0x04000000)
+#define MCF_INTC_IMRH_INT_MASK59   (0x08000000)
+#define MCF_INTC_IMRH_INT_MASK60   (0x10000000)
+#define MCF_INTC_IMRH_INT_MASK61   (0x20000000)
+#define MCF_INTC_IMRH_INT_MASK62   (0x40000000)
+#define MCF_INTC_IMRH_INT_MASK63   (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_IMRL */
+#define MCF_INTC_IMRL_INT_MASK0    (0x00000001)
+#define MCF_INTC_IMRL_INT_MASK1    (0x00000002)
+#define MCF_INTC_IMRL_INT_MASK2    (0x00000004)
+#define MCF_INTC_IMRL_INT_MASK3    (0x00000008)
+#define MCF_INTC_IMRL_INT_MASK4    (0x00000010)
+#define MCF_INTC_IMRL_INT_MASK5    (0x00000020)
+#define MCF_INTC_IMRL_INT_MASK6    (0x00000040)
+#define MCF_INTC_IMRL_INT_MASK7    (0x00000080)
+#define MCF_INTC_IMRL_INT_MASK8    (0x00000100)
+#define MCF_INTC_IMRL_INT_MASK9    (0x00000200)
+#define MCF_INTC_IMRL_INT_MASK10   (0x00000400)
+#define MCF_INTC_IMRL_INT_MASK11   (0x00000800)
+#define MCF_INTC_IMRL_INT_MASK12   (0x00001000)
+#define MCF_INTC_IMRL_INT_MASK13   (0x00002000)
+#define MCF_INTC_IMRL_INT_MASK14   (0x00004000)
+#define MCF_INTC_IMRL_INT_MASK15   (0x00008000)
+#define MCF_INTC_IMRL_INT_MASK16   (0x00010000)
+#define MCF_INTC_IMRL_INT_MASK17   (0x00020000)
+#define MCF_INTC_IMRL_INT_MASK18   (0x00040000)
+#define MCF_INTC_IMRL_INT_MASK19   (0x00080000)
+#define MCF_INTC_IMRL_INT_MASK20   (0x00100000)
+#define MCF_INTC_IMRL_INT_MASK21   (0x00200000)
+#define MCF_INTC_IMRL_INT_MASK22   (0x00400000)
+#define MCF_INTC_IMRL_INT_MASK23   (0x00800000)
+#define MCF_INTC_IMRL_INT_MASK24   (0x01000000)
+#define MCF_INTC_IMRL_INT_MASK25   (0x02000000)
+#define MCF_INTC_IMRL_INT_MASK26   (0x04000000)
+#define MCF_INTC_IMRL_INT_MASK27   (0x08000000)
+#define MCF_INTC_IMRL_INT_MASK28   (0x10000000)
+#define MCF_INTC_IMRL_INT_MASK29   (0x20000000)
+#define MCF_INTC_IMRL_INT_MASK30   (0x40000000)
+#define MCF_INTC_IMRL_INT_MASK31   (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_INTFRCH */
+#define MCF_INTC_INTFRCH_INTFRC32  (0x00000001)
+#define MCF_INTC_INTFRCH_INTFRC33  (0x00000002)
+#define MCF_INTC_INTFRCH_INTFRC34  (0x00000004)
+#define MCF_INTC_INTFRCH_INTFRC35  (0x00000008)
+#define MCF_INTC_INTFRCH_INTFRC36  (0x00000010)
+#define MCF_INTC_INTFRCH_INTFRC37  (0x00000020)
+#define MCF_INTC_INTFRCH_INTFRC38  (0x00000040)
+#define MCF_INTC_INTFRCH_INTFRC39  (0x00000080)
+#define MCF_INTC_INTFRCH_INTFRC40  (0x00000100)
+#define MCF_INTC_INTFRCH_INTFRC41  (0x00000200)
+#define MCF_INTC_INTFRCH_INTFRC42  (0x00000400)
+#define MCF_INTC_INTFRCH_INTFRC43  (0x00000800)
+#define MCF_INTC_INTFRCH_INTFRC44  (0x00001000)
+#define MCF_INTC_INTFRCH_INTFRC45  (0x00002000)
+#define MCF_INTC_INTFRCH_INTFRC46  (0x00004000)
+#define MCF_INTC_INTFRCH_INTFRC47  (0x00008000)
+#define MCF_INTC_INTFRCH_INTFRC48  (0x00010000)
+#define MCF_INTC_INTFRCH_INTFRC49  (0x00020000)
+#define MCF_INTC_INTFRCH_INTFRC50  (0x00040000)
+#define MCF_INTC_INTFRCH_INTFRC51  (0x00080000)
+#define MCF_INTC_INTFRCH_INTFRC52  (0x00100000)
+#define MCF_INTC_INTFRCH_INTFRC53  (0x00200000)
+#define MCF_INTC_INTFRCH_INTFRC54  (0x00400000)
+#define MCF_INTC_INTFRCH_INTFRC55  (0x00800000)
+#define MCF_INTC_INTFRCH_INTFRC56  (0x01000000)
+#define MCF_INTC_INTFRCH_INTFRC57  (0x02000000)
+#define MCF_INTC_INTFRCH_INTFRC58  (0x04000000)
+#define MCF_INTC_INTFRCH_INTFRC59  (0x08000000)
+#define MCF_INTC_INTFRCH_INTFRC60  (0x10000000)
+#define MCF_INTC_INTFRCH_INTFRC61  (0x20000000)
+#define MCF_INTC_INTFRCH_INTFRC62  (0x40000000)
+#define MCF_INTC_INTFRCH_INTFRC63  (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_INTFRCL */
+#define MCF_INTC_INTFRCL_INTFRC0   (0x00000001)
+#define MCF_INTC_INTFRCL_INTFRC1   (0x00000002)
+#define MCF_INTC_INTFRCL_INTFRC2   (0x00000004)
+#define MCF_INTC_INTFRCL_INTFRC3   (0x00000008)
+#define MCF_INTC_INTFRCL_INTFRC4   (0x00000010)
+#define MCF_INTC_INTFRCL_INTFRC5   (0x00000020)
+#define MCF_INTC_INTFRCL_INTFRC6   (0x00000040)
+#define MCF_INTC_INTFRCL_INTFRC7   (0x00000080)
+#define MCF_INTC_INTFRCL_INTFRC8   (0x00000100)
+#define MCF_INTC_INTFRCL_INTFRC9   (0x00000200)
+#define MCF_INTC_INTFRCL_INTFRC10  (0x00000400)
+#define MCF_INTC_INTFRCL_INTFRC11  (0x00000800)
+#define MCF_INTC_INTFRCL_INTFRC12  (0x00001000)
+#define MCF_INTC_INTFRCL_INTFRC13  (0x00002000)
+#define MCF_INTC_INTFRCL_INTFRC14  (0x00004000)
+#define MCF_INTC_INTFRCL_INTFRC15  (0x00008000)
+#define MCF_INTC_INTFRCL_INTFRC16  (0x00010000)
+#define MCF_INTC_INTFRCL_INTFRC17  (0x00020000)
+#define MCF_INTC_INTFRCL_INTFRC18  (0x00040000)
+#define MCF_INTC_INTFRCL_INTFRC19  (0x00080000)
+#define MCF_INTC_INTFRCL_INTFRC20  (0x00100000)
+#define MCF_INTC_INTFRCL_INTFRC21  (0x00200000)
+#define MCF_INTC_INTFRCL_INTFRC22  (0x00400000)
+#define MCF_INTC_INTFRCL_INTFRC23  (0x00800000)
+#define MCF_INTC_INTFRCL_INTFRC24  (0x01000000)
+#define MCF_INTC_INTFRCL_INTFRC25  (0x02000000)
+#define MCF_INTC_INTFRCL_INTFRC26  (0x04000000)
+#define MCF_INTC_INTFRCL_INTFRC27  (0x08000000)
+#define MCF_INTC_INTFRCL_INTFRC28  (0x10000000)
+#define MCF_INTC_INTFRCL_INTFRC29  (0x20000000)
+#define MCF_INTC_INTFRCL_INTFRC30  (0x40000000)
+#define MCF_INTC_INTFRCL_INTFRC31  (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_ICONFIG */
+#define MCF_INTC_ICONFIG_EMASK     (0x0020)
+#define MCF_INTC_ICONFIG_ELVLPRI1  (0x0200)
+#define MCF_INTC_ICONFIG_ELVLPRI2  (0x0400)
+#define MCF_INTC_ICONFIG_ELVLPRI3  (0x0800)
+#define MCF_INTC_ICONFIG_ELVLPRI4  (0x1000)
+#define MCF_INTC_ICONFIG_ELVLPRI5  (0x2000)
+#define MCF_INTC_ICONFIG_ELVLPRI6  (0x4000)
+#define MCF_INTC_ICONFIG_ELVLPRI7  (0x8000)
+
+/* Bit definitions and macros for MCF_INTC_SIMR */
+#define MCF_INTC_SIMR_SIMR(x)      (((x)&0x7F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_CIMR */
+#define MCF_INTC_CIMR_CIMR(x)      (((x)&0x7F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_CLMASK */
+#define MCF_INTC_CLMASK_CLMASK(x)  (((x)&0x0F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_SLMASK */
+#define MCF_INTC_SLMASK_SLMASK(x)  (((x)&0x0F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_ICR */
+#define MCF_INTC_ICR_IL(x)         (((x)&0x07)<<0)
+
+/* Bit definitions and macros for MCF_INTC_SWIACK */
+#define MCF_INTC_SWIACK_VECTOR(x)  (((x)&0xFF)<<0)
+
+/* Bit definitions and macros for MCF_INTC_LIACK */
+#define MCF_INTC_LIACK_VECTOR(x)   (((x)&0xFF)<<0)
+
+/********************************************************************/
+/*********************************************************************
+*
+* LCD Controller (LCDC)
+*
+*********************************************************************/
+
+/* Register read/write macros */
+#define MCF_LCDC_LSSAR                  MCF_REG32(0xFC0AC000)
+#define MCF_LCDC_LSR                    MCF_REG32(0xFC0AC004)
+#define MCF_LCDC_LVPWR                  MCF_REG32(0xFC0AC008)
+#define MCF_LCDC_LCPR                   MCF_REG32(0xFC0AC00C)
+#define MCF_LCDC_LCWHBR                 MCF_REG32(0xFC0AC010)
+#define MCF_LCDC_LCCMR                  MCF_REG32(0xFC0AC014)
+#define MCF_LCDC_LPCR                   MCF_REG32(0xFC0AC018)
+#define MCF_LCDC_LHCR                   MCF_REG32(0xFC0AC01C)
+#define MCF_LCDC_LVCR                   MCF_REG32(0xFC0AC020)
+#define MCF_LCDC_LPOR                   MCF_REG32(0xFC0AC024)
+#define MCF_LCDC_LSCR                   MCF_REG32(0xFC0AC028)
+#define MCF_LCDC_LPCCR                  MCF_REG32(0xFC0AC02C)
+#define MCF_LCDC_LDCR                   MCF_REG32(0xFC0AC030)
+#define MCF_LCDC_LRMCR                  MCF_REG32(0xFC0AC034)
+#define MCF_LCDC_LICR                   MCF_REG32(0xFC0AC038)
+#define MCF_LCDC_LIER                   MCF_REG32(0xFC0AC03C)
+#define MCF_LCDC_LISR                   MCF_REG32(0xFC0AC040)
+#define MCF_LCDC_LGWSAR                 MCF_REG32(0xFC0AC050)
+#define MCF_LCDC_LGWSR                  MCF_REG32(0xFC0AC054)
+#define MCF_LCDC_LGWVPWR                MCF_REG32(0xFC0AC058)
+#define MCF_LCDC_LGWPOR                 MCF_REG32(0xFC0AC05C)
+#define MCF_LCDC_LGWPR                  MCF_REG32(0xFC0AC060)
+#define MCF_LCDC_LGWCR                  MCF_REG32(0xFC0AC064)
+#define MCF_LCDC_LGWDCR                 MCF_REG32(0xFC0AC068)
+#define MCF_LCDC_BPLUT_BASE             MCF_REG32(0xFC0AC800)
+#define MCF_LCDC_GWLUT_BASE             MCF_REG32(0xFC0ACC00)
+
+/* Bit definitions and macros for MCF_LCDC_LSSAR */
+#define MCF_LCDC_LSSAR_SSA(x)           (((x)&0x3FFFFFFF)<<2)
+
+/* Bit definitions and macros for MCF_LCDC_LSR */
+#define MCF_LCDC_LSR_YMAX(x)            (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LSR_XMAX(x)            (((x)&0x0000003F)<<20)
+
+/* Bit definitions and macros for MCF_LCDC_LVPWR */
+#define MCF_LCDC_LVPWR_VPW(x)           (((x)&0x000003FF)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LCPR */
+#define MCF_LCDC_LCPR_CYP(x)            (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LCPR_CXP(x)            (((x)&0x000003FF)<<16)
+#define MCF_LCDC_LCPR_OP                (0x10000000)
+#define MCF_LCDC_LCPR_CC(x)             (((x)&0x00000003)<<30)
+#define MCF_LCDC_LCPR_CC_TRANSPARENT    (0x00000000)
+#define MCF_LCDC_LCPR_CC_OR             (0x40000000)
+#define MCF_LCDC_LCPR_CC_XOR            (0x80000000)
+#define MCF_LCDC_LCPR_CC_AND            (0xC0000000)
+#define MCF_LCDC_LCPR_OP_ON             (0x10000000)
+#define MCF_LCDC_LCPR_OP_OFF            (0x00000000)
+
+/* Bit definitions and macros for MCF_LCDC_LCWHBR */
+#define MCF_LCDC_LCWHBR_BD(x)           (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LCWHBR_CH(x)           (((x)&0x0000001F)<<16)
+#define MCF_LCDC_LCWHBR_CW(x)           (((x)&0x0000001F)<<24)
+#define MCF_LCDC_LCWHBR_BK_EN           (0x80000000)
+#define MCF_LCDC_LCWHBR_BK_EN_ON        (0x80000000)
+#define MCF_LCDC_LCWHBR_BK_EN_OFF       (0x00000000)
+
+/* Bit definitions and macros for MCF_LCDC_LCCMR */
+#define MCF_LCDC_LCCMR_CUR_COL_B(x)     (((x)&0x0000003F)<<0)
+#define MCF_LCDC_LCCMR_CUR_COL_G(x)     (((x)&0x0000003F)<<6)
+#define MCF_LCDC_LCCMR_CUR_COL_R(x)     (((x)&0x0000003F)<<12)
+
+/* Bit definitions and macros for MCF_LCDC_LPCR */
+#define MCF_LCDC_LPCR_PCD(x)            (((x)&0x0000003F)<<0)
+#define MCF_LCDC_LPCR_SHARP             (0x00000040)
+#define MCF_LCDC_LPCR_SCLKSEL           (0x00000080)
+#define MCF_LCDC_LPCR_ACD(x)            (((x)&0x0000007F)<<8)
+#define MCF_LCDC_LPCR_ACDSEL            (0x00008000)
+#define MCF_LCDC_LPCR_REV_VS            (0x00010000)
+#define MCF_LCDC_LPCR_SWAP_SEL          (0x00020000)
+#define MCF_LCDC_LPCR_ENDSEL            (0x00040000)
+#define MCF_LCDC_LPCR_SCLKIDLE          (0x00080000)
+#define MCF_LCDC_LPCR_OEPOL             (0x00100000)
+#define MCF_LCDC_LPCR_CLKPOL            (0x00200000)
+#define MCF_LCDC_LPCR_LPPOL             (0x00400000)
+#define MCF_LCDC_LPCR_FLM               (0x00800000)
+#define MCF_LCDC_LPCR_PIXPOL            (0x01000000)
+#define MCF_LCDC_LPCR_BPIX(x)           (((x)&0x00000007)<<25)
+#define MCF_LCDC_LPCR_PBSIZ(x)          (((x)&0x00000003)<<28)
+#define MCF_LCDC_LPCR_COLOR             (0x40000000)
+#define MCF_LCDC_LPCR_TFT               (0x80000000)
+#define MCF_LCDC_LPCR_MODE_MONOCGROME   (0x00000000)
+#define MCF_LCDC_LPCR_MODE_CSTN         (0x40000000)
+#define MCF_LCDC_LPCR_MODE_TFT          (0xC0000000)
+#define MCF_LCDC_LPCR_PBSIZ_1           (0x00000000)
+#define MCF_LCDC_LPCR_PBSIZ_2           (0x10000000)
+#define MCF_LCDC_LPCR_PBSIZ_4           (0x20000000)
+#define MCF_LCDC_LPCR_PBSIZ_8           (0x30000000)
+#define MCF_LCDC_LPCR_BPIX_1bpp         (0x00000000)
+#define MCF_LCDC_LPCR_BPIX_2bpp         (0x02000000)
+#define MCF_LCDC_LPCR_BPIX_4bpp         (0x04000000)
+#define MCF_LCDC_LPCR_BPIX_8bpp         (0x06000000)
+#define MCF_LCDC_LPCR_BPIX_12bpp        (0x08000000)
+#define MCF_LCDC_LPCR_BPIX_16bpp        (0x0A000000)
+#define MCF_LCDC_LPCR_BPIX_18bpp        (0x0C000000)
+
+#define MCF_LCDC_LPCR_PANEL_TYPE(x)     (((x)&0x00000003)<<30) 
+
+/* Bit definitions and macros for MCF_LCDC_LHCR */
+#define MCF_LCDC_LHCR_H_WAIT_2(x)       (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LHCR_H_WAIT_1(x)       (((x)&0x000000FF)<<8)
+#define MCF_LCDC_LHCR_H_WIDTH(x)        (((x)&0x0000003F)<<26)
+
+/* Bit definitions and macros for MCF_LCDC_LVCR */
+#define MCF_LCDC_LVCR_V_WAIT_2(x)       (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LVCR_V_WAIT_1(x)       (((x)&0x000000FF)<<8)
+#define MCF_LCDC_LVCR_V_WIDTH(x)      (((x)&0x0000003F)<<26)
+
+/* Bit definitions and macros for MCF_LCDC_LPOR */
+#define MCF_LCDC_LPOR_POS(x)            (((x)&0x0000001F)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LPCCR */
+#define MCF_LCDC_LPCCR_PW(x)            (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LPCCR_CC_EN            (0x00000100)
+#define MCF_LCDC_LPCCR_SCR(x)           (((x)&0x00000003)<<9)
+#define MCF_LCDC_LPCCR_LDMSK            (0x00008000)
+#define MCF_LCDC_LPCCR_CLS_HI_WIDTH(x)  (((x)&0x000001FF)<<16)
+#define MCF_LCDC_LPCCR_SCR_LINEPULSE    (0x00000000)
+#define MCF_LCDC_LPCCR_SCR_PIXELCLK     (0x00002000)
+#define MCF_LCDC_LPCCR_SCR_LCDCLOCK     (0x00004000)
+
+/* Bit definitions and macros for MCF_LCDC_LDCR */
+#define MCF_LCDC_LDCR_TM(x)             (((x)&0x0000001F)<<0)
+#define MCF_LCDC_LDCR_HM(x)             (((x)&0x0000001F)<<16)
+#define MCF_LCDC_LDCR_BURST             (0x80000000)
+
+/* Bit definitions and macros for MCF_LCDC_LRMCR */
+#define MCF_LCDC_LRMCR_SEL_REF          (0x00000001)
+
+/* Bit definitions and macros for MCF_LCDC_LICR */
+#define MCF_LCDC_LICR_INTCON            (0x00000001)
+#define MCF_LCDC_LICR_INTSYN            (0x00000004)
+#define MCF_LCDC_LICR_GW_INT_CON        (0x00000010)
+
+/* Bit definitions and macros for MCF_LCDC_LIER */
+#define MCF_LCDC_LIER_BOF_EN            (0x00000001)
+#define MCF_LCDC_LIER_EOF_EN            (0x00000002)
+#define MCF_LCDC_LIER_ERR_RES_EN        (0x00000004)
+#define MCF_LCDC_LIER_UDR_ERR_EN        (0x00000008)
+#define MCF_LCDC_LIER_GW_BOF_EN         (0x00000010)
+#define MCF_LCDC_LIER_GW_EOF_EN         (0x00000020)
+#define MCF_LCDC_LIER_GW_ERR_RES_EN     (0x00000040)
+#define MCF_LCDC_LIER_GW_UDR_ERR_EN     (0x00000080)
+
+/* Bit definitions and macros for MCF_LCDC_LISR */
+#define MCF_LCDC_LISR_BOF               (0x00000001)
+#define MCF_LCDC_LISR_EOF               (0x00000002)
+#define MCF_LCDC_LISR_ERR_RES           (0x00000004)
+#define MCF_LCDC_LISR_UDR_ERR           (0x00000008)
+#define MCF_LCDC_LISR_GW_BOF            (0x00000010)
+#define MCF_LCDC_LISR_GW_EOF            (0x00000020)
+#define MCF_LCDC_LISR_GW_ERR_RES        (0x00000040)
+#define MCF_LCDC_LISR_GW_UDR_ERR        (0x00000080)
+
+/* Bit definitions and macros for MCF_LCDC_LGWSAR */
+#define MCF_LCDC_LGWSAR_GWSA(x)         (((x)&0x3FFFFFFF)<<2)
+
+/* Bit definitions and macros for MCF_LCDC_LGWSR */
+#define MCF_LCDC_LGWSR_GWH(x)           (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LGWSR_GWW(x)           (((x)&0x0000003F)<<20)
+
+/* Bit definitions and macros for MCF_LCDC_LGWVPWR */
+#define MCF_LCDC_LGWVPWR_GWVPW(x)       (((x)&0x000003FF)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LGWPOR */
+#define MCF_LCDC_LGWPOR_GWPO(x)         (((x)&0x0000001F)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LGWPR */
+#define MCF_LCDC_LGWPR_GWYP(x)          (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LGWPR_GWXP(x)          (((x)&0x000003FF)<<16)
+
+/* Bit definitions and macros for MCF_LCDC_LGWCR */
+#define MCF_LCDC_LGWCR_GWCKB(x)         (((x)&0x0000003F)<<0)
+#define MCF_LCDC_LGWCR_GWCKG(x)         (((x)&0x0000003F)<<6)
+#define MCF_LCDC_LGWCR_GWCKR(x)         (((x)&0x0000003F)<<12)
+#define MCF_LCDC_LGWCR_GW_RVS           (0x00200000)
+#define MCF_LCDC_LGWCR_GWE              (0x00400000)
+#define MCF_LCDC_LGWCR_GWCKE            (0x00800000)
+#define MCF_LCDC_LGWCR_GWAV(x)          (((x)&0x000000FF)<<24)
+
+/* Bit definitions and macros for MCF_LCDC_LGWDCR */
+#define MCF_LCDC_LGWDCR_GWTM(x)         (((x)&0x0000001F)<<0)
+#define MCF_LCDC_LGWDCR_GWHM(x)         (((x)&0x0000001F)<<16)
+#define MCF_LCDC_LGWDCR_GWBT            (0x80000000)
+
+/* Bit definitions and macros for MCF_LCDC_LSCR */
+#define MCF_LCDC_LSCR_PS_RISE_DELAY(x)    (((x)&0x0000003F)<<26)
+#define MCF_LCDC_LSCR_CLS_RISE_DELAY(x)   (((x)&0x000000FF)<<16)
+#define MCF_LCDC_LSCR_REV_TOGGLE_DELAY(x) (((x)&0x0000000F)<<8)
+#define MCF_LCDC_LSCR_GRAY_2(x)                  (((x)&0x0000000F)<<4)
+#define MCF_LCDC_LSCR_GRAY_1(x)                  (((x)&0x0000000F)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_BPLUT_BASE */
+#define MCF_LCDC_BPLUT_BASE_BASE(x)     (((x)&0xFFFFFFFF)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_GWLUT_BASE */
+#define MCF_LCDC_GWLUT_BASE_BASE(x)     (((x)&0xFFFFFFFF)<<0)
+
+/*********************************************************************
+ *
+ * Phase Locked Loop (PLL)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_PLL_PODR              MCF_REG08(0xFC0C0000)
+#define MCF_PLL_PLLCR             MCF_REG08(0xFC0C0004)
+#define MCF_PLL_PMDR              MCF_REG08(0xFC0C0008)
+#define MCF_PLL_PFDR              MCF_REG08(0xFC0C000C)
+
+/* Bit definitions and macros for MCF_PLL_PODR */
+#define MCF_PLL_PODR_BUSDIV(x)    (((x)&0x0F)<<0)
+#define MCF_PLL_PODR_CPUDIV(x)    (((x)&0x0F)<<4)
+
+/* Bit definitions and macros for MCF_PLL_PLLCR */
+#define MCF_PLL_PLLCR_DITHDEV(x)  (((x)&0x07)<<0)
+#define MCF_PLL_PLLCR_DITHEN      (0x80)
+
+/* Bit definitions and macros for MCF_PLL_PMDR */
+#define MCF_PLL_PMDR_MODDIV(x)    (((x)&0xFF)<<0)
+
+/* Bit definitions and macros for MCF_PLL_PFDR */
+#define MCF_PLL_PFDR_MFD(x)       (((x)&0xFF)<<0)
+
+/*********************************************************************
+ *
+ * System Control Module Registers (SCM)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_SCM_MPR                    MCF_REG32(0xFC000000)
+#define MCF_SCM_PACRA                  MCF_REG32(0xFC000020)
+#define MCF_SCM_PACRB                  MCF_REG32(0xFC000024)
+#define MCF_SCM_PACRC                  MCF_REG32(0xFC000028)
+#define MCF_SCM_PACRD                  MCF_REG32(0xFC00002C)
+#define MCF_SCM_PACRE                  MCF_REG32(0xFC000040)
+#define MCF_SCM_PACRF                  MCF_REG32(0xFC000044)
+
+#define MCF_SCM_BCR                    MCF_REG32(0xFC040024)
+
+/*********************************************************************
+ *
+ * SDRAM Controller (SDRAMC)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_SDRAMC_SDMR                        MCF_REG32(0xFC0B8000)
+#define MCF_SDRAMC_SDCR                        MCF_REG32(0xFC0B8004)
+#define MCF_SDRAMC_SDCFG1              MCF_REG32(0xFC0B8008)
+#define MCF_SDRAMC_SDCFG2              MCF_REG32(0xFC0B800C)
+#define MCF_SDRAMC_LIMP_FIX            MCF_REG32(0xFC0B8080)
+#define MCF_SDRAMC_SDDS                        MCF_REG32(0xFC0B8100)
+#define MCF_SDRAMC_SDCS0               MCF_REG32(0xFC0B8110)
+#define MCF_SDRAMC_SDCS1               MCF_REG32(0xFC0B8114)
+#define MCF_SDRAMC_SDCS2               MCF_REG32(0xFC0B8118)
+#define MCF_SDRAMC_SDCS3               MCF_REG32(0xFC0B811C)
+#define MCF_SDRAMC_SDCS(x)             MCF_REG32(0xFC0B8110+((x)*0x004))
+
+/* Bit definitions and macros for MCF_SDRAMC_SDMR */
+#define MCF_SDRAMC_SDMR_CMD            (0x00010000)
+#define MCF_SDRAMC_SDMR_AD(x)          (((x)&0x00000FFF)<<18)
+#define MCF_SDRAMC_SDMR_BNKAD(x)       (((x)&0x00000003)<<30)
+#define MCF_SDRAMC_SDMR_BNKAD_LMR      (0x00000000)
+#define MCF_SDRAMC_SDMR_BNKAD_LEMR     (0x40000000)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCR */
+#define MCF_SDRAMC_SDCR_IPALL          (0x00000002)
+#define MCF_SDRAMC_SDCR_IREF           (0x00000004)
+#define MCF_SDRAMC_SDCR_DQS_OE(x)      (((x)&0x0000000F)<<8)
+#define MCF_SDRAMC_SDCR_PS(x)          (((x)&0x00000003)<<12)
+#define MCF_SDRAMC_SDCR_RCNT(x)                (((x)&0x0000003F)<<16)
+#define MCF_SDRAMC_SDCR_OE_RULE                (0x00400000)
+#define MCF_SDRAMC_SDCR_MUX(x)         (((x)&0x00000003)<<24)
+#define MCF_SDRAMC_SDCR_REF            (0x10000000)
+#define MCF_SDRAMC_SDCR_DDR            (0x20000000)
+#define MCF_SDRAMC_SDCR_CKE            (0x40000000)
+#define MCF_SDRAMC_SDCR_MODE_EN                (0x80000000)
+#define MCF_SDRAMC_SDCR_PS_16          (0x00002000)
+#define MCF_SDRAMC_SDCR_PS_32          (0x00000000)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCFG1 */
+#define MCF_SDRAMC_SDCFG1_WTLAT(x)     (((x)&0x00000007)<<4)
+#define MCF_SDRAMC_SDCFG1_REF2ACT(x)   (((x)&0x0000000F)<<8)
+#define MCF_SDRAMC_SDCFG1_PRE2ACT(x)   (((x)&0x00000007)<<12)
+#define MCF_SDRAMC_SDCFG1_ACT2RW(x)    (((x)&0x00000007)<<16)
+#define MCF_SDRAMC_SDCFG1_RDLAT(x)     (((x)&0x0000000F)<<20)
+#define MCF_SDRAMC_SDCFG1_SWT2RD(x)    (((x)&0x00000007)<<24)
+#define MCF_SDRAMC_SDCFG1_SRD2RW(x)    (((x)&0x0000000F)<<28)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCFG2 */
+#define MCF_SDRAMC_SDCFG2_BL(x)                (((x)&0x0000000F)<<16)
+#define MCF_SDRAMC_SDCFG2_BRD2WT(x)    (((x)&0x0000000F)<<20)
+#define MCF_SDRAMC_SDCFG2_BWT2RW(x)    (((x)&0x0000000F)<<24)
+#define MCF_SDRAMC_SDCFG2_BRD2PRE(x)   (((x)&0x0000000F)<<28)
+
+/* Device Errata - LIMP mode work around */
+#define MCF_SDRAMC_REFRESH             (0x40000000)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDDS */
+#define MCF_SDRAMC_SDDS_SB_D(x)                (((x)&0x00000003)<<0)
+#define MCF_SDRAMC_SDDS_SB_S(x)                (((x)&0x00000003)<<2)
+#define MCF_SDRAMC_SDDS_SB_A(x)                (((x)&0x00000003)<<4)
+#define MCF_SDRAMC_SDDS_SB_C(x)                (((x)&0x00000003)<<6)
+#define MCF_SDRAMC_SDDS_SB_E(x)                (((x)&0x00000003)<<8)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCS */
+#define MCF_SDRAMC_SDCS_CSSZ(x)                (((x)&0x0000001F)<<0)
+#define MCF_SDRAMC_SDCS_BASE(x)                (((x)&0x00000FFF)<<20)
+#define MCF_SDRAMC_SDCS_BA(x)          ((x)&0xFFF00000)
+#define MCF_SDRAMC_SDCS_CSSZ_DIABLE    (0x00000000)
+#define MCF_SDRAMC_SDCS_CSSZ_1MBYTE    (0x00000013)
+#define MCF_SDRAMC_SDCS_CSSZ_2MBYTE    (0x00000014)
+#define MCF_SDRAMC_SDCS_CSSZ_4MBYTE    (0x00000015)
+#define MCF_SDRAMC_SDCS_CSSZ_8MBYTE    (0x00000016)
+#define MCF_SDRAMC_SDCS_CSSZ_16MBYTE   (0x00000017)
+#define MCF_SDRAMC_SDCS_CSSZ_32MBYTE   (0x00000018)
+#define MCF_SDRAMC_SDCS_CSSZ_64MBYTE   (0x00000019)
+#define MCF_SDRAMC_SDCS_CSSZ_128MBYTE  (0x0000001A)
+#define MCF_SDRAMC_SDCS_CSSZ_256MBYTE  (0x0000001B)
+#define MCF_SDRAMC_SDCS_CSSZ_512MBYTE  (0x0000001C)
+#define MCF_SDRAMC_SDCS_CSSZ_1GBYTE    (0x0000001D)
+#define MCF_SDRAMC_SDCS_CSSZ_2GBYTE    (0x0000001E)
+#define MCF_SDRAMC_SDCS_CSSZ_4GBYTE    (0x0000001F)
+
+/*********************************************************************
+ *
+ *      FlexCAN module registers
+ *
+ *********************************************************************/
+#define MCF_FLEXCAN_BASEADDR(x)                (0xFC020000+(x)*0x0800)
+#define MCF_FLEXCAN_CANMCR(x)          MCF_REG32(0xFC020000+(x)*0x0800+0x00)
+#define MCF_FLEXCAN_CANCTRL(x)         MCF_REG32(0xFC020000+(x)*0x0800+0x04)
+#define MCF_FLEXCAN_TIMER(x)           MCF_REG32(0xFC020000+(x)*0x0800+0x08)
+#define MCF_FLEXCAN_RXGMASK(x)         MCF_REG32(0xFC020000+(x)*0x0800+0x10)
+#define MCF_FLEXCAN_RX14MASK(x)                MCF_REG32(0xFC020000+(x)*0x0800+0x14)
+#define MCF_FLEXCAN_RX15MASK(x)                MCF_REG32(0xFC020000+(x)*0x0800+0x18)
+#define MCF_FLEXCAN_ERRCNT(x)          MCF_REG32(0xFC020000+(x)*0x0800+0x1C)
+#define MCF_FLEXCAN_ERRSTAT(x)         MCF_REG32(0xFC020000+(x)*0x0800+0x20)
+#define MCF_FLEXCAN_IMASK(x)           MCF_REG32(0xFC020000+(x)*0x0800+0x28)
+#define MCF_FLEXCAN_IFLAG(x)           MCF_REG32(0xFC020000+(x)*0x0800+0x30)
+
+#define MCF_FLEXCAN_MB_CNT(x,y)                MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x0)
+#define MCF_FLEXCAN_MB_ID(x,y)         MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x4)
+#define MCF_FLEXCAN_MB_DB(x,y,z)       MCF_REG08(0xFC020080+(x)*0x0800+(y)*0x10+0x8+(z)*0x1)
+
+/*
+ *      FlexCAN Module Configuration Register
+ */
+#define CANMCR_MDIS            (0x80000000)
+#define CANMCR_FRZ             (0x40000000)
+#define CANMCR_HALT            (0x10000000)
+#define CANMCR_SOFTRST         (0x02000000)
+#define CANMCR_FRZACK          (0x01000000)
+#define CANMCR_SUPV            (0x00800000)
+#define CANMCR_MAXMB(x)         ((x)&0x0F)
+
+/*
+ *      FlexCAN Control Register
+ */
+#define CANCTRL_PRESDIV(x)      (((x)&0xFF)<<24)
+#define CANCTRL_RJW(x)          (((x)&0x03)<<22)
+#define CANCTRL_PSEG1(x)        (((x)&0x07)<<19)
+#define CANCTRL_PSEG2(x)        (((x)&0x07)<<16)
+#define CANCTRL_BOFFMSK         (0x00008000)
+#define CANCTRL_ERRMSK         (0x00004000)
+#define CANCTRL_CLKSRC         (0x00002000)
+#define CANCTRL_LPB            (0x00001000)
+#define CANCTRL_SAMP           (0x00000080)
+#define CANCTRL_BOFFREC         (0x00000040)
+#define CANCTRL_TSYNC           (0x00000020)
+#define CANCTRL_LBUF            (0x00000010)
+#define CANCTRL_LOM             (0x00000008)
+#define CANCTRL_PROPSEG(x)      ((x)&0x07)
+
+/*
+ *      FlexCAN Error Counter Register
+ */
+#define ERRCNT_RXECTR(x)        (((x)&0xFF)<<8)
+#define ERRCNT_TXECTR(x)        ((x)&0xFF)
+
+/*
+ *      FlexCAN Error and Status Register
+ */
+#define ERRSTAT_BITERR(x)       (((x)&0x03)<<14)
+#define ERRSTAT_ACKERR           (0x00002000)
+#define ERRSTAT_CRCERR           (0x00001000)
+#define ERRSTAT_FRMERR           (0x00000800)
+#define ERRSTAT_STFERR           (0x00000400)
+#define ERRSTAT_TXWRN            (0x00000200)
+#define ERRSTAT_RXWRN            (0x00000100)
+#define ERRSTAT_IDLE             (0x00000080)
+#define ERRSTAT_TXRX             (0x00000040)
+#define ERRSTAT_FLTCONF(x)       (((x)&0x03)<<4)
+#define ERRSTAT_BOFFINT          (0x00000004)
+#define ERRSTAT_ERRINT           (0x00000002)
+
+/*
+ *      Interrupt Mask Register
+ */
+#define IMASK_BUF15M           (0x8000)
+#define IMASK_BUF14M           (0x4000)
+#define IMASK_BUF13M           (0x2000)
+#define IMASK_BUF12M           (0x1000)
+#define IMASK_BUF11M           (0x0800)
+#define IMASK_BUF10M           (0x0400)
+#define IMASK_BUF9M            (0x0200)
+#define IMASK_BUF8M            (0x0100)
+#define IMASK_BUF7M            (0x0080)
+#define IMASK_BUF6M            (0x0040)
+#define IMASK_BUF5M            (0x0020)
+#define IMASK_BUF4M            (0x0010)
+#define IMASK_BUF3M            (0x0008)
+#define IMASK_BUF2M            (0x0004)
+#define IMASK_BUF1M            (0x0002)
+#define IMASK_BUF0M            (0x0001)
+#define IMASK_BUFnM(x)         (0x1<<(x))
+#define IMASK_BUFF_ENABLE_ALL  (0x1111)
+#define IMASK_BUFF_DISABLE_ALL (0x0000)
+
+/*
+ *      Interrupt Flag Register
+ */
+#define IFLAG_BUF15M           (0x8000)
+#define IFLAG_BUF14M           (0x4000)
+#define IFLAG_BUF13M           (0x2000)
+#define IFLAG_BUF12M           (0x1000)
+#define IFLAG_BUF11M           (0x0800)
+#define IFLAG_BUF10M           (0x0400)
+#define IFLAG_BUF9M            (0x0200)
+#define IFLAG_BUF8M            (0x0100)
+#define IFLAG_BUF7M            (0x0080)
+#define IFLAG_BUF6M            (0x0040)
+#define IFLAG_BUF5M            (0x0020)
+#define IFLAG_BUF4M            (0x0010)
+#define IFLAG_BUF3M            (0x0008)
+#define IFLAG_BUF2M            (0x0004)
+#define IFLAG_BUF1M            (0x0002)
+#define IFLAG_BUF0M            (0x0001)
+#define IFLAG_BUFF_SET_ALL     (0xFFFF)
+#define IFLAG_BUFF_CLEAR_ALL   (0x0000)
+#define IFLAG_BUFnM(x)         (0x1<<(x))
+
+/*
+ *      Message Buffers
+ */
+#define MB_CNT_CODE(x)         (((x)&0x0F)<<24)
+#define MB_CNT_SRR             (0x00400000)
+#define MB_CNT_IDE             (0x00200000)
+#define MB_CNT_RTR             (0x00100000)
+#define MB_CNT_LENGTH(x)       (((x)&0x0F)<<16)
+#define MB_CNT_TIMESTAMP(x)    ((x)&0xFFFF)
+#define MB_ID_STD(x)           (((x)&0x07FF)<<18)
+#define MB_ID_EXT(x)           ((x)&0x3FFFF)
+
+/*********************************************************************
+ *
+ * Edge Port Module (EPORT)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_EPORT_EPPAR                MCF_REG16(0xFC094000)
+#define MCF_EPORT_EPDDR                MCF_REG08(0xFC094002)
+#define MCF_EPORT_EPIER                MCF_REG08(0xFC094003)
+#define MCF_EPORT_EPDR                 MCF_REG08(0xFC094004)
+#define MCF_EPORT_EPPDR                MCF_REG08(0xFC094005)
+#define MCF_EPORT_EPFR                 MCF_REG08(0xFC094006)
+
+/* Bit definitions and macros for MCF_EPORT_EPPAR */
+#define MCF_EPORT_EPPAR_EPPA1(x)       (((x)&0x0003)<<2)
+#define MCF_EPORT_EPPAR_EPPA2(x)       (((x)&0x0003)<<4)
+#define MCF_EPORT_EPPAR_EPPA3(x)       (((x)&0x0003)<<6)
+#define MCF_EPORT_EPPAR_EPPA4(x)       (((x)&0x0003)<<8)
+#define MCF_EPORT_EPPAR_EPPA5(x)       (((x)&0x0003)<<10)
+#define MCF_EPORT_EPPAR_EPPA6(x)       (((x)&0x0003)<<12)
+#define MCF_EPORT_EPPAR_EPPA7(x)       (((x)&0x0003)<<14)
+#define MCF_EPORT_EPPAR_LEVEL          (0)
+#define MCF_EPORT_EPPAR_RISING         (1)
+#define MCF_EPORT_EPPAR_FALLING        (2)
+#define MCF_EPORT_EPPAR_BOTH           (3)
+#define MCF_EPORT_EPPAR_EPPA7_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA7_RISING   (0x4000)
+#define MCF_EPORT_EPPAR_EPPA7_FALLING  (0x8000)
+#define MCF_EPORT_EPPAR_EPPA7_BOTH     (0xC000)
+#define MCF_EPORT_EPPAR_EPPA6_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA6_RISING   (0x1000)
+#define MCF_EPORT_EPPAR_EPPA6_FALLING  (0x2000)
+#define MCF_EPORT_EPPAR_EPPA6_BOTH     (0x3000)
+#define MCF_EPORT_EPPAR_EPPA5_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA5_RISING   (0x0400)
+#define MCF_EPORT_EPPAR_EPPA5_FALLING  (0x0800)
+#define MCF_EPORT_EPPAR_EPPA5_BOTH     (0x0C00)
+#define MCF_EPORT_EPPAR_EPPA4_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA4_RISING   (0x0100)
+#define MCF_EPORT_EPPAR_EPPA4_FALLING  (0x0200)
+#define MCF_EPORT_EPPAR_EPPA4_BOTH     (0x0300)
+#define MCF_EPORT_EPPAR_EPPA3_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA3_RISING   (0x0040)
+#define MCF_EPORT_EPPAR_EPPA3_FALLING  (0x0080)
+#define MCF_EPORT_EPPAR_EPPA3_BOTH     (0x00C0)
+#define MCF_EPORT_EPPAR_EPPA2_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA2_RISING   (0x0010)
+#define MCF_EPORT_EPPAR_EPPA2_FALLING  (0x0020)
+#define MCF_EPORT_EPPAR_EPPA2_BOTH     (0x0030)
+#define MCF_EPORT_EPPAR_EPPA1_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA1_RISING   (0x0004)
+#define MCF_EPORT_EPPAR_EPPA1_FALLING  (0x0008)
+#define MCF_EPORT_EPPAR_EPPA1_BOTH     (0x000C)
+
+/* Bit definitions and macros for MCF_EPORT_EPDDR */
+#define MCF_EPORT_EPDDR_EPDD1          (0x02)
+#define MCF_EPORT_EPDDR_EPDD2          (0x04)
+#define MCF_EPORT_EPDDR_EPDD3          (0x08)
+#define MCF_EPORT_EPDDR_EPDD4          (0x10)
+#define MCF_EPORT_EPDDR_EPDD5          (0x20)
+#define MCF_EPORT_EPDDR_EPDD6          (0x40)
+#define MCF_EPORT_EPDDR_EPDD7          (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPIER */
+#define MCF_EPORT_EPIER_EPIE1          (0x02)
+#define MCF_EPORT_EPIER_EPIE2          (0x04)
+#define MCF_EPORT_EPIER_EPIE3          (0x08)
+#define MCF_EPORT_EPIER_EPIE4          (0x10)
+#define MCF_EPORT_EPIER_EPIE5          (0x20)
+#define MCF_EPORT_EPIER_EPIE6          (0x40)
+#define MCF_EPORT_EPIER_EPIE7          (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPDR */
+#define MCF_EPORT_EPDR_EPD1            (0x02)
+#define MCF_EPORT_EPDR_EPD2            (0x04)
+#define MCF_EPORT_EPDR_EPD3            (0x08)
+#define MCF_EPORT_EPDR_EPD4            (0x10)
+#define MCF_EPORT_EPDR_EPD5            (0x20)
+#define MCF_EPORT_EPDR_EPD6            (0x40)
+#define MCF_EPORT_EPDR_EPD7            (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPPDR */
+#define MCF_EPORT_EPPDR_EPPD1          (0x02)
+#define MCF_EPORT_EPPDR_EPPD2          (0x04)
+#define MCF_EPORT_EPPDR_EPPD3          (0x08)
+#define MCF_EPORT_EPPDR_EPPD4          (0x10)
+#define MCF_EPORT_EPPDR_EPPD5          (0x20)
+#define MCF_EPORT_EPPDR_EPPD6          (0x40)
+#define MCF_EPORT_EPPDR_EPPD7          (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPFR */
+#define MCF_EPORT_EPFR_EPF1            (0x02)
+#define MCF_EPORT_EPFR_EPF2            (0x04)
+#define MCF_EPORT_EPFR_EPF3            (0x08)
+#define MCF_EPORT_EPFR_EPF4            (0x10)
+#define MCF_EPORT_EPFR_EPF5            (0x20)
+#define MCF_EPORT_EPFR_EPF6            (0x40)
+#define MCF_EPORT_EPFR_EPF7            (0x80)
+
+/********************************************************************/
+#endif /* m532xsim_h */
diff --git a/include/asm-mips/Kbuild b/include/asm-mips/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-mips/apm.h b/include/asm-mips/apm.h
new file mode 100644 (file)
index 0000000..4b99ffc
--- /dev/null
@@ -0,0 +1,64 @@
+/* -*- linux-c -*-
+ *
+ * (C) 2003 zecke@handhelds.org
+ *
+ * GPL version 2
+ *
+ * based on arch/arm/kernel/apm.c
+ * factor out the information needed by architectures to provide
+ * apm status
+ *
+ *
+ */
+#ifndef MIPS_ASM_SA1100_APM_H
+#define MIPS_ASM_SA1100_APM_H
+
+#include <linux/apm_bios.h>
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation.  Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+       unsigned char   ac_line_status;
+#define APM_AC_OFFLINE                 0
+#define APM_AC_ONLINE                  1
+#define APM_AC_BACKUP                  2
+#define APM_AC_UNKNOWN                 0xff
+
+       unsigned char   battery_status;
+#define APM_BATTERY_STATUS_HIGH                0
+#define APM_BATTERY_STATUS_LOW         1
+#define APM_BATTERY_STATUS_CRITICAL    2
+#define APM_BATTERY_STATUS_CHARGING    3
+#define APM_BATTERY_STATUS_NOT_PRESENT 4
+#define APM_BATTERY_STATUS_UNKNOWN     0xff
+
+       unsigned char   battery_flag;
+#define APM_BATTERY_FLAG_HIGH          (1 << 0)
+#define APM_BATTERY_FLAG_LOW           (1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL      (1 << 2)
+#define APM_BATTERY_FLAG_CHARGING      (1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT   (1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN       0xff
+
+       int             battery_life;
+       int             time;
+       int             units;
+#define APM_UNITS_MINS                 0
+#define APM_UNITS_SECS                 1
+#define APM_UNITS_UNKNOWN              -1
+
+};
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
+
+#endif
diff --git a/include/asm-mips/emma2rh/emma2rh.h b/include/asm-mips/emma2rh/emma2rh.h
new file mode 100644 (file)
index 0000000..4fb8df7
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ *  include/asm-mips/emma2rh/emma2rh.h
+ *      This file is EMMA2RH common header.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
+ *          Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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_EMMA2RH_EMMA2RH_H
+#define __ASM_EMMA2RH_EMMA2RH_H
+
+/*
+ * EMMA2RH registers
+ */
+#define REGBASE 0x10000000
+
+#define EMMA2RH_BHIF_STRAP_0   (0x000010+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_0  (0x000030+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_1  (0x000034+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_2  (0x000038+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_0  (0x000040+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_1  (0x000044+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_2  (0x000048+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_0 (0x000050+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_1 (0x000054+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_2 (0x000058+REGBASE)
+#define EMMA2RH_BHIF_SW_INT    (0x000070+REGBASE)
+#define EMMA2RH_BHIF_SW_INT_EN (0x000080+REGBASE)
+#define EMMA2RH_BHIF_SW_INT_CLR        (0x000090+REGBASE)
+#define EMMA2RH_BHIF_MAIN_CTRL (0x0000b4+REGBASE)
+#define EMMA2RH_BHIF_EXCEPT_VECT_BASE_ADDRESS  (0x0000c0+REGBASE)
+#define EMMA2RH_GPIO_DIR       (0x110d20+REGBASE)
+#define EMMA2RH_GPIO_INT_ST    (0x110d30+REGBASE)
+#define EMMA2RH_GPIO_INT_MASK  (0x110d3c+REGBASE)
+#define EMMA2RH_GPIO_INT_MODE  (0x110d48+REGBASE)
+#define EMMA2RH_GPIO_INT_CND_A (0x110d54+REGBASE)
+#define EMMA2RH_GPIO_INT_CND_B (0x110d60+REGBASE)
+#define EMMA2RH_PBRD_INT_EN    (0x100010+REGBASE)
+#define EMMA2RH_PBRD_CLKSEL    (0x100028+REGBASE)
+#define EMMA2RH_PFUR0_BASE     (0x101000+REGBASE)
+#define EMMA2RH_PFUR1_BASE     (0x102000+REGBASE)
+#define EMMA2RH_PFUR2_BASE     (0x103000+REGBASE)
+#define EMMA2RH_PIIC0_BASE     (0x107000+REGBASE)
+#define EMMA2RH_PIIC1_BASE     (0x108000+REGBASE)
+#define EMMA2RH_PIIC2_BASE     (0x109000+REGBASE)
+#define EMMA2RH_PCI_CONTROL    (0x200000+REGBASE)
+#define EMMA2RH_PCI_ARBIT_CTR  (0x200004+REGBASE)
+#define EMMA2RH_PCI_IWIN0_CTR  (0x200010+REGBASE)
+#define EMMA2RH_PCI_IWIN1_CTR  (0x200014+REGBASE)
+#define EMMA2RH_PCI_INIT_ESWP  (0x200018+REGBASE)
+#define EMMA2RH_PCI_INT                (0x200020+REGBASE)
+#define EMMA2RH_PCI_INT_EN     (0x200024+REGBASE)
+#define EMMA2RH_PCI_TWIN_CTR   (0x200030+REGBASE)
+#define EMMA2RH_PCI_TWIN_BADR  (0x200034+REGBASE)
+#define EMMA2RH_PCI_TWIN0_DADR (0x200038+REGBASE)
+#define EMMA2RH_PCI_TWIN1_DADR (0x20003c+REGBASE)
+
+/*
+ *  Memory map (physical address)
+ *
+ *  Note most of the following address must be properly aligned by the
+ *  corresponding size.  For example, if PCI_IO_SIZE is 16MB, then
+ *  PCI_IO_BASE must be aligned along 16MB boundary.
+ */
+
+/* the actual ram size is detected at run-time */
+#define EMMA2RH_RAM_BASE       0x00000000
+#define EMMA2RH_RAM_SIZE       0x10000000      /* less than 256MB */
+
+#define EMMA2RH_IO_BASE                0x10000000
+#define EMMA2RH_IO_SIZE                0x01000000      /* 16 MB */
+
+#define EMMA2RH_GENERALIO_BASE 0x11000000
+#define EMMA2RH_GENERALIO_SIZE 0x01000000      /* 16 MB */
+
+#define EMMA2RH_PCI_IO_BASE    0x12000000
+#define EMMA2RH_PCI_IO_SIZE    0x02000000      /* 32 MB */
+
+#define EMMA2RH_PCI_MEM_BASE   0x14000000
+#define EMMA2RH_PCI_MEM_SIZE   0x08000000      /* 128 MB */
+
+#define EMMA2RH_ROM_BASE       0x1c000000
+#define EMMA2RH_ROM_SIZE       0x04000000      /* 64 MB */
+
+#define EMMA2RH_PCI_CONFIG_BASE        EMMA2RH_PCI_IO_BASE
+#define EMMA2RH_PCI_CONFIG_SIZE        EMMA2RH_PCI_IO_SIZE
+
+#define NUM_CPU_IRQ            8
+#define NUM_EMMA2RH_IRQ                96
+
+#define CPU_EMMA2RH_CASCADE    2
+#define EMMA2RH_IRQ_BASE       0
+
+/*
+ * emma2rh irq defs
+ */
+
+#define EMMA2RH_IRQ_INT0       (0 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT1       (1 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT2       (2 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT3       (3 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT4       (4 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT5       (5 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT6       (6 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT7       (7 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT8       (8 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT9       (9 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT10      (10 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT11      (11 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT12      (12 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT13      (13 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT14      (14 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT15      (15 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT16      (16 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT17      (17 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT18      (18 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT19      (19 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT20      (20 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT21      (21 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT22      (22 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT23      (23 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT24      (24 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT25      (25 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT26      (26 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT27      (27 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT28      (28 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT29      (29 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT30      (30 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT31      (31 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT32      (32 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT33      (33 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT34      (34 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT35      (35 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT36      (36 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT37      (37 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT38      (38 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT39      (39 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT40      (40 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT41      (41 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT42      (42 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT43      (43 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT44      (44 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT45      (45 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT46      (46 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT47      (47 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT48      (48 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT49      (49 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT50      (50 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT51      (51 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT52      (52 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT53      (53 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT54      (54 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT55      (55 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT56      (56 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT57      (57 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT58      (58 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT59      (59 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT60      (60 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT61      (61 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT62      (62 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT63      (63 + EMMA2RH_IRQ_BASE)
+
+#define EMMA2RH_IRQ_PFUR0      EMMA2RH_IRQ_INT49
+#define EMMA2RH_IRQ_PFUR1      EMMA2RH_IRQ_INT50
+#define EMMA2RH_IRQ_PFUR2      EMMA2RH_IRQ_INT51
+#define EMMA2RH_IRQ_PIIC0      EMMA2RH_IRQ_INT56
+#define EMMA2RH_IRQ_PIIC1      EMMA2RH_IRQ_INT57
+#define EMMA2RH_IRQ_PIIC2      EMMA2RH_IRQ_INT58
+
+/*
+ *  EMMA2RH Register Access
+ */
+
+#define EMMA2RH_BASE (0xa0000000)
+
+static inline void emma2rh_sync(void)
+{
+       volatile u32 *p = (volatile u32 *)0xbfc00000;
+       (void)(*p);
+}
+
+static inline void emma2rh_out32(u32 offset, u32 val)
+{
+       *(volatile u32 *)(EMMA2RH_BASE | offset) = val;
+       emma2rh_sync();
+}
+
+static inline u32 emma2rh_in32(u32 offset)
+{
+       u32 val = *(volatile u32 *)(EMMA2RH_BASE | offset);
+       emma2rh_sync();
+       return val;
+}
+
+static inline void emma2rh_out16(u32 offset, u16 val)
+{
+       *(volatile u16 *)(EMMA2RH_BASE | offset) = val;
+       emma2rh_sync();
+}
+
+static inline u16 emma2rh_in16(u32 offset)
+{
+       u16 val = *(volatile u16 *)(EMMA2RH_BASE | offset);
+       emma2rh_sync();
+       return val;
+}
+
+static inline void emma2rh_out8(u32 offset, u8 val)
+{
+       *(volatile u8 *)(EMMA2RH_BASE | offset) = val;
+       emma2rh_sync();
+}
+
+static inline u8 emma2rh_in8(u32 offset)
+{
+       u8 val = *(volatile u8 *)(EMMA2RH_BASE | offset);
+       emma2rh_sync();
+       return val;
+}
+
+/**
+ * IIC registers map
+ **/
+
+/*---------------------------------------------------------------------------*/
+/* CNT - Control register (00H R/W)                                          */
+/*---------------------------------------------------------------------------*/
+#define SPT         0x00000001
+#define STT         0x00000002
+#define ACKE        0x00000004
+#define WTIM        0x00000008
+#define SPIE        0x00000010
+#define WREL        0x00000020
+#define LREL        0x00000040
+#define IICE        0x00000080
+#define CNT_RESERVED    0x000000ff     /* reserved bit 0 */
+
+#define I2C_EMMA_START      (IICE | STT)
+#define I2C_EMMA_STOP       (IICE | SPT)
+#define I2C_EMMA_REPSTART   I2C_EMMA_START
+
+/*---------------------------------------------------------------------------*/
+/* STA - Status register (10H Read)                                          */
+/*---------------------------------------------------------------------------*/
+#define MSTS        0x00000080
+#define ALD         0x00000040
+#define EXC         0x00000020
+#define COI         0x00000010
+#define TRC         0x00000008
+#define ACKD        0x00000004
+#define STD         0x00000002
+#define SPD         0x00000001
+
+/*---------------------------------------------------------------------------*/
+/* CSEL - Clock select register (20H R/W)                                    */
+/*---------------------------------------------------------------------------*/
+#define FCL         0x00000080
+#define ND50        0x00000040
+#define CLD         0x00000020
+#define DAD         0x00000010
+#define SMC         0x00000008
+#define DFC         0x00000004
+#define CL          0x00000003
+#define CSEL_RESERVED   0x000000ff     /* reserved bit 0 */
+
+#define FAST397     0x0000008b
+#define FAST297     0x0000008a
+#define FAST347     0x0000000b
+#define FAST260     0x0000000a
+#define FAST130     0x00000008
+#define STANDARD108 0x00000083
+#define STANDARD83  0x00000082
+#define STANDARD95  0x00000003
+#define STANDARD73  0x00000002
+#define STANDARD36  0x00000001
+#define STANDARD71  0x00000000
+
+/*---------------------------------------------------------------------------*/
+/* SVA - Slave address register (30H R/W)                                    */
+/*---------------------------------------------------------------------------*/
+#define SVA         0x000000fe
+
+/*---------------------------------------------------------------------------*/
+/* SHR - Shift register (40H R/W)                                            */
+/*---------------------------------------------------------------------------*/
+#define SR          0x000000ff
+
+/*---------------------------------------------------------------------------*/
+/* INT - Interrupt register (50H R/W)                                        */
+/* INTM - Interrupt mask register (60H R/W)                                  */
+/*---------------------------------------------------------------------------*/
+#define INTE0       0x00000001
+
+/***********************************************************************
+ * I2C registers
+ ***********************************************************************
+ */
+#define I2C_EMMA_CNT            0x00
+#define I2C_EMMA_STA            0x10
+#define I2C_EMMA_CSEL           0x20
+#define I2C_EMMA_SVA            0x30
+#define I2C_EMMA_SHR            0x40
+#define I2C_EMMA_INT            0x50
+#define I2C_EMMA_INTM           0x60
+
+/*
+ * include the board dependent part
+ */
+#if defined(CONFIG_MARKEINS)
+#include <asm/emma2rh/markeins.h>
+#else
+#error "Unknown EMMA2RH board!"
+#endif
+
+#endif /* __ASM_EMMA2RH_EMMA2RH_H */
diff --git a/include/asm-mips/emma2rh/markeins.h b/include/asm-mips/emma2rh/markeins.h
new file mode 100644 (file)
index 0000000..8fa7667
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  include/asm-mips/emma2rh/markeins.h
+ *      This file is EMMA2RH board depended header.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
+ *          Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU 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 MARKEINS_H
+#define MARKEINS_H
+
+#define NUM_EMMA2RH_IRQ_SW     32
+#define NUM_EMMA2RH_IRQ_GPIO   32
+
+#define EMMA2RH_SW_CASCADE     (EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0)
+#define EMMA2RH_GPIO_CASCADE   (EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0)
+
+#define EMMA2RH_SW_IRQ_BASE    (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ)
+#define EMMA2RH_GPIO_IRQ_BASE  (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW)
+#define CPU_IRQ_BASE           (EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO)
+
+#define EMMA2RH_SW_IRQ_INT0    (0+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT1    (1+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT2    (2+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT3    (3+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT4    (4+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT5    (5+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT6    (6+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT7    (7+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT8    (8+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT9    (9+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT10   (10+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT11   (11+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT12   (12+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT13   (13+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT14   (14+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT15   (15+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT16   (16+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT17   (17+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT18   (18+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT19   (19+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT20   (20+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT21   (21+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT22   (22+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT23   (23+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT24   (24+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT25   (25+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT26   (26+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT27   (27+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT28   (28+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT29   (29+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT30   (30+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT31   (31+EMMA2RH_SW_IRQ_BASE)
+
+#define MARKEINS_PCI_IRQ_INTA  EMMA2RH_GPIO_IRQ_BASE+15
+#define MARKEINS_PCI_IRQ_INTB  EMMA2RH_GPIO_IRQ_BASE+16
+#define MARKEINS_PCI_IRQ_INTC  EMMA2RH_GPIO_IRQ_BASE+17
+#define MARKEINS_PCI_IRQ_INTD  EMMA2RH_GPIO_IRQ_BASE+18
+
+#endif /* CONFIG_MARKEINS */
diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h
new file mode 100644 (file)
index 0000000..43ca09a
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * 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, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/hazards.h>
+
+__asm__ (
+       "       .macro  raw_local_irq_enable                            \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
+       "       ori     $1, 0x400                                       \n"
+       "       xori    $1, 0x400                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       ei                                                      \n"
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1e                                         \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_enable_hazard                                       \n"
+       "       .set    pop                                             \n"
+       "       .endm");
+
+static inline void raw_local_irq_enable(void)
+{
+       __asm__ __volatile__(
+               "raw_local_irq_enable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+}
+
+/*
+ * For cli() we have to insert nops to make sure that the new value
+ * has actually arrived in the status register before the end of this
+ * macro.
+ * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
+ * no nops at all.
+ */
+/*
+ * For TX49, operating only IE bit is not enough.
+ *
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
+__asm__ (
+       "       .macro  raw_local_irq_disable\n"
+       "       .set    push                                            \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1                                       \n"
+       "       ori     $1, 0x400                                       \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       di                                                      \n"
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1f                                         \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+static inline void raw_local_irq_disable(void)
+{
+       __asm__ __volatile__(
+               "raw_local_irq_disable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+}
+
+__asm__ (
+       "       .macro  raw_local_save_flags flags                      \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\flags, $2, 1                                  \n"
+#else
+       "       mfc0    \\flags, $12                                    \n"
+#endif
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+#define raw_local_save_flags(x)                                                \
+__asm__ __volatile__(                                                  \
+       "raw_local_save_flags %0"                                       \
+       : "=r" (x))
+
+__asm__ (
+       "       .macro  raw_local_irq_save result                       \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\result, $2, 1                                 \n"
+       "       ori     $1, \\result, 0x400                             \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+       "       andi    \\result, \\result, 0x400                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       di      \\result                                        \n"
+       "       andi    \\result, 1                                     \n"
+#else
+       "       mfc0    \\result, $12                                   \n"
+       "       ori     $1, \\result, 0x1f                              \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $12                                         \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+#define raw_local_irq_save(x)                                          \
+__asm__ __volatile__(                                                  \
+       "raw_local_irq_save\t%0"                                        \
+       : "=r" (x)                                                      \
+       : /* no inputs */                                               \
+       : "memory")
+
+__asm__ (
+       "       .macro  raw_local_irq_restore flags                     \n"
+       "       .set    push                                            \n"
+       "       .set    noreorder                                       \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "mfc0   $1, $2, 1                                               \n"
+       "andi   \\flags, 0x400                                          \n"
+       "ori    $1, 0x400                                               \n"
+       "xori   $1, 0x400                                               \n"
+       "or     \\flags, $1                                             \n"
+       "mtc0   \\flags, $2, 1                                          \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+       /*
+        * Slow, but doesn't suffer from a relativly unlikely race
+        * condition we're having since days 1.
+        */
+       "       beqz    \\flags, 1f                                     \n"
+       "        di                                                     \n"
+       "       ei                                                      \n"
+       "1:                                                             \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /*
+        * Fast, dangerous.  Life is fun, life is good.
+        */
+       "       mfc0    $1, $12                                         \n"
+       "       ins     $1, \\flags, 0, 1                               \n"
+       "       mtc0    $1, $12                                         \n"
+#else
+       "       mfc0    $1, $12                                         \n"
+       "       andi    \\flags, 1                                      \n"
+       "       ori     $1, 0x1f                                        \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       or      \\flags, $1                                     \n"
+       "       mtc0    \\flags, $12                                    \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+#define raw_local_irq_restore(flags)                                   \
+do {                                                                   \
+       unsigned long __tmp1;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+               "raw_local_irq_restore\t%0"                             \
+               : "=r" (__tmp1)                                         \
+               : "0" (flags)                                           \
+               : "memory");                                            \
+} while(0)
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
+        */
+       return flags & 0x400;
+#else
+       return !(flags & 1);
+#endif
+}
+
+#endif
+
+/*
+ * Do the CPU's IRQ-state tracing from assembly code.
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS
+# define TRACE_IRQS_ON                                                 \
+       jal     trace_hardirqs_on
+# define TRACE_IRQS_OFF                                                        \
+       jal     trace_hardirqs_off
+#else
+# define TRACE_IRQS_ON
+# define TRACE_IRQS_OFF
+#endif
+
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/include/asm-mips/mach-emma2rh/irq.h b/include/asm-mips/mach-emma2rh/irq.h
new file mode 100644 (file)
index 0000000..bce6424
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_EMMA2RH_IRQ_H
+#define __ASM_MACH_EMMA2RH_IRQ_H
+
+#define NR_IRQS        256
+
+#endif /* __ASM_MACH_EMMA2RH_IRQ_H */
diff --git a/include/asm-mips/mach-excite/cpu-feature-overrides.h b/include/asm-mips/mach-excite/cpu-feature-overrides.h
new file mode 100644 (file)
index 0000000..0d31854
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 Thomas Koeller <thomas.koeller@baslerweb.com>
+ */
+#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * Basler eXcite has an RM9122 processor.
+ */
+#define cpu_has_watch          1
+#define cpu_has_mips16         0
+#define cpu_has_divec          0
+#define cpu_has_vce            0
+#define cpu_has_cache_cdex_p   0
+#define cpu_has_cache_cdex_s   0
+#define cpu_has_prefetch       1
+#define cpu_has_mcheck         0
+#define cpu_has_ejtag          0
+
+#define cpu_has_llsc           1
+#define cpu_has_vtag_icache    0
+#define cpu_has_dc_aliases     0
+#define cpu_has_ic_fills_f_dc  0
+#define cpu_has_dsp            0
+#define cpu_icache_snoops_remote_store 0
+
+#define cpu_has_nofpuex                0
+#define cpu_has_64bits         1
+
+#define cpu_has_inclusive_pcaches      0
+
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+#define cpu_scache_line_size() 32
+
+#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-excite/excite.h b/include/asm-mips/mach-excite/excite.h
new file mode 100644 (file)
index 0000000..130bd4b
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef __EXCITE_H__
+#define __EXCITE_H__
+
+#include <linux/init.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+
+#define EXCITE_CPU_EXT_CLOCK 100000000
+
+#if !defined(__ASSEMBLER__)
+void __init excite_kgdb_init(void);
+void excite_procfs_init(void);
+extern unsigned long memsize;
+extern char modetty[];
+extern u32 unit_id;
+#endif
+
+/* Base name for XICAP devices */
+#define XICAP_NAME     "xicap_gpi"
+
+/* OCD register offsets */
+#define LKB0           0x0038
+#define LKB5           0x0128
+#define LKM5           0x012C
+#define LKB7           0x0138
+#define LKM7           0x013c
+#define LKB8           0x0140
+#define LKM8           0x0144
+#define LKB9           0x0148
+#define LKM9           0x014c
+#define LKB10          0x0150
+#define LKM10          0x0154
+#define LKB11          0x0158
+#define LKM11          0x015c
+#define LKB12          0x0160
+#define LKM12          0x0164
+#define LKB13          0x0168
+#define LKM13          0x016c
+#define LDP0           0x0200
+#define LDP1           0x0210
+#define LDP2           0x0220
+#define LDP3           0x0230
+#define INTPIN0                0x0A40
+#define INTPIN1                0x0A44
+#define INTPIN2                0x0A48
+#define INTPIN3                0x0A4C
+#define INTPIN4                0x0A50
+#define INTPIN5                0x0A54
+#define INTPIN6                0x0A58
+#define INTPIN7                0x0A5C
+
+
+
+
+/* TITAN register offsets */
+#define CPRR           0x0004
+#define CPDSR          0x0008
+#define CPTC0R         0x000c
+#define CPTC1R         0x0010
+#define CPCFG0         0x0020
+#define CPCFG1         0x0024
+#define CPDST0A                0x0028
+#define CPDST0B                0x002c
+#define CPDST1A                0x0030
+#define CPDST1B                0x0034
+#define CPXDSTA                0x0038
+#define CPXDSTB                0x003c
+#define CPXCISRA       0x0048
+#define CPXCISRB       0x004c
+#define CPGIG0ER       0x0050
+#define CPGIG1ER       0x0054
+#define CPGRWL         0x0068
+#define CPURSLMT       0x00f8
+#define UACFG          0x0200
+#define UAINTS         0x0204
+#define SDRXFCIE       0x4828
+#define SDTXFCIE       0x4928
+#define INTP0Status0   0x1B00
+#define INTP0Mask0     0x1B04
+#define INTP0Set0      0x1B08
+#define INTP0Clear0    0x1B0C
+#define GXCFG          0x5000
+#define GXDMADRPFX     0x5018
+#define GXDMA_DESCADR  0x501c
+#define GXCH0TDESSTRT  0x5054
+
+/* IRQ definitions */
+#define NMICONFIG              0xac0
+#define TITAN_MSGINT   0xc4
+#define TITAN_IRQ      ((TITAN_MSGINT / 0x20) + 2)
+#define FPGA0_MSGINT   0x5a
+#define FPGA0_IRQ      ((FPGA0_MSGINT / 0x20) + 2)
+#define FPGA1_MSGINT   0x7b
+#define FPGA1_IRQ      ((FPGA1_MSGINT / 0x20) + 2)
+#define PHY_MSGINT     0x9c
+#define PHY_IRQ                ((PHY_MSGINT   / 0x20) + 2)
+
+#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE)
+/* Pre-release units used interrupt pin #9 */
+#define USB_IRQ                11
+#else
+/* Re-designed units use interrupt pin #1 */
+#define USB_MSGINT     0x39
+#define USB_IRQ                ((USB_MSGINT / 0x20) + 2)
+#endif
+#define TIMER_IRQ      12
+
+
+/* Device address ranges */
+#define EXCITE_OFFS_OCD                0x1fffc000
+#define        EXCITE_SIZE_OCD         (16 * 1024)
+#define EXCITE_PHYS_OCD                CPHYSADDR(EXCITE_OFFS_OCD)
+#define EXCITE_ADDR_OCD                CKSEG1ADDR(EXCITE_OFFS_OCD)
+
+#define EXCITE_OFFS_SCRAM      0x1fffa000
+#define        EXCITE_SIZE_SCRAM       (8 << 10)
+#define EXCITE_PHYS_SCRAM      CPHYSADDR(EXCITE_OFFS_SCRAM)
+#define EXCITE_ADDR_SCRAM      CKSEG1ADDR(EXCITE_OFFS_SCRAM)
+
+#define EXCITE_OFFS_PCI_IO     0x1fff8000
+#define        EXCITE_SIZE_PCI_IO      (8 << 10)
+#define EXCITE_PHYS_PCI_IO     CPHYSADDR(EXCITE_OFFS_PCI_IO)
+#define EXCITE_ADDR_PCI_IO     CKSEG1ADDR(EXCITE_OFFS_PCI_IO)
+
+#define EXCITE_OFFS_TITAN      0x1fff0000
+#define EXCITE_SIZE_TITAN      (32 << 10)
+#define EXCITE_PHYS_TITAN      CPHYSADDR(EXCITE_OFFS_TITAN)
+#define EXCITE_ADDR_TITAN      CKSEG1ADDR(EXCITE_OFFS_TITAN)
+
+#define EXCITE_OFFS_PCI_MEM    0x1ffe0000
+#define EXCITE_SIZE_PCI_MEM    (64 << 10)
+#define EXCITE_PHYS_PCI_MEM    CPHYSADDR(EXCITE_OFFS_PCI_MEM)
+#define EXCITE_ADDR_PCI_MEM    CKSEG1ADDR(EXCITE_OFFS_PCI_MEM)
+
+#define EXCITE_OFFS_FPGA       0x1ffdc000
+#define EXCITE_SIZE_FPGA       (16 << 10)
+#define EXCITE_PHYS_FPGA       CPHYSADDR(EXCITE_OFFS_FPGA)
+#define EXCITE_ADDR_FPGA       CKSEG1ADDR(EXCITE_OFFS_FPGA)
+
+#define EXCITE_OFFS_NAND       0x1ffd8000
+#define EXCITE_SIZE_NAND       (16 << 10)
+#define EXCITE_PHYS_NAND       CPHYSADDR(EXCITE_OFFS_NAND)
+#define EXCITE_ADDR_NAND       CKSEG1ADDR(EXCITE_OFFS_NAND)
+
+#define EXCITE_OFFS_BOOTROM    0x1f000000
+#define EXCITE_SIZE_BOOTROM    (8 << 20)
+#define EXCITE_PHYS_BOOTROM    CPHYSADDR(EXCITE_OFFS_BOOTROM)
+#define EXCITE_ADDR_BOOTROM    CKSEG1ADDR(EXCITE_OFFS_BOOTROM)
+
+/* FPGA address offsets */
+#define EXCITE_FPGA_DPR                0x0104  /* dual-ported ram */
+#define EXCITE_FPGA_SYSCTL     0x0200  /* system control register block */
+
+#endif /* __EXCITE_H__ */
diff --git a/include/asm-mips/mach-excite/excite_nandflash.h b/include/asm-mips/mach-excite/excite_nandflash.h
new file mode 100644 (file)
index 0000000..c4cf614
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __EXCITE_NANDFLASH_H__
+#define __EXCITE_NANDFLASH_H__
+
+/* Resource names */
+#define EXCITE_NANDFLASH_RESOURCE_REGS "excite_nandflash_regs"
+
+#endif /* __EXCITE_NANDFLASH_H__ */
diff --git a/include/asm-mips/mach-excite/rm9k_eth.h b/include/asm-mips/mach-excite/rm9k_eth.h
new file mode 100644 (file)
index 0000000..94705a4
--- /dev/null
@@ -0,0 +1,23 @@
+#if !defined(__RM9K_ETH_H__)
+#define __RM9K_ETH_H__
+
+#define RM9K_GE_NAME                   "rm9k_ge"
+
+/* Resource names */
+#define RM9K_GE_RESOURCE_MAC           "rm9k_ge_mac"
+#define RM9K_GE_RESOURCE_MSTAT         "rm9k_ge_mstat"
+#define RM9K_GE_RESOURCE_PKTPROC       "rm9k_ge_pktproc"
+#define RM9K_GE_RESOURCE_XDMA          "rm9k_ge_xdma"
+#define RM9K_GE_RESOURCE_FIFO_RX       "rm9k_ge_fifo_rx"
+#define RM9K_GE_RESOURCE_FIFO_TX       "rm9k_ge_fifo_tx"
+#define RM9K_GE_RESOURCE_FIFOMEM_RX    "rm9k_ge_fifo_memory_rx"
+#define RM9K_GE_RESOURCE_FIFOMEM_TX    "rm9k_ge_fifo_memory_tx"
+#define RM9K_GE_RESOURCE_PHY           "rm9k_ge_phy"
+#define RM9K_GE_RESOURCE_DMADESC_RX    "rm9k_ge_dmadesc_rx"
+#define RM9K_GE_RESOURCE_DMADESC_TX    "rm9k_ge_dmadesc_tx"
+#define RM9K_GE_RESOURCE_IRQ_MAIN      "rm9k_ge_irq_main"
+#define RM9K_GE_RESOURCE_IRQ_PHY       "rm9k_ge_irq_phy"
+#define RM9K_GE_RESOURCE_GPI_SLICE     "rm9k_ge_gpi_slice"
+#define RM9K_GE_RESOURCE_MDIO_CHANNEL  "rm9k_ge_mdio_channel"
+
+#endif /* !defined(__RM9K_ETH_H__) */
diff --git a/include/asm-mips/mach-excite/rm9k_wdt.h b/include/asm-mips/mach-excite/rm9k_wdt.h
new file mode 100644 (file)
index 0000000..3fa3c08
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __RM9K_WDT_H__
+#define __RM9K_WDT_H__
+
+/* Device name */
+#define WDT_NAME               "wdt_gpi"
+
+/* Resource names */
+#define WDT_RESOURCE_REGS      "excite_watchdog_regs"
+#define WDT_RESOURCE_IRQ       "excite_watchdog_irq"
+#define WDT_RESOURCE_COUNTER   "excite_watchdog_counter"
+
+#endif /* __RM9K_WDT_H__ */
diff --git a/include/asm-mips/mach-excite/rm9k_xicap.h b/include/asm-mips/mach-excite/rm9k_xicap.h
new file mode 100644 (file)
index 0000000..0095777
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __EXCITE_XICAP_H__
+#define __EXCITE_XICAP_H__
+
+
+/* Resource names */
+#define XICAP_RESOURCE_FIFO_RX         "xicap_fifo_rx"
+#define XICAP_RESOURCE_FIFO_TX         "xicap_fifo_tx"
+#define XICAP_RESOURCE_XDMA            "xicap_xdma"
+#define XICAP_RESOURCE_DMADESC         "xicap_dmadesc"
+#define XICAP_RESOURCE_PKTPROC         "xicap_pktproc"
+#define XICAP_RESOURCE_IRQ             "xicap_irq"
+#define XICAP_RESOURCE_GPI_SLICE       "xicap_gpi_slice"
+#define XICAP_RESOURCE_FIFO_BLK                "xicap_fifo_blocks"
+#define XICAP_RESOURCE_PKT_STREAM      "xicap_pkt_stream"
+
+#endif /* __EXCITE_XICAP_H__ */
diff --git a/include/asm-mips/mach-wrppmc/mach-gt64120.h b/include/asm-mips/mach-wrppmc/mach-gt64120.h
new file mode 100644 (file)
index 0000000..ba9205a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ * The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef __ASM_MIPS_GT64120_H
+#define __ASM_MIPS_GT64120_H
+
+/*
+ * This is the CPU physical memory map of PPMC Board:
+ *
+ *    0x00000000-0x03FFFFFF      - 64MB SDRAM (SCS[0]#)
+ *    0x1C000000-0x1C000000      - LED (CS0)
+ *    0x1C800000-0x1C800007      - UART 16550 port (CS1)
+ *    0x1F000000-0x1F000000      - MailBox (CS3)
+ *    0x1FC00000-0x20000000      - 4MB Flash (BOOT CS)
+ */
+
+#define WRPPMC_SDRAM_SCS0_BASE 0x00000000
+#define WRPPMC_SDRAM_SCS0_SIZE 0x04000000
+
+#define WRPPMC_UART16550_BASE  0x1C800000
+#define WRPPMC_UART16550_CLOCK 3686400 /* 3.68MHZ */
+
+#define WRPPMC_LED_BASE                0x1C000000
+#define WRPPMC_MBOX_BASE       0x1F000000
+
+#define WRPPMC_BOOTROM_BASE    0x1FC00000
+#define WRPPMC_BOOTROM_SIZE    0x00400000 /* 4M Flash */
+
+#define WRPPMC_MIPS_TIMER_IRQ  7 /* MIPS compare/count timer interrupt */
+#define WRPPMC_UART16550_IRQ   6
+#define WRPPMC_PCI_INTA_IRQ    3
+
+/*
+ * PCI Bus I/O and Memory resources allocation
+ *
+ * NOTE: We only have PCI_0 hose interface
+ */
+#define GT_PCI_MEM_BASE        0x13000000UL
+#define GT_PCI_MEM_SIZE        0x02000000UL
+#define GT_PCI_IO_BASE 0x11000000UL
+#define GT_PCI_IO_SIZE 0x02000000UL
+#define GT_ISA_IO_BASE PCI_IO_BASE
+
+/*
+ * PCI interrupts will come in on either the INTA or INTD interrups lines,
+ * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
+ * boards, they all either come in on IntD or they all come in on IntA, they
+ * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
+ * "requested" interrupt numbers and go through the list whenever we get an
+ * IntA/D.
+ *
+ * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
+ * INTD is 11.
+ */
+#define GT_TIMER       4
+#define GT_INTA                2
+#define GT_INTD                5
+
+#ifndef __ASSEMBLY__
+
+/*
+ * GT64120 internal register space base address
+ */
+extern unsigned long gt64120_base;
+
+#define GT64120_BASE   (gt64120_base)
+
+/* define WRPPMC_EARLY_DEBUG to enable early output something to UART */
+#undef WRPPMC_EARLY_DEBUG
+
+#ifdef WRPPMC_EARLY_DEBUG
+extern void wrppmc_led_on(int mask);
+extern void wrppmc_led_off(int mask);
+extern void wrppmc_early_printk(const char *fmt, ...);
+#else
+#define wrppmc_early_printk(fmt, ...) do {} while (0)
+#endif /* WRPPMC_EARLY_DEBUG */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_MIPS_GT64120_H */
diff --git a/include/asm-mips/rm9k-ocd.h b/include/asm-mips/rm9k-ocd.h
new file mode 100644 (file)
index 0000000..b0b80d9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.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
+ */
+
+#if !defined(_ASM_RM9K_OCD_H)
+#define _ASM_RM9K_OCD_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+extern volatile void __iomem * const ocd_base;
+extern volatile void __iomem * const titan_base;
+
+#define ocd_addr(__x__)                (ocd_base + (__x__))
+#define titan_addr(__x__)      (titan_base + (__x__))
+#define scram_addr(__x__)      (scram_base + (__x__))
+
+/* OCD register access */
+#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__))
+#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__))
+#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__))
+#define ocd_writel(__val__, __offs__) \
+       __raw_writel((__val__), ocd_addr(__offs__))
+#define ocd_writew(__val__, __offs__) \
+       __raw_writew((__val__), ocd_addr(__offs__))
+#define ocd_writeb(__val__, __offs__) \
+       __raw_writeb((__val__), ocd_addr(__offs__))
+
+/* TITAN register access - 32 bit-wide only */
+#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__))
+#define titan_writel(__val__, __offs__) \
+       __raw_writel((__val__), titan_addr(__offs__))
+
+/* Protect access to shared TITAN registers */
+extern spinlock_t titan_lock;
+extern int titan_irqflags;
+#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags)
+#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags)
+
+#endif /* !defined(_ASM_RM9K_OCD_H) */
diff --git a/include/asm-mips/sn/fru.h b/include/asm-mips/sn/fru.h
new file mode 100644 (file)
index 0000000..b3e3606
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ * Derived from IRIX <sys/SN/SN0/sn0_fru.h>
+ *
+ * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc.
+ * Copyright (C) 1999, 2006 Ralf Baechle (ralf@linux-mips)
+ */
+#ifndef __ASM_SN_FRU_H
+#define __ASM_SN_FRU_H
+
+#define MAX_DIMMS                      8        /* max # of dimm banks */
+#define MAX_PCIDEV                     8        /* max # of pci devices on a pci bus */
+
+typedef unsigned char confidence_t;
+
+typedef struct kf_mem_s {
+       confidence_t km_confidence; /* confidence level that the memory is bad
+                                    * is this necessary ?
+                                    */
+       confidence_t km_dimm[MAX_DIMMS];
+                                   /* confidence level that dimm[i] is bad
+                                    *I think this is the right number
+                                    */
+
+} kf_mem_t;
+
+typedef struct kf_cpu_s {
+       confidence_t    kc_confidence; /* confidence level that cpu is bad */
+       confidence_t    kc_icache; /* confidence level that instr. cache is bad */
+       confidence_t    kc_dcache; /* confidence level that data   cache is bad */
+       confidence_t    kc_scache; /* confidence level that sec.   cache is bad */
+       confidence_t    kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */
+} kf_cpu_t;
+
+typedef struct kf_pci_bus_s {
+       confidence_t    kpb_belief;     /* confidence level  that the  pci bus is bad */
+       confidence_t    kpb_pcidev_belief[MAX_PCIDEV];
+                                       /* confidence level that the pci dev is bad */
+} kf_pci_bus_t;
+
+#endif /* __ASM_SN_FRU_H */
diff --git a/include/asm-mips/vr41xx/irq.h b/include/asm-mips/vr41xx/irq.h
new file mode 100644 (file)
index 0000000..d315dfb
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * include/asm-mips/vr41xx/irq.h
+ *
+ * Interrupt numbers for NEC VR4100 series.
+ *
+ * Copyright (C) 1999 Michael Klar
+ * Copyright (C) 2001, 2002 Paul Mundt
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ * Copyright (C) 2002 TimeSys Corp.
+ * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef __NEC_VR41XX_IRQ_H
+#define __NEC_VR41XX_IRQ_H
+
+/*
+ * CPU core Interrupt Numbers
+ */
+#define MIPS_CPU_IRQ_BASE      0
+#define MIPS_CPU_IRQ(x)                (MIPS_CPU_IRQ_BASE + (x))
+#define MIPS_SOFTINT0_IRQ      MIPS_CPU_IRQ(0)
+#define MIPS_SOFTINT1_IRQ      MIPS_CPU_IRQ(1)
+#define INT0_IRQ               MIPS_CPU_IRQ(2)
+#define INT1_IRQ               MIPS_CPU_IRQ(3)
+#define INT2_IRQ               MIPS_CPU_IRQ(4)
+#define INT3_IRQ               MIPS_CPU_IRQ(5)
+#define INT4_IRQ               MIPS_CPU_IRQ(6)
+#define TIMER_IRQ              MIPS_CPU_IRQ(7)
+
+/*
+ * SYINT1 Interrupt Numbers
+ */
+#define SYSINT1_IRQ_BASE       8
+#define SYSINT1_IRQ(x)         (SYSINT1_IRQ_BASE + (x))
+#define BATTRY_IRQ             SYSINT1_IRQ(0)
+#define POWER_IRQ              SYSINT1_IRQ(1)
+#define RTCLONG1_IRQ           SYSINT1_IRQ(2)
+#define ELAPSEDTIME_IRQ                SYSINT1_IRQ(3)
+/* RFU */
+#define PIU_IRQ                        SYSINT1_IRQ(5)
+#define AIU_IRQ                        SYSINT1_IRQ(6)
+#define KIU_IRQ                        SYSINT1_IRQ(7)
+#define GIUINT_IRQ             SYSINT1_IRQ(8)
+#define SIU_IRQ                        SYSINT1_IRQ(9)
+#define BUSERR_IRQ             SYSINT1_IRQ(10)
+#define SOFTINT_IRQ            SYSINT1_IRQ(11)
+#define CLKRUN_IRQ             SYSINT1_IRQ(12)
+#define DOZEPIU_IRQ            SYSINT1_IRQ(13)
+#define SYSINT1_IRQ_LAST       DOZEPIU_IRQ
+
+/*
+ * SYSINT2 Interrupt Numbers
+ */
+#define SYSINT2_IRQ_BASE       24
+#define SYSINT2_IRQ(x)         (SYSINT2_IRQ_BASE + (x))
+#define RTCLONG2_IRQ           SYSINT2_IRQ(0)
+#define LED_IRQ                        SYSINT2_IRQ(1)
+#define HSP_IRQ                        SYSINT2_IRQ(2)
+#define TCLOCK_IRQ             SYSINT2_IRQ(3)
+#define FIR_IRQ                        SYSINT2_IRQ(4)
+#define CEU_IRQ                        SYSINT2_IRQ(4)  /* same number as FIR_IRQ */
+#define DSIU_IRQ               SYSINT2_IRQ(5)
+#define PCI_IRQ                        SYSINT2_IRQ(6)
+#define SCU_IRQ                        SYSINT2_IRQ(7)
+#define CSI_IRQ                        SYSINT2_IRQ(8)
+#define BCU_IRQ                        SYSINT2_IRQ(9)
+#define ETHERNET_IRQ           SYSINT2_IRQ(10)
+#define SYSINT2_IRQ_LAST       ETHERNET_IRQ
+
+/*
+ * GIU Interrupt Numbers
+ */
+#define GIU_IRQ_BASE           40
+#define GIU_IRQ(x)             (GIU_IRQ_BASE + (x))    /* IRQ 40-71 */
+#define GIU_IRQ_LAST           GIU_IRQ(31)
+
+/*
+ * VRC4173 Interrupt Numbers
+ */
+#define VRC4173_IRQ_BASE       72
+#define VRC4173_IRQ(x)         (VRC4173_IRQ_BASE + (x))
+#define VRC4173_USB_IRQ                VRC4173_IRQ(0)
+#define VRC4173_PCMCIA2_IRQ    VRC4173_IRQ(1)
+#define VRC4173_PCMCIA1_IRQ    VRC4173_IRQ(2)
+#define VRC4173_PS2CH2_IRQ     VRC4173_IRQ(3)
+#define VRC4173_PS2CH1_IRQ     VRC4173_IRQ(4)
+#define VRC4173_PIU_IRQ                VRC4173_IRQ(5)
+#define VRC4173_AIU_IRQ                VRC4173_IRQ(6)
+#define VRC4173_KIU_IRQ                VRC4173_IRQ(7)
+#define VRC4173_GIU_IRQ                VRC4173_IRQ(8)
+#define VRC4173_AC97_IRQ       VRC4173_IRQ(9)
+#define VRC4173_AC97INT1_IRQ   VRC4173_IRQ(10)
+/* RFU */
+#define VRC4173_DOZEPIU_IRQ    VRC4173_IRQ(13)
+#define VRC4173_IRQ_LAST       VRC4173_DOZEPIU_IRQ
+
+#endif /* __NEC_VR41XX_IRQ_H */
diff --git a/include/asm-parisc/Kbuild b/include/asm-parisc/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
new file mode 100644 (file)
index 0000000..9827849
--- /dev/null
@@ -0,0 +1,41 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += auxvec.h
+header-y += ioctls.h
+header-y += mman.h
+header-y += sembuf.h
+header-y += siginfo.h
+header-y += stat.h
+header-y += errno.h
+header-y += ipcbuf.h
+header-y += msgbuf.h
+header-y += shmbuf.h
+header-y += socket.h
+header-y += termbits.h
+header-y += fcntl.h
+header-y += ipc.h
+header-y += poll.h
+header-y += shmparam.h
+header-y += sockios.h
+header-y += ucontext.h
+header-y += ioctl.h
+header-y += linkage.h
+header-y += resource.h
+header-y += sigcontext.h
+header-y += statfs.h
+
+unifdef-y += a.out.h
+unifdef-y += asm-compat.h
+unifdef-y += bootx.h
+unifdef-y += byteorder.h
+unifdef-y += cputable.h
+unifdef-y += elf.h
+unifdef-y += nvram.h
+unifdef-y += param.h
+unifdef-y += posix_types.h
+unifdef-y += ptrace.h
+unifdef-y += seccomp.h
+unifdef-y += signal.h
+unifdef-y += termios.h
+unifdef-y += types.h
+unifdef-y += unistd.h
diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h
new file mode 100644 (file)
index 0000000..d905b66
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * MPC86xx Internal Memory Map
+ *
+ * Author: Jeff Brown
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __ASM_POWERPC_IMMAP_86XX_H__
+#define __ASM_POWERPC_IMMAP_86XX_H__
+#ifdef __KERNEL__
+
+/* Eventually this should define all the IO block registers in 86xx */
+
+/* PCI Registers */
+typedef struct ccsr_pci {
+       uint    cfg_addr;       /* 0x.000 - PCI Configuration Address Register */
+       uint    cfg_data;       /* 0x.004 - PCI Configuration Data Register */
+       uint    int_ack;        /* 0x.008 - PCI Interrupt Acknowledge Register */
+       char    res1[3060];
+       uint    potar0;         /* 0x.c00 - PCI Outbound Transaction Address Register 0 */
+       uint    potear0;        /* 0x.c04 - PCI Outbound Translation Extended Address Register 0 */
+       uint    powbar0;        /* 0x.c08 - PCI Outbound Window Base Address Register 0 */
+       char    res2[4];
+       uint    powar0;         /* 0x.c10 - PCI Outbound Window Attributes Register 0 */
+       char    res3[12];
+       uint    potar1;         /* 0x.c20 - PCI Outbound Transaction Address Register 1 */
+       uint    potear1;        /* 0x.c24 - PCI Outbound Translation Extended Address Register 1 */
+       uint    powbar1;        /* 0x.c28 - PCI Outbound Window Base Address Register 1 */
+       char    res4[4];
+       uint    powar1;         /* 0x.c30 - PCI Outbound Window Attributes Register 1 */
+       char    res5[12];
+       uint    potar2;         /* 0x.c40 - PCI Outbound Transaction Address Register 2 */
+       uint    potear2;        /* 0x.c44 - PCI Outbound Translation Extended Address Register 2 */
+       uint    powbar2;        /* 0x.c48 - PCI Outbound Window Base Address Register 2 */
+       char    res6[4];
+       uint    powar2;         /* 0x.c50 - PCI Outbound Window Attributes Register 2 */
+       char    res7[12];
+       uint    potar3;         /* 0x.c60 - PCI Outbound Transaction Address Register 3 */
+       uint    potear3;        /* 0x.c64 - PCI Outbound Translation Extended Address Register 3 */
+       uint    powbar3;        /* 0x.c68 - PCI Outbound Window Base Address Register 3 */
+       char    res8[4];
+       uint    powar3;         /* 0x.c70 - PCI Outbound Window Attributes Register 3 */
+       char    res9[12];
+       uint    potar4;         /* 0x.c80 - PCI Outbound Transaction Address Register 4 */
+       uint    potear4;        /* 0x.c84 - PCI Outbound Translation Extended Address Register 4 */
+       uint    powbar4;        /* 0x.c88 - PCI Outbound Window Base Address Register 4 */
+       char    res10[4];
+       uint    powar4;         /* 0x.c90 - PCI Outbound Window Attributes Register 4 */
+       char    res11[268];
+       uint    pitar3;         /* 0x.da0 - PCI Inbound Translation Address Register 3  */
+       char    res12[4];
+       uint    piwbar3;        /* 0x.da8 - PCI Inbound Window Base Address Register 3 */
+       uint    piwbear3;       /* 0x.dac - PCI Inbound Window Base Extended Address Register 3 */
+       uint    piwar3;         /* 0x.db0 - PCI Inbound Window Attributes Register 3 */
+       char    res13[12];
+       uint    pitar2;         /* 0x.dc0 - PCI Inbound Translation Address Register 2  */
+       char    res14[4];
+       uint    piwbar2;        /* 0x.dc8 - PCI Inbound Window Base Address Register 2 */
+       uint    piwbear2;       /* 0x.dcc - PCI Inbound Window Base Extended Address Register 2 */
+       uint    piwar2;         /* 0x.dd0 - PCI Inbound Window Attributes Register 2 */
+       char    res15[12];
+       uint    pitar1;         /* 0x.de0 - PCI Inbound Translation Address Register 1  */
+       char    res16[4];
+       uint    piwbar1;        /* 0x.de8 - PCI Inbound Window Base Address Register 1 */
+       char    res17[4];
+       uint    piwar1;         /* 0x.df0 - PCI Inbound Window Attributes Register 1 */
+       char    res18[12];
+       uint    err_dr;         /* 0x.e00 - PCI Error Detect Register */
+       uint    err_cap_dr;     /* 0x.e04 - PCI Error Capture Disable Register */
+       uint    err_en;         /* 0x.e08 - PCI Error Enable Register */
+       uint    err_attrib;     /* 0x.e0c - PCI Error Attributes Capture Register */
+       uint    err_addr;       /* 0x.e10 - PCI Error Address Capture Register */
+       uint    err_ext_addr;   /* 0x.e14 - PCI Error Extended Address Capture Register */
+       uint    err_dl;         /* 0x.e18 - PCI Error Data Low Capture Register */
+       uint    err_dh;         /* 0x.e1c - PCI Error Data High Capture Register */
+       uint    gas_timr;       /* 0x.e20 - PCI Gasket Timer Register */
+       uint    pci_timr;       /* 0x.e24 - PCI Timer Register */
+       char    res19[472];
+} ccsr_pci_t;
+
+/* PCI Express Registers */
+typedef struct ccsr_pex {
+       uint    pex_config_addr;        /* 0x.000 - PCI Express Configuration Address Register */
+       uint    pex_config_data;        /* 0x.004 - PCI Express Configuration Data Register */
+       char    res1[4];
+       uint    pex_otb_cpl_tor;        /* 0x.00c - PCI Express Outbound completion timeout register */
+       uint    pex_conf_tor;           /* 0x.010 - PCI Express configuration timeout register */
+       char    res2[12];
+       uint    pex_pme_mes_dr;         /* 0x.020 - PCI Express PME and message detect register */
+       uint    pex_pme_mes_disr;       /* 0x.024 - PCI Express PME and message disable register */
+       uint    pex_pme_mes_ier;        /* 0x.028 - PCI Express PME and message interrupt enable register */
+       uint    pex_pmcr;               /* 0x.02c - PCI Express power management command register */
+       char    res3[3024];
+       uint    pexotar0;               /* 0x.c00 - PCI Express outbound translation address register 0 */
+       uint    pexotear0;              /* 0x.c04 - PCI Express outbound translation extended address register 0*/
+       char    res4[8];
+       uint    pexowar0;               /* 0x.c10 - PCI Express outbound window attributes register 0*/
+       char    res5[12];
+       uint    pexotar1;               /* 0x.c20 - PCI Express outbound translation address register 1 */
+       uint    pexotear1;              /* 0x.c24 - PCI Express outbound translation extended address register 1*/
+       uint    pexowbar1;              /* 0x.c28 - PCI Express outbound window base address register 1*/
+       char    res6[4];
+       uint    pexowar1;               /* 0x.c30 - PCI Express outbound window attributes register 1*/
+       char    res7[12];
+       uint    pexotar2;               /* 0x.c40 - PCI Express outbound translation address register 2 */
+       uint    pexotear2;              /* 0x.c44 - PCI Express outbound translation extended address register 2*/
+       uint    pexowbar2;              /* 0x.c48 - PCI Express outbound window base address register 2*/
+       char    res8[4];
+       uint    pexowar2;               /* 0x.c50 - PCI Express outbound window attributes register 2*/
+       char    res9[12];
+       uint    pexotar3;               /* 0x.c60 - PCI Express outbound translation address register 3 */
+       uint    pexotear3;              /* 0x.c64 - PCI Express outbound translation extended address register 3*/
+       uint    pexowbar3;              /* 0x.c68 - PCI Express outbound window base address register 3*/
+       char    res10[4];
+       uint    pexowar3;               /* 0x.c70 - PCI Express outbound window attributes register 3*/
+       char    res11[12];
+       uint    pexotar4;               /* 0x.c80 - PCI Express outbound translation address register 4 */
+       uint    pexotear4;              /* 0x.c84 - PCI Express outbound translation extended address register 4*/
+       uint    pexowbar4;              /* 0x.c88 - PCI Express outbound window base address register 4*/
+       char    res12[4];
+       uint    pexowar4;               /* 0x.c90 - PCI Express outbound window attributes register 4*/
+       char    res13[12];
+       char    res14[256];
+       uint    pexitar3;               /* 0x.da0 - PCI Express inbound translation address register 3 */
+       char    res15[4];
+       uint    pexiwbar3;              /* 0x.da8 - PCI Express inbound window base address register 3 */
+       uint    pexiwbear3;             /* 0x.dac - PCI Express inbound window base extended address register 3 */
+       uint    pexiwar3;               /* 0x.db0 - PCI Express inbound window attributes register 3 */
+       char    res16[12];
+       uint    pexitar2;               /* 0x.dc0 - PCI Express inbound translation address register 2 */
+       char    res17[4];
+       uint    pexiwbar2;              /* 0x.dc8 - PCI Express inbound window base address register 2 */
+       uint    pexiwbear2;             /* 0x.dcc - PCI Express inbound window base extended address register 2 */
+       uint    pexiwar2;               /* 0x.dd0 - PCI Express inbound window attributes register 2 */
+       char    res18[12];
+       uint    pexitar1;               /* 0x.de0 - PCI Express inbound translation address register 2 */
+       char    res19[4];
+       uint    pexiwbar1;              /* 0x.de8 - PCI Express inbound window base address register 2 */
+       uint    pexiwbear1;             /* 0x.dec - PCI Express inbound window base extended address register 2 */
+       uint    pexiwar1;               /* 0x.df0 - PCI Express inbound window attributes register 2 */
+       char    res20[12];
+       uint    pex_err_dr;             /* 0x.e00 - PCI Express error detect register */
+       char    res21[4];
+       uint    pex_err_en;             /* 0x.e08 - PCI Express error interrupt enable register */
+       char    res22[4];
+       uint    pex_err_disr;           /* 0x.e10 - PCI Express error disable register */
+       char    res23[12];
+       uint    pex_err_cap_stat;       /* 0x.e20 - PCI Express error capture status register */
+       char    res24[4];
+       uint    pex_err_cap_r0;         /* 0x.e28 - PCI Express error capture register 0 */
+       uint    pex_err_cap_r1;         /* 0x.e2c - PCI Express error capture register 0 */
+       uint    pex_err_cap_r2;         /* 0x.e30 - PCI Express error capture register 0 */
+       uint    pex_err_cap_r3;         /* 0x.e34 - PCI Express error capture register 0 */
+} ccsr_pex_t;
+
+/* Global Utility Registers */
+typedef struct ccsr_guts {
+       uint    porpllsr;       /* 0x.0000 - POR PLL Ratio Status Register */
+       uint    porbmsr;        /* 0x.0004 - POR Boot Mode Status Register */
+       uint    porimpscr;      /* 0x.0008 - POR I/O Impedance Status and Control Register */
+       uint    pordevsr;       /* 0x.000c - POR I/O Device Status Register */
+       uint    pordbgmsr;      /* 0x.0010 - POR Debug Mode Status Register */
+       char    res1[12];
+       uint    gpporcr;        /* 0x.0020 - General-Purpose POR Configuration Register */
+       char    res2[12];
+       uint    gpiocr;         /* 0x.0030 - GPIO Control Register */
+       char    res3[12];
+       uint    gpoutdr;        /* 0x.0040 - General-Purpose Output Data Register */
+       char    res4[12];
+       uint    gpindr;         /* 0x.0050 - General-Purpose Input Data Register */
+       char    res5[12];
+       uint    pmuxcr;         /* 0x.0060 - Alternate Function Signal Multiplex Control */
+       char    res6[12];
+       uint    devdisr;        /* 0x.0070 - Device Disable Control */
+       char    res7[12];
+       uint    powmgtcsr;      /* 0x.0080 - Power Management Status and Control Register */
+       char    res8[12];
+       uint    mcpsumr;        /* 0x.0090 - Machine Check Summary Register */
+       char    res9[12];
+       uint    pvr;            /* 0x.00a0 - Processor Version Register */
+       uint    svr;            /* 0x.00a4 - System Version Register */
+       char    res10[3416];
+       uint    clkocr;         /* 0x.0e00 - Clock Out Select Register */
+       char    res11[12];
+       uint    ddrdllcr;       /* 0x.0e10 - DDR DLL Control Register */
+       char    res12[12];
+       uint    lbcdllcr;       /* 0x.0e20 - LBC DLL Control Register */
+       char    res13[61916];
+} ccsr_guts_t;
+
+#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/irqflags.h b/include/asm-powerpc/irqflags.h
new file mode 100644 (file)
index 0000000..7970cba
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * include/asm-powerpc/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() macros from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+/*
+ * Get definitions for raw_local_save_flags(x), etc.
+ */
+#include <asm-powerpc/hw_irq.h>
+
+/*
+ * Do the CPU's IRQ-state tracing from assembly code. We call a
+ * C function, so save all the C-clobbered registers:
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
+
+#else
+# define TRACE_IRQS_ON
+# define TRACE_IRQS_OFF
+#endif
+
+#endif
diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h
new file mode 100644 (file)
index 0000000..0edbfe1
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _ASM_POWERPC_ISERIES_IOMMU_H
+#define _ASM_POWERPC_ISERIES_IOMMU_H
+
+/*
+ * Copyright (C) 2005  Stephen Rothwell, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330,
+ * Boston, MA  02111-1307  USA
+ */
+
+struct device_node;
+struct iommu_table;
+
+/* Creates table for an individual device node */
+extern void iommu_devnode_init_iSeries(struct device_node *dn);
+
+/* Get table parameters from HV */
+extern void iommu_table_getparms_iSeries(unsigned long busno,
+               unsigned char slotno, unsigned char virtbus,
+               struct iommu_table *tbl);
+
+#endif /* _ASM_POWERPC_ISERIES_IOMMU_H */
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
new file mode 100644 (file)
index 0000000..b85df45
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * MPC86xx definitions
+ *
+ * Author: Jeff Brown
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_POWERPC_MPC86xx_H__
+#define __ASM_POWERPC_MPC86xx_H__
+
+#include <asm/mmu.h>
+
+#ifdef CONFIG_PPC_86xx
+
+#define _IO_BASE        isa_io_base
+#define _ISA_MEM_BASE   isa_mem_base
+#ifdef CONFIG_PCI
+#define PCI_DRAM_OFFSET pci_dram_offset
+#endif
+
+#define CPU0_BOOT_RELEASE 0x01000000
+#define CPU1_BOOT_RELEASE 0x02000000
+#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
+#define MCM_PORT_CONFIG_OFFSET 0x1010
+
+/* Offset from CCSRBAR */
+#define MPC86xx_MCM_OFFSET      (0x00000)
+#define MPC86xx_MCM_SIZE        (0x02000)
+
+#endif /* CONFIG_PPC_86xx */
+#endif /* __ASM_POWERPC_MPC86xx_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h
new file mode 100644 (file)
index 0000000..300c458
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Defines an spu hypervisor abstraction layer.
+ *
+ *  Copyright 2006 Sony 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; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_SPU_PRIV1_H)
+#define _SPU_PRIV1_H
+#if defined(__KERNEL__)
+
+struct spu;
+
+/* access to priv1 registers */
+
+struct spu_priv1_ops
+{
+       void (*int_mask_and) (struct spu *spu, int class, u64 mask);
+       void (*int_mask_or) (struct spu *spu, int class, u64 mask);
+       void (*int_mask_set) (struct spu *spu, int class, u64 mask);
+       u64 (*int_mask_get) (struct spu *spu, int class);
+       void (*int_stat_clear) (struct spu *spu, int class, u64 stat);
+       u64 (*int_stat_get) (struct spu *spu, int class);
+       void (*cpu_affinity_set) (struct spu *spu, int cpu);
+       u64 (*mfc_dar_get) (struct spu *spu);
+       u64 (*mfc_dsisr_get) (struct spu *spu);
+       void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr);
+       void (*mfc_sdr_set) (struct spu *spu, u64 sdr);
+       void (*mfc_sr1_set) (struct spu *spu, u64 sr1);
+       u64 (*mfc_sr1_get) (struct spu *spu);
+       void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id);
+       u64 (*mfc_tclass_id_get) (struct spu *spu);
+       void (*tlb_invalidate) (struct spu *spu);
+       void (*resource_allocation_groupID_set) (struct spu *spu, u64 id);
+       u64 (*resource_allocation_groupID_get) (struct spu *spu);
+       void (*resource_allocation_enable_set) (struct spu *spu, u64 enable);
+       u64 (*resource_allocation_enable_get) (struct spu *spu);
+};
+
+extern const struct spu_priv1_ops* spu_priv1_ops;
+
+static inline void
+spu_int_mask_and (struct spu *spu, int class, u64 mask)
+{
+       spu_priv1_ops->int_mask_and(spu, class, mask);
+}
+
+static inline void
+spu_int_mask_or (struct spu *spu, int class, u64 mask)
+{
+       spu_priv1_ops->int_mask_or(spu, class, mask);
+}
+
+static inline void
+spu_int_mask_set (struct spu *spu, int class, u64 mask)
+{
+       spu_priv1_ops->int_mask_set(spu, class, mask);
+}
+
+static inline u64
+spu_int_mask_get (struct spu *spu, int class)
+{
+       return spu_priv1_ops->int_mask_get(spu, class);
+}
+
+static inline void
+spu_int_stat_clear (struct spu *spu, int class, u64 stat)
+{
+       spu_priv1_ops->int_stat_clear(spu, class, stat);
+}
+
+static inline u64
+spu_int_stat_get (struct spu *spu, int class)
+{
+       return spu_priv1_ops->int_stat_get (spu, class);
+}
+
+static inline void
+spu_cpu_affinity_set (struct spu *spu, int cpu)
+{
+       spu_priv1_ops->cpu_affinity_set(spu, cpu);
+}
+
+static inline u64
+spu_mfc_dar_get (struct spu *spu)
+{
+       return spu_priv1_ops->mfc_dar_get(spu);
+}
+
+static inline u64
+spu_mfc_dsisr_get (struct spu *spu)
+{
+       return spu_priv1_ops->mfc_dsisr_get(spu);
+}
+
+static inline void
+spu_mfc_dsisr_set (struct spu *spu, u64 dsisr)
+{
+       spu_priv1_ops->mfc_dsisr_set(spu, dsisr);
+}
+
+static inline void
+spu_mfc_sdr_set (struct spu *spu, u64 sdr)
+{
+       spu_priv1_ops->mfc_sdr_set(spu, sdr);
+}
+
+static inline void
+spu_mfc_sr1_set (struct spu *spu, u64 sr1)
+{
+       spu_priv1_ops->mfc_sr1_set(spu, sr1);
+}
+
+static inline u64
+spu_mfc_sr1_get (struct spu *spu)
+{
+       return spu_priv1_ops->mfc_sr1_get(spu);
+}
+
+static inline void
+spu_mfc_tclass_id_set (struct spu *spu, u64 tclass_id)
+{
+       spu_priv1_ops->mfc_tclass_id_set(spu, tclass_id);
+}
+
+static inline u64
+spu_mfc_tclass_id_get (struct spu *spu)
+{
+       return spu_priv1_ops->mfc_tclass_id_get(spu);
+}
+
+static inline void
+spu_tlb_invalidate (struct spu *spu)
+{
+       spu_priv1_ops->tlb_invalidate(spu);
+}
+
+static inline void
+spu_resource_allocation_groupID_set (struct spu *spu, u64 id)
+{
+       spu_priv1_ops->resource_allocation_groupID_set(spu, id);
+}
+
+static inline u64
+spu_resource_allocation_groupID_get (struct spu *spu)
+{
+       return spu_priv1_ops->resource_allocation_groupID_get(spu);
+}
+
+static inline void
+spu_resource_allocation_enable_set (struct spu *spu, u64 enable)
+{
+       spu_priv1_ops->resource_allocation_enable_set(spu, enable);
+}
+
+static inline u64
+spu_resource_allocation_enable_get (struct spu *spu)
+{
+       return spu_priv1_ops->resource_allocation_enable_get(spu);
+}
+
+/* The declarations folowing are put here for convenience
+ * and only intended to be used by the platform setup code
+ * for initializing spu_priv1_ops.
+ */
+
+extern const struct spu_priv1_ops spu_priv1_mmio_ops;
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
new file mode 100644 (file)
index 0000000..607c1e0
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * List of powerpc syscalls. For the meaning of the _SPU suffix see
+ * arch/powerpc/platforms/cell/spu_callbacks.c
+ */
+
+SYSCALL(restart_syscall)
+SYSCALL(exit)
+PPC_SYS(fork)
+SYSCALL_SPU(read)
+SYSCALL_SPU(write)
+COMPAT_SYS_SPU(open)
+SYSCALL_SPU(close)
+COMPAT_SYS_SPU(waitpid)
+COMPAT_SYS_SPU(creat)
+SYSCALL_SPU(link)
+SYSCALL_SPU(unlink)
+COMPAT_SYS(execve)
+SYSCALL_SPU(chdir)
+COMPAT_SYS_SPU(time)
+SYSCALL_SPU(mknod)
+SYSCALL_SPU(chmod)
+SYSCALL_SPU(lchown)
+SYSCALL(ni_syscall)
+OLDSYS(stat)
+SYSX_SPU(sys_lseek,ppc32_lseek,sys_lseek)
+SYSCALL_SPU(getpid)
+COMPAT_SYS(mount)
+SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount)
+SYSCALL_SPU(setuid)
+SYSCALL_SPU(getuid)
+COMPAT_SYS_SPU(stime)
+COMPAT_SYS(ptrace)
+SYSCALL_SPU(alarm)
+OLDSYS(fstat)
+COMPAT_SYS(pause)
+COMPAT_SYS(utime)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(access)
+COMPAT_SYS_SPU(nice)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(sync)
+COMPAT_SYS_SPU(kill)
+SYSCALL_SPU(rename)
+COMPAT_SYS_SPU(mkdir)
+SYSCALL_SPU(rmdir)
+SYSCALL_SPU(dup)
+SYSCALL_SPU(pipe)
+COMPAT_SYS_SPU(times)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(brk)
+SYSCALL_SPU(setgid)
+SYSCALL_SPU(getgid)
+SYSCALL(signal)
+SYSCALL_SPU(geteuid)
+SYSCALL_SPU(getegid)
+SYSCALL(acct)
+SYSCALL(umount)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(ioctl)
+COMPAT_SYS_SPU(fcntl)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(setpgid)
+SYSCALL(ni_syscall)
+SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
+COMPAT_SYS_SPU(umask)
+SYSCALL_SPU(chroot)
+SYSCALL(ustat)
+SYSCALL_SPU(dup2)
+SYSCALL_SPU(getppid)
+SYSCALL_SPU(getpgrp)
+SYSCALL_SPU(setsid)
+SYS32ONLY(sigaction)
+SYSCALL_SPU(sgetmask)
+COMPAT_SYS_SPU(ssetmask)
+SYSCALL_SPU(setreuid)
+SYSCALL_SPU(setregid)
+SYS32ONLY(sigsuspend)
+COMPAT_SYS(sigpending)
+COMPAT_SYS_SPU(sethostname)
+COMPAT_SYS_SPU(setrlimit)
+COMPAT_SYS(old_getrlimit)
+COMPAT_SYS_SPU(getrusage)
+COMPAT_SYS_SPU(gettimeofday)
+COMPAT_SYS_SPU(settimeofday)
+COMPAT_SYS_SPU(getgroups)
+COMPAT_SYS_SPU(setgroups)
+SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select)
+SYSCALL_SPU(symlink)
+OLDSYS(lstat)
+COMPAT_SYS_SPU(readlink)
+SYSCALL(uselib)
+SYSCALL(swapon)
+SYSCALL(reboot)
+SYSX(sys_ni_syscall,old32_readdir,old_readdir)
+SYSCALL_SPU(mmap)
+SYSCALL_SPU(munmap)
+SYSCALL_SPU(truncate)
+SYSCALL_SPU(ftruncate)
+SYSCALL_SPU(fchmod)
+SYSCALL_SPU(fchown)
+COMPAT_SYS_SPU(getpriority)
+COMPAT_SYS_SPU(setpriority)
+SYSCALL(ni_syscall)
+COMPAT_SYS(statfs)
+COMPAT_SYS(fstatfs)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(socketcall)
+COMPAT_SYS_SPU(syslog)
+COMPAT_SYS_SPU(setitimer)
+COMPAT_SYS_SPU(getitimer)
+COMPAT_SYS_SPU(newstat)
+COMPAT_SYS_SPU(newlstat)
+COMPAT_SYS_SPU(newfstat)
+SYSX(sys_ni_syscall,sys_uname,sys_uname)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(vhangup)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(wait4)
+SYSCALL(swapoff)
+COMPAT_SYS_SPU(sysinfo)
+COMPAT_SYS(ipc)
+SYSCALL_SPU(fsync)
+SYS32ONLY(sigreturn)
+PPC_SYS(clone)
+COMPAT_SYS_SPU(setdomainname)
+PPC_SYS_SPU(newuname)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(adjtimex)
+SYSCALL_SPU(mprotect)
+SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask)
+SYSCALL(ni_syscall)
+SYSCALL(init_module)
+SYSCALL(delete_module)
+SYSCALL(ni_syscall)
+SYSCALL(quotactl)
+COMPAT_SYS_SPU(getpgid)
+SYSCALL_SPU(fchdir)
+SYSCALL_SPU(bdflush)
+COMPAT_SYS(sysfs)
+SYSX_SPU(ppc64_personality,ppc64_personality,sys_personality)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(setfsuid)
+SYSCALL_SPU(setfsgid)
+SYSCALL_SPU(llseek)
+COMPAT_SYS_SPU(getdents)
+SYSX_SPU(sys_select,ppc32_select,ppc_select)
+SYSCALL_SPU(flock)
+SYSCALL_SPU(msync)
+COMPAT_SYS_SPU(readv)
+COMPAT_SYS_SPU(writev)
+COMPAT_SYS_SPU(getsid)
+SYSCALL_SPU(fdatasync)
+COMPAT_SYS(sysctl)
+SYSCALL_SPU(mlock)
+SYSCALL_SPU(munlock)
+SYSCALL_SPU(mlockall)
+SYSCALL_SPU(munlockall)
+COMPAT_SYS_SPU(sched_setparam)
+COMPAT_SYS_SPU(sched_getparam)
+COMPAT_SYS_SPU(sched_setscheduler)
+COMPAT_SYS_SPU(sched_getscheduler)
+SYSCALL_SPU(sched_yield)
+COMPAT_SYS_SPU(sched_get_priority_max)
+COMPAT_SYS_SPU(sched_get_priority_min)
+COMPAT_SYS_SPU(sched_rr_get_interval)
+COMPAT_SYS_SPU(nanosleep)
+SYSCALL_SPU(mremap)
+SYSCALL_SPU(setresuid)
+SYSCALL_SPU(getresuid)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(poll)
+COMPAT_SYS(nfsservctl)
+SYSCALL_SPU(setresgid)
+SYSCALL_SPU(getresgid)
+COMPAT_SYS_SPU(prctl)
+COMPAT_SYS(rt_sigreturn)
+COMPAT_SYS(rt_sigaction)
+COMPAT_SYS(rt_sigprocmask)
+COMPAT_SYS(rt_sigpending)
+COMPAT_SYS(rt_sigtimedwait)
+COMPAT_SYS(rt_sigqueueinfo)
+COMPAT_SYS(rt_sigsuspend)
+COMPAT_SYS_SPU(pread64)
+COMPAT_SYS_SPU(pwrite64)
+SYSCALL_SPU(chown)
+SYSCALL_SPU(getcwd)
+SYSCALL_SPU(capget)
+SYSCALL_SPU(capset)
+COMPAT_SYS(sigaltstack)
+SYSX_SPU(sys_sendfile64,compat_sys_sendfile,sys_sendfile)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+PPC_SYS(vfork)
+COMPAT_SYS_SPU(getrlimit)
+COMPAT_SYS_SPU(readahead)
+SYS32ONLY(mmap2)
+SYS32ONLY(truncate64)
+SYS32ONLY(ftruncate64)
+SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
+SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
+SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
+SYSCALL(pciconfig_read)
+SYSCALL(pciconfig_write)
+SYSCALL(pciconfig_iobase)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(getdents64)
+SYSCALL_SPU(pivot_root)
+SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64)
+SYSCALL_SPU(madvise)
+SYSCALL_SPU(mincore)
+SYSCALL_SPU(gettid)
+SYSCALL_SPU(tkill)
+SYSCALL_SPU(setxattr)
+SYSCALL_SPU(lsetxattr)
+SYSCALL_SPU(fsetxattr)
+SYSCALL_SPU(getxattr)
+SYSCALL_SPU(lgetxattr)
+SYSCALL_SPU(fgetxattr)
+SYSCALL_SPU(listxattr)
+SYSCALL_SPU(llistxattr)
+SYSCALL_SPU(flistxattr)
+SYSCALL_SPU(removexattr)
+SYSCALL_SPU(lremovexattr)
+SYSCALL_SPU(fremovexattr)
+COMPAT_SYS_SPU(futex)
+COMPAT_SYS_SPU(sched_setaffinity)
+COMPAT_SYS_SPU(sched_getaffinity)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYS32ONLY(sendfile64)
+COMPAT_SYS_SPU(io_setup)
+SYSCALL_SPU(io_destroy)
+COMPAT_SYS_SPU(io_getevents)
+COMPAT_SYS_SPU(io_submit)
+SYSCALL_SPU(io_cancel)
+SYSCALL(set_tid_address)
+SYSX_SPU(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
+SYSCALL(exit_group)
+SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
+SYSCALL_SPU(epoll_create)
+SYSCALL_SPU(epoll_ctl)
+SYSCALL_SPU(epoll_wait)
+SYSCALL_SPU(remap_file_pages)
+SYSX_SPU(sys_timer_create,compat_sys_timer_create,sys_timer_create)
+COMPAT_SYS_SPU(timer_settime)
+COMPAT_SYS_SPU(timer_gettime)
+SYSCALL_SPU(timer_getoverrun)
+SYSCALL_SPU(timer_delete)
+COMPAT_SYS_SPU(clock_settime)
+COMPAT_SYS_SPU(clock_gettime)
+COMPAT_SYS_SPU(clock_getres)
+COMPAT_SYS_SPU(clock_nanosleep)
+SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
+COMPAT_SYS_SPU(tgkill)
+COMPAT_SYS_SPU(utimes)
+COMPAT_SYS_SPU(statfs64)
+COMPAT_SYS_SPU(fstatfs64)
+SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
+PPC_SYS_SPU(rtas)
+OLDSYS(debug_setcontext)
+SYSX(sys_vserver, sys32_vserver, sys_vserver)
+SYSCALL(ni_syscall)
+COMPAT_SYS(mbind)
+COMPAT_SYS(get_mempolicy)
+COMPAT_SYS(set_mempolicy)
+COMPAT_SYS(mq_open)
+SYSCALL(mq_unlink)
+COMPAT_SYS(mq_timedsend)
+COMPAT_SYS(mq_timedreceive)
+COMPAT_SYS(mq_notify)
+COMPAT_SYS(mq_getsetattr)
+COMPAT_SYS(kexec_load)
+COMPAT_SYS(add_key)
+COMPAT_SYS(request_key)
+COMPAT_SYS(keyctl)
+COMPAT_SYS(waitid)
+COMPAT_SYS(ioprio_set)
+COMPAT_SYS(ioprio_get)
+SYSCALL(inotify_init)
+SYSCALL(inotify_add_watch)
+SYSCALL(inotify_rm_watch)
+SYSCALL(spu_run)
+SYSCALL(spu_create)
+COMPAT_SYS(pselect6)
+COMPAT_SYS(ppoll)
+SYSCALL_SPU(unshare)
+SYSCALL_SPU(splice)
+SYSCALL_SPU(tee)
+SYSCALL_SPU(vmsplice)
+COMPAT_SYS_SPU(openat)
+SYSCALL_SPU(mkdirat)
+SYSCALL_SPU(mknodat)
+SYSCALL_SPU(fchownat)
+COMPAT_SYS_SPU(futimesat)
+SYSX_SPU(sys_newfstatat, sys_fstatat64, sys_fstatat64)
+SYSCALL_SPU(unlinkat)
+SYSCALL_SPU(renameat)
+SYSCALL_SPU(linkat)
+SYSCALL_SPU(symlinkat)
+SYSCALL_SPU(readlinkat)
+SYSCALL_SPU(fchmodat)
+SYSCALL_SPU(faccessat)
+COMPAT_SYS_SPU(get_robust_list)
+COMPAT_SYS_SPU(set_robust_list)
diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h
new file mode 100644 (file)
index 0000000..60a8c39
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * Definitions for the M48Txx and mc146818 series of Time of day/Real Time
+ * Clock chips.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips.
+ * Purpose is to make one generic file that handles all of these chips instead
+ * of every platform implementing the same code over & over again.
+ */
+
+#ifndef __PPC_KERNEL_TODC_H
+#define __PPC_KERNEL_TODC_H
+
+typedef struct {
+       uint rtc_type;          /* your particular chip */
+
+       /*
+        * Following are the addresses of the AS0, AS1, and DATA registers
+        * of these chips.  Note that these are board-specific.
+        */
+       unsigned int nvram_as0;
+       unsigned int nvram_as1;
+       unsigned int nvram_data;
+
+       /*
+        * Define bits to stop external set of regs from changing so
+        * the chip can be read/written reliably.
+        */
+       unsigned char enable_read;
+       unsigned char enable_write;
+
+       /*
+        * Following is the number of AS0 address bits.  This is normally
+        * 8 but some bad hardware routes address lines incorrectly.
+        */
+       int as0_bits;
+
+       int nvram_size; /* Size of NVRAM on chip */
+       int sw_flags;   /* Software control flags */
+
+       /* Following are the register offsets for the particular chip */
+       int year;
+       int month;
+       int day_of_month;
+       int day_of_week;
+       int hours;
+       int minutes;
+       int seconds;
+       int control_b;
+       int control_a;
+       int watchdog;
+       int interrupts;
+       int alarm_date;
+       int alarm_hour;
+       int alarm_minutes;
+       int alarm_seconds;
+       int century;
+       int flags;
+
+       /*
+        * Some RTC chips have their NVRAM buried behind a addr/data pair of
+        * regs on the first level/clock registers.  The following fields
+        * are the addresses for those addr/data regs.
+        */
+       int nvram_addr_reg;
+       int nvram_data_reg;
+} todc_info_t;
+
+/*
+ * Define the types of TODC/RTC variants that are supported in
+ * arch/ppc/kernel/todc_time.c
+ * Make a new one of these for any chip somehow differs from what's already
+ * defined.  That way, if you ever need to put in code to touch those
+ * bits/registers in todc_time.c, you can put it inside an
+ * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break
+ * anyone else.
+ */
+#define TODC_TYPE_MK48T35              1
+#define TODC_TYPE_MK48T37              2
+#define TODC_TYPE_MK48T59              3
+#define TODC_TYPE_DS1693               4       /* Dallas DS1693 RTC */
+#define TODC_TYPE_DS1743               5       /* Dallas DS1743 RTC */
+#define TODC_TYPE_DS1746               6       /* Dallas DS1746 RTC */
+#define TODC_TYPE_DS1747               7       /* Dallas DS1747 RTC */
+#define TODC_TYPE_DS1501               8       /* Dallas DS1501 RTC */
+#define TODC_TYPE_DS1643               9       /* Dallas DS1643 RTC */
+#define TODC_TYPE_PC97307              10      /* PC97307 internal RTC */
+#define TODC_TYPE_DS1557               11      /* Dallas DS1557 RTC */
+#define TODC_TYPE_DS17285              12      /* Dallas DS17285 RTC */
+#define TODC_TYPE_DS1553               13      /* Dallas DS1553 RTC */
+#define TODC_TYPE_MC146818             100     /* Leave room for m48txx's */
+
+/*
+ * Bit to clear/set to enable reads/writes to the chip
+ */
+#define TODC_MK48TXX_CNTL_A_R          0x40
+#define TODC_MK48TXX_CNTL_A_W          0x80
+#define TODC_MK48TXX_DAY_CB            0x80
+
+#define TODC_DS1501_CNTL_B_TE          0x80
+
+/*
+ * Define flag bits used by todc routines.
+ */
+#define TODC_FLAG_2_LEVEL_NVRAM                0x00000001
+
+/*
+ * Define the values for the various RTC's that should to into the todc_info
+ * table.
+ * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only
+ * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set.
+ */
+#define TODC_TYPE_MK48T35_NVRAM_SIZE           0x7ff8
+#define TODC_TYPE_MK48T35_SW_FLAGS             0
+#define TODC_TYPE_MK48T35_YEAR                 0x7fff
+#define TODC_TYPE_MK48T35_MONTH                        0x7ffe
+#define TODC_TYPE_MK48T35_DOM                  0x7ffd  /* Day of Month */
+#define TODC_TYPE_MK48T35_DOW                  0x7ffc  /* Day of Week */
+#define TODC_TYPE_MK48T35_HOURS                        0x7ffb
+#define TODC_TYPE_MK48T35_MINUTES              0x7ffa
+#define TODC_TYPE_MK48T35_SECONDS              0x7ff9
+#define TODC_TYPE_MK48T35_CNTL_B               0x7ff9
+#define TODC_TYPE_MK48T35_CNTL_A               0x7ff8
+#define TODC_TYPE_MK48T35_WATCHDOG             0x0000
+#define TODC_TYPE_MK48T35_INTERRUPTS           0x0000
+#define TODC_TYPE_MK48T35_ALARM_DATE           0x0000
+#define TODC_TYPE_MK48T35_ALARM_HOUR           0x0000
+#define TODC_TYPE_MK48T35_ALARM_MINUTES                0x0000
+#define TODC_TYPE_MK48T35_ALARM_SECONDS                0x0000
+#define TODC_TYPE_MK48T35_CENTURY              0x0000
+#define TODC_TYPE_MK48T35_FLAGS                        0x0000
+#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG       0
+#define TODC_TYPE_MK48T35_NVRAM_DATA_REG       0
+
+#define TODC_TYPE_MK48T37_NVRAM_SIZE           0x7ff0
+#define TODC_TYPE_MK48T37_SW_FLAGS             0
+#define TODC_TYPE_MK48T37_YEAR                 0x7fff
+#define TODC_TYPE_MK48T37_MONTH                        0x7ffe
+#define TODC_TYPE_MK48T37_DOM                  0x7ffd  /* Day of Month */
+#define TODC_TYPE_MK48T37_DOW                  0x7ffc  /* Day of Week */
+#define TODC_TYPE_MK48T37_HOURS                        0x7ffb
+#define TODC_TYPE_MK48T37_MINUTES              0x7ffa
+#define TODC_TYPE_MK48T37_SECONDS              0x7ff9
+#define TODC_TYPE_MK48T37_CNTL_B               0x7ff9
+#define TODC_TYPE_MK48T37_CNTL_A               0x7ff8
+#define TODC_TYPE_MK48T37_WATCHDOG             0x7ff7
+#define TODC_TYPE_MK48T37_INTERRUPTS           0x7ff6
+#define TODC_TYPE_MK48T37_ALARM_DATE           0x7ff5
+#define TODC_TYPE_MK48T37_ALARM_HOUR           0x7ff4
+#define TODC_TYPE_MK48T37_ALARM_MINUTES                0x7ff3
+#define TODC_TYPE_MK48T37_ALARM_SECONDS                0x7ff2
+#define TODC_TYPE_MK48T37_CENTURY              0x7ff1
+#define TODC_TYPE_MK48T37_FLAGS                        0x7ff0
+#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG       0
+#define TODC_TYPE_MK48T37_NVRAM_DATA_REG       0
+
+#define TODC_TYPE_MK48T59_NVRAM_SIZE           0x1ff0
+#define TODC_TYPE_MK48T59_SW_FLAGS             0
+#define TODC_TYPE_MK48T59_YEAR                 0x1fff
+#define TODC_TYPE_MK48T59_MONTH                        0x1ffe
+#define TODC_TYPE_MK48T59_DOM                  0x1ffd  /* Day of Month */
+#define TODC_TYPE_MK48T59_DOW                  0x1ffc  /* Day of Week */
+#define TODC_TYPE_MK48T59_HOURS                        0x1ffb
+#define TODC_TYPE_MK48T59_MINUTES              0x1ffa
+#define TODC_TYPE_MK48T59_SECONDS              0x1ff9
+#define TODC_TYPE_MK48T59_CNTL_B               0x1ff9
+#define TODC_TYPE_MK48T59_CNTL_A               0x1ff8
+#define TODC_TYPE_MK48T59_WATCHDOG             0x1fff
+#define TODC_TYPE_MK48T59_INTERRUPTS           0x1fff
+#define TODC_TYPE_MK48T59_ALARM_DATE           0x1fff
+#define TODC_TYPE_MK48T59_ALARM_HOUR           0x1fff
+#define TODC_TYPE_MK48T59_ALARM_MINUTES                0x1fff
+#define TODC_TYPE_MK48T59_ALARM_SECONDS                0x1fff
+#define TODC_TYPE_MK48T59_CENTURY              0x1fff
+#define TODC_TYPE_MK48T59_FLAGS                        0x1fff
+#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG       0
+#define TODC_TYPE_MK48T59_NVRAM_DATA_REG       0
+
+#define TODC_TYPE_DS1501_NVRAM_SIZE    0x100
+#define TODC_TYPE_DS1501_SW_FLAGS      TODC_FLAG_2_LEVEL_NVRAM
+#define TODC_TYPE_DS1501_YEAR          (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06)
+#define TODC_TYPE_DS1501_MONTH         (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05)
+#define TODC_TYPE_DS1501_DOM           (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04)
+#define TODC_TYPE_DS1501_DOW           (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03)
+#define TODC_TYPE_DS1501_HOURS         (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02)
+#define TODC_TYPE_DS1501_MINUTES       (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01)
+#define TODC_TYPE_DS1501_SECONDS       (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00)
+#define TODC_TYPE_DS1501_CNTL_B                (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
+#define TODC_TYPE_DS1501_CNTL_A                (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
+#define TODC_TYPE_DS1501_WATCHDOG      (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
+#define TODC_TYPE_DS1501_INTERRUPTS    (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
+#define TODC_TYPE_DS1501_ALARM_DATE    (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b)
+#define TODC_TYPE_DS1501_ALARM_HOUR    (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a)
+#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09)
+#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08)
+#define TODC_TYPE_DS1501_CENTURY       (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07)
+#define TODC_TYPE_DS1501_FLAGS         (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
+#define TODC_TYPE_DS1501_NVRAM_ADDR_REG        0x10
+#define TODC_TYPE_DS1501_NVRAM_DATA_REG        0x13
+
+#define TODC_TYPE_DS1553_NVRAM_SIZE            0x1ff0
+#define TODC_TYPE_DS1553_SW_FLAGS              0
+#define TODC_TYPE_DS1553_YEAR                  0x1fff
+#define TODC_TYPE_DS1553_MONTH                 0x1ffe
+#define TODC_TYPE_DS1553_DOM                   0x1ffd  /* Day of Month */
+#define TODC_TYPE_DS1553_DOW                   0x1ffc  /* Day of Week */
+#define TODC_TYPE_DS1553_HOURS                 0x1ffb
+#define TODC_TYPE_DS1553_MINUTES               0x1ffa
+#define TODC_TYPE_DS1553_SECONDS               0x1ff9
+#define TODC_TYPE_DS1553_CNTL_B                        0x1ff9
+#define TODC_TYPE_DS1553_CNTL_A                        0x1ff8  /* control_a R/W regs */
+#define TODC_TYPE_DS1553_WATCHDOG              0x1ff7
+#define TODC_TYPE_DS1553_INTERRUPTS            0x1ff6
+#define TODC_TYPE_DS1553_ALARM_DATE            0x1ff5
+#define TODC_TYPE_DS1553_ALARM_HOUR            0x1ff4
+#define TODC_TYPE_DS1553_ALARM_MINUTES         0x1ff3
+#define TODC_TYPE_DS1553_ALARM_SECONDS         0x1ff2
+#define TODC_TYPE_DS1553_CENTURY               0x1ff8
+#define TODC_TYPE_DS1553_FLAGS                 0x1ff0
+#define TODC_TYPE_DS1553_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1553_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS1557_NVRAM_SIZE            0x7fff0
+#define TODC_TYPE_DS1557_SW_FLAGS              0
+#define TODC_TYPE_DS1557_YEAR                  0x7ffff
+#define TODC_TYPE_DS1557_MONTH                 0x7fffe
+#define TODC_TYPE_DS1557_DOM                   0x7fffd /* Day of Month */
+#define TODC_TYPE_DS1557_DOW                   0x7fffc /* Day of Week */
+#define TODC_TYPE_DS1557_HOURS                 0x7fffb
+#define TODC_TYPE_DS1557_MINUTES               0x7fffa
+#define TODC_TYPE_DS1557_SECONDS               0x7fff9
+#define TODC_TYPE_DS1557_CNTL_B                        0x7fff9
+#define TODC_TYPE_DS1557_CNTL_A                        0x7fff8 /* control_a R/W regs */
+#define TODC_TYPE_DS1557_WATCHDOG              0x7fff7
+#define TODC_TYPE_DS1557_INTERRUPTS            0x7fff6
+#define TODC_TYPE_DS1557_ALARM_DATE            0x7fff5
+#define TODC_TYPE_DS1557_ALARM_HOUR            0x7fff4
+#define TODC_TYPE_DS1557_ALARM_MINUTES         0x7fff3
+#define TODC_TYPE_DS1557_ALARM_SECONDS         0x7fff2
+#define TODC_TYPE_DS1557_CENTURY               0x7fff8
+#define TODC_TYPE_DS1557_FLAGS                 0x7fff0
+#define TODC_TYPE_DS1557_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1557_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS1643_NVRAM_SIZE            0x1ff8
+#define TODC_TYPE_DS1643_SW_FLAGS              0
+#define TODC_TYPE_DS1643_YEAR                  0x1fff
+#define TODC_TYPE_DS1643_MONTH                 0x1ffe
+#define TODC_TYPE_DS1643_DOM                   0x1ffd  /* Day of Month */
+#define TODC_TYPE_DS1643_DOW                   0x1ffc  /* Day of Week */
+#define TODC_TYPE_DS1643_HOURS                 0x1ffb
+#define TODC_TYPE_DS1643_MINUTES               0x1ffa
+#define TODC_TYPE_DS1643_SECONDS               0x1ff9
+#define TODC_TYPE_DS1643_CNTL_B                        0x1ff9
+#define TODC_TYPE_DS1643_CNTL_A                        0x1ff8  /* control_a R/W regs */
+#define TODC_TYPE_DS1643_WATCHDOG              0x1fff
+#define TODC_TYPE_DS1643_INTERRUPTS            0x1fff
+#define TODC_TYPE_DS1643_ALARM_DATE            0x1fff
+#define TODC_TYPE_DS1643_ALARM_HOUR            0x1fff
+#define TODC_TYPE_DS1643_ALARM_MINUTES         0x1fff
+#define TODC_TYPE_DS1643_ALARM_SECONDS         0x1fff
+#define TODC_TYPE_DS1643_CENTURY               0x1ff8
+#define TODC_TYPE_DS1643_FLAGS                 0x1fff
+#define TODC_TYPE_DS1643_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1643_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS1693_NVRAM_SIZE            0 /* Not handled yet */
+#define TODC_TYPE_DS1693_SW_FLAGS              0
+#define TODC_TYPE_DS1693_YEAR                  0x09
+#define TODC_TYPE_DS1693_MONTH                 0x08
+#define TODC_TYPE_DS1693_DOM                   0x07    /* Day of Month */
+#define TODC_TYPE_DS1693_DOW                   0x06    /* Day of Week */
+#define TODC_TYPE_DS1693_HOURS                 0x04
+#define TODC_TYPE_DS1693_MINUTES               0x02
+#define TODC_TYPE_DS1693_SECONDS               0x00
+#define TODC_TYPE_DS1693_CNTL_B                        0x0b
+#define TODC_TYPE_DS1693_CNTL_A                        0x0a
+#define TODC_TYPE_DS1693_WATCHDOG              0xff
+#define TODC_TYPE_DS1693_INTERRUPTS            0xff
+#define TODC_TYPE_DS1693_ALARM_DATE            0x49
+#define TODC_TYPE_DS1693_ALARM_HOUR            0x05
+#define TODC_TYPE_DS1693_ALARM_MINUTES         0x03
+#define TODC_TYPE_DS1693_ALARM_SECONDS         0x01
+#define TODC_TYPE_DS1693_CENTURY               0x48
+#define TODC_TYPE_DS1693_FLAGS                 0xff
+#define TODC_TYPE_DS1693_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1693_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS1743_NVRAM_SIZE            0x1ff8
+#define TODC_TYPE_DS1743_SW_FLAGS              0
+#define TODC_TYPE_DS1743_YEAR                  0x1fff
+#define TODC_TYPE_DS1743_MONTH                 0x1ffe
+#define TODC_TYPE_DS1743_DOM                   0x1ffd  /* Day of Month */
+#define TODC_TYPE_DS1743_DOW                   0x1ffc  /* Day of Week */
+#define TODC_TYPE_DS1743_HOURS                 0x1ffb
+#define TODC_TYPE_DS1743_MINUTES               0x1ffa
+#define TODC_TYPE_DS1743_SECONDS               0x1ff9
+#define TODC_TYPE_DS1743_CNTL_B                        0x1ff9
+#define TODC_TYPE_DS1743_CNTL_A                        0x1ff8  /* control_a R/W regs */
+#define TODC_TYPE_DS1743_WATCHDOG              0x1fff
+#define TODC_TYPE_DS1743_INTERRUPTS            0x1fff
+#define TODC_TYPE_DS1743_ALARM_DATE            0x1fff
+#define TODC_TYPE_DS1743_ALARM_HOUR            0x1fff
+#define TODC_TYPE_DS1743_ALARM_MINUTES         0x1fff
+#define TODC_TYPE_DS1743_ALARM_SECONDS         0x1fff
+#define TODC_TYPE_DS1743_CENTURY               0x1ff8
+#define TODC_TYPE_DS1743_FLAGS                 0x1fff
+#define TODC_TYPE_DS1743_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1743_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS1746_NVRAM_SIZE            0x1fff8
+#define TODC_TYPE_DS1746_SW_FLAGS              0
+#define TODC_TYPE_DS1746_YEAR                  0x1ffff
+#define TODC_TYPE_DS1746_MONTH                 0x1fffe
+#define TODC_TYPE_DS1746_DOM                   0x1fffd /* Day of Month */
+#define TODC_TYPE_DS1746_DOW                   0x1fffc /* Day of Week */
+#define TODC_TYPE_DS1746_HOURS                 0x1fffb
+#define TODC_TYPE_DS1746_MINUTES               0x1fffa
+#define TODC_TYPE_DS1746_SECONDS               0x1fff9
+#define TODC_TYPE_DS1746_CNTL_B                        0x1fff9
+#define TODC_TYPE_DS1746_CNTL_A                        0x1fff8 /* control_a R/W regs */
+#define TODC_TYPE_DS1746_WATCHDOG              0x00000
+#define TODC_TYPE_DS1746_INTERRUPTS            0x00000
+#define TODC_TYPE_DS1746_ALARM_DATE            0x00000
+#define TODC_TYPE_DS1746_ALARM_HOUR            0x00000
+#define TODC_TYPE_DS1746_ALARM_MINUTES         0x00000
+#define TODC_TYPE_DS1746_ALARM_SECONDS         0x00000
+#define TODC_TYPE_DS1746_CENTURY               0x00000
+#define TODC_TYPE_DS1746_FLAGS                 0x00000
+#define TODC_TYPE_DS1746_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1746_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS1747_NVRAM_SIZE            0x7fff8
+#define TODC_TYPE_DS1747_SW_FLAGS              0
+#define TODC_TYPE_DS1747_YEAR                  0x7ffff
+#define TODC_TYPE_DS1747_MONTH                 0x7fffe
+#define TODC_TYPE_DS1747_DOM                   0x7fffd /* Day of Month */
+#define TODC_TYPE_DS1747_DOW                   0x7fffc /* Day of Week */
+#define TODC_TYPE_DS1747_HOURS                 0x7fffb
+#define TODC_TYPE_DS1747_MINUTES               0x7fffa
+#define TODC_TYPE_DS1747_SECONDS               0x7fff9
+#define TODC_TYPE_DS1747_CNTL_B                        0x7fff9
+#define TODC_TYPE_DS1747_CNTL_A                        0x7fff8 /* control_a R/W regs */
+#define TODC_TYPE_DS1747_WATCHDOG              0x00000
+#define TODC_TYPE_DS1747_INTERRUPTS            0x00000
+#define TODC_TYPE_DS1747_ALARM_DATE            0x00000
+#define TODC_TYPE_DS1747_ALARM_HOUR            0x00000
+#define TODC_TYPE_DS1747_ALARM_MINUTES         0x00000
+#define TODC_TYPE_DS1747_ALARM_SECONDS         0x00000
+#define TODC_TYPE_DS1747_CENTURY               0x00000
+#define TODC_TYPE_DS1747_FLAGS                 0x00000
+#define TODC_TYPE_DS1747_NVRAM_ADDR_REG                0
+#define TODC_TYPE_DS1747_NVRAM_DATA_REG                0
+
+#define TODC_TYPE_DS17285_NVRAM_SIZE           (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */
+#define TODC_TYPE_DS17285_SW_FLAGS             TODC_FLAG_2_LEVEL_NVRAM
+#define TODC_TYPE_DS17285_SECONDS              (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00)
+#define TODC_TYPE_DS17285_ALARM_SECONDS                (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01)
+#define TODC_TYPE_DS17285_MINUTES              (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02)
+#define TODC_TYPE_DS17285_ALARM_MINUTES                (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03)
+#define TODC_TYPE_DS17285_HOURS                        (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04)
+#define TODC_TYPE_DS17285_ALARM_HOUR           (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05)
+#define TODC_TYPE_DS17285_DOW                  (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06)
+#define TODC_TYPE_DS17285_DOM                  (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07)
+#define TODC_TYPE_DS17285_MONTH                        (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08)
+#define TODC_TYPE_DS17285_YEAR                 (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09)
+#define TODC_TYPE_DS17285_CNTL_A               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A)
+#define TODC_TYPE_DS17285_CNTL_B               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B)
+#define TODC_TYPE_DS17285_CNTL_C               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C)
+#define TODC_TYPE_DS17285_CNTL_D               (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D)
+#define TODC_TYPE_DS17285_WATCHDOG             0
+#define TODC_TYPE_DS17285_INTERRUPTS           0
+#define TODC_TYPE_DS17285_ALARM_DATE           0
+#define TODC_TYPE_DS17285_CENTURY              0
+#define TODC_TYPE_DS17285_FLAGS                        0
+#define TODC_TYPE_DS17285_NVRAM_ADDR_REG       0x50
+#define TODC_TYPE_DS17285_NVRAM_DATA_REG       0x53
+
+#define TODC_TYPE_MC146818_NVRAM_SIZE          0       /* XXXX */
+#define TODC_TYPE_MC146818_SW_FLAGS            0
+#define TODC_TYPE_MC146818_YEAR                        0x09
+#define TODC_TYPE_MC146818_MONTH               0x08
+#define TODC_TYPE_MC146818_DOM                 0x07    /* Day of Month */
+#define TODC_TYPE_MC146818_DOW                 0x06    /* Day of Week */
+#define TODC_TYPE_MC146818_HOURS               0x04
+#define TODC_TYPE_MC146818_MINUTES             0x02
+#define TODC_TYPE_MC146818_SECONDS             0x00
+#define TODC_TYPE_MC146818_CNTL_B              0x0a
+#define TODC_TYPE_MC146818_CNTL_A              0x0b    /* control_a R/W regs */
+#define TODC_TYPE_MC146818_WATCHDOG            0
+#define TODC_TYPE_MC146818_INTERRUPTS          0x0c
+#define TODC_TYPE_MC146818_ALARM_DATE          0xff
+#define TODC_TYPE_MC146818_ALARM_HOUR          0x05
+#define TODC_TYPE_MC146818_ALARM_MINUTES       0x03
+#define TODC_TYPE_MC146818_ALARM_SECONDS       0x01
+#define TODC_TYPE_MC146818_CENTURY             0xff
+#define TODC_TYPE_MC146818_FLAGS               0xff
+#define TODC_TYPE_MC146818_NVRAM_ADDR_REG      0
+#define TODC_TYPE_MC146818_NVRAM_DATA_REG      0
+
+#define TODC_TYPE_PC97307_NVRAM_SIZE           0       /* No NVRAM? */
+#define TODC_TYPE_PC97307_SW_FLAGS             0
+#define TODC_TYPE_PC97307_YEAR                 0x09
+#define TODC_TYPE_PC97307_MONTH                        0x08
+#define TODC_TYPE_PC97307_DOM                  0x07    /* Day of Month */
+#define TODC_TYPE_PC97307_DOW                  0x06    /* Day of Week */
+#define TODC_TYPE_PC97307_HOURS                        0x04
+#define TODC_TYPE_PC97307_MINUTES              0x02
+#define TODC_TYPE_PC97307_SECONDS              0x00
+#define TODC_TYPE_PC97307_CNTL_B               0x0a
+#define TODC_TYPE_PC97307_CNTL_A               0x0b    /* control_a R/W regs */
+#define TODC_TYPE_PC97307_WATCHDOG             0x0c
+#define TODC_TYPE_PC97307_INTERRUPTS           0x0d
+#define TODC_TYPE_PC97307_ALARM_DATE           0xff
+#define TODC_TYPE_PC97307_ALARM_HOUR           0x05
+#define TODC_TYPE_PC97307_ALARM_MINUTES                0x03
+#define TODC_TYPE_PC97307_ALARM_SECONDS                0x01
+#define TODC_TYPE_PC97307_CENTURY              0xff
+#define TODC_TYPE_PC97307_FLAGS                        0xff
+#define TODC_TYPE_PC97307_NVRAM_ADDR_REG       0
+#define TODC_TYPE_PC97307_NVRAM_DATA_REG       0
+
+/*
+ * Define macros to allocate and init the todc_info_t table that will
+ * be used by the todc_time.c routines.
+ */
+#define TODC_ALLOC()                                                   \
+       static todc_info_t todc_info_alloc;                             \
+       todc_info_t *todc_info = &todc_info_alloc;
+
+#define TODC_INIT(clock_type, as0, as1, data, bits) {                  \
+       todc_info->rtc_type = clock_type;                               \
+                                                                       \
+       todc_info->nvram_as0 = (unsigned int)(as0);                     \
+       todc_info->nvram_as1 = (unsigned int)(as1);                     \
+       todc_info->nvram_data = (unsigned int)(data);                   \
+                                                                       \
+       todc_info->as0_bits = (bits);                                   \
+                                                                       \
+       todc_info->nvram_size = clock_type ##_NVRAM_SIZE;               \
+       todc_info->sw_flags = clock_type ##_SW_FLAGS;                   \
+                                                                       \
+       todc_info->year = clock_type ##_YEAR;                           \
+       todc_info->month = clock_type ##_MONTH;                         \
+       todc_info->day_of_month = clock_type ##_DOM;                    \
+       todc_info->day_of_week = clock_type ##_DOW;                     \
+       todc_info->hours = clock_type ##_HOURS;                         \
+       todc_info->minutes = clock_type ##_MINUTES;                     \
+       todc_info->seconds = clock_type ##_SECONDS;                     \
+       todc_info->control_b = clock_type ##_CNTL_B;                    \
+       todc_info->control_a = clock_type ##_CNTL_A;                    \
+       todc_info->watchdog = clock_type ##_WATCHDOG;                   \
+       todc_info->interrupts = clock_type ##_INTERRUPTS;               \
+       todc_info->alarm_date = clock_type ##_ALARM_DATE;               \
+       todc_info->alarm_hour = clock_type ##_ALARM_HOUR;               \
+       todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES;         \
+       todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS;         \
+       todc_info->century = clock_type ##_CENTURY;                     \
+       todc_info->flags = clock_type ##_FLAGS;                         \
+                                                                       \
+       todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG;       \
+       todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG;       \
+}
+
+extern todc_info_t *todc_info;
+
+unsigned char todc_direct_read_val(int addr);
+void todc_direct_write_val(int addr, unsigned char val);
+unsigned char todc_m48txx_read_val(int addr);
+void todc_m48txx_write_val(int addr, unsigned char val);
+unsigned char todc_mc146818_read_val(int addr);
+void todc_mc146818_write_val(int addr, unsigned char val);
+
+long todc_time_init(void);
+void todc_get_rtc_time(struct rtc_time *);
+int todc_set_rtc_time(struct rtc_time *);
+void todc_calibrate_decr(void);
+
+#endif                         /* __PPC_KERNEL_TODC_H */
diff --git a/include/asm-powerpc/tracehook.h b/include/asm-powerpc/tracehook.h
new file mode 100644 (file)
index 0000000..2cf5dc3
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Tracing hooks, PowerPC CPU support
+ */
+
+#ifndef _ASM_TRACEHOOK_H
+#define _ASM_TRACEHOOK_H       1
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/*
+ * See linux/tracehook.h for the descriptions of what these need to do.
+ */
+
+#define ARCH_HAS_SINGLE_STEP   (1)
+
+static inline void tracehook_enable_single_step(struct task_struct *task)
+{
+       struct pt_regs *regs = task->thread.regs;
+       if (regs != NULL) {
+#if defined(CONFIG_PPC32) && (defined(CONFIG_40x) || defined(CONFIG_BOOKE))
+               task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
+               regs->msr |= MSR_DE;
+#else
+               regs->msr |= MSR_SE;
+#endif
+       }
+       set_tsk_thread_flag(task, TIF_SINGLESTEP);
+}
+
+static inline void tracehook_disable_single_step(struct task_struct *task)
+{
+       struct pt_regs *regs = task->thread.regs;
+       if (regs != NULL) {
+#if defined(CONFIG_PPC32) && (defined(CONFIG_40x) || defined(CONFIG_BOOKE))
+               task->thread.dbcr0 = 0;
+               regs->msr &= ~MSR_DE;
+#else
+               regs->msr &= ~MSR_SE;
+#endif
+       }
+       clear_tsk_thread_flag(task, TIF_SINGLESTEP);
+}
+
+static inline int tracehook_single_step_enabled(struct task_struct *tsk)
+{
+       return test_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+}
+
+static inline void tracehook_enable_syscall_trace(struct task_struct *tsk)
+{
+       set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_disable_syscall_trace(struct task_struct *tsk)
+{
+       clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_abort_syscall(struct pt_regs *regs)
+{
+       regs->orig_gpr3 = -1L;
+}
+
+
+extern const struct utrace_regset_view utrace_ppc_native_view;
+static inline const struct utrace_regset_view *
+utrace_native_view(struct task_struct *tsk)
+{
+#ifdef CONFIG_PPC64
+       extern const struct utrace_regset_view utrace_ppc32_view;
+
+       if (test_tsk_thread_flag(tsk, TIF_32BIT))
+               return &utrace_ppc32_view;
+#endif
+       return &utrace_ppc_native_view;
+}
+
+
+#endif
diff --git a/include/asm-powerpc/tsi108.h b/include/asm-powerpc/tsi108.h
new file mode 100644 (file)
index 0000000..2c702d3
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * common routine and memory layout for Tundra TSI108(Grendel) host bridge
+ * memory controller.
+ *
+ * Author: Jacob Pan (jacob.pan@freescale.com)
+ *        Alex Bounine (alexandreb@tundra.com)
+ *
+ * Copyright 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __PPC_KERNEL_TSI108_H
+#define __PPC_KERNEL_TSI108_H
+
+#include <asm/pci-bridge.h>
+
+/* Size of entire register space */
+#define TSI108_REG_SIZE                (0x10000)
+
+/* Sizes of register spaces for individual blocks */
+#define TSI108_HLP_SIZE                0x1000
+#define TSI108_PCI_SIZE                0x1000
+#define TSI108_CLK_SIZE                0x1000
+#define TSI108_PB_SIZE         0x1000
+#define TSI108_SD_SIZE         0x1000
+#define TSI108_DMA_SIZE                0x1000
+#define TSI108_ETH_SIZE                0x1000
+#define TSI108_I2C_SIZE                0x400
+#define TSI108_MPIC_SIZE       0x400
+#define TSI108_UART0_SIZE      0x200
+#define TSI108_GPIO_SIZE       0x200
+#define TSI108_UART1_SIZE      0x200
+
+/* Offsets within Tsi108(A) CSR space for individual blocks */
+#define TSI108_HLP_OFFSET      0x0000
+#define TSI108_PCI_OFFSET      0x1000
+#define TSI108_CLK_OFFSET      0x2000
+#define TSI108_PB_OFFSET       0x3000
+#define TSI108_SD_OFFSET       0x4000
+#define TSI108_DMA_OFFSET      0x5000
+#define TSI108_ETH_OFFSET      0x6000
+#define TSI108_I2C_OFFSET      0x7000
+#define TSI108_MPIC_OFFSET     0x7400
+#define TSI108_UART0_OFFSET    0x7800
+#define TSI108_GPIO_OFFSET     0x7A00
+#define TSI108_UART1_OFFSET    0x7C00
+
+/* Tsi108 registers used by common code components */
+#define TSI108_PCI_CSR         (0x004)
+#define TSI108_PCI_IRP_CFG_CTL (0x180)
+#define TSI108_PCI_IRP_STAT    (0x184)
+#define TSI108_PCI_IRP_ENABLE  (0x188)
+#define TSI108_PCI_IRP_INTAD   (0x18C)
+
+#define TSI108_PCI_IRP_STAT_P_INT      (0x00400000)
+#define TSI108_PCI_IRP_ENABLE_P_INT    (0x00400000)
+
+#define TSI108_CG_PWRUP_STATUS (0x234)
+
+#define TSI108_PB_ISR          (0x00C)
+#define TSI108_PB_ERRCS                (0x404)
+#define TSI108_PB_AERR         (0x408)
+
+#define TSI108_PB_ERRCS_ES             (1 << 1)
+#define TSI108_PB_ISR_PBS_RD_ERR       (1 << 8)
+
+#define TSI108_PCI_CFG_BASE_PHYS       (0xfb000000)
+#define TSI108_PCI_CFG_SIZE            (0x01000000)
+/* Global variables */
+
+extern u32 tsi108_pci_cfg_base;
+/* Exported functions */
+
+extern int tsi108_bridge_init(struct pci_controller *hose, uint phys_csr_base);
+extern unsigned long tsi108_get_mem_size(void);
+extern unsigned long tsi108_get_cpu_clk(void);
+extern unsigned long tsi108_get_sdc_clk(void);
+extern int tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfn,
+                                     int offset, int len, u32 val);
+extern int tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn,
+                                    int offset, int len, u32 * val);
+extern void tsi108_clear_pci_error(u32 pci_cfg_base);
+
+extern phys_addr_t get_csrbase(void);
+
+typedef struct {
+       u32 regs;               /* hw registers base address */
+       u32 phyregs;            /* phy registers base address */
+       u16 phy;                /* phy address */
+       u16 irq_num;            /* irq number */
+       u8 mac_addr[6];         /* phy mac address */
+} hw_info;
+
+extern u32 get_vir_csrbase(void);
+extern u32 tsi108_csr_vir_base;
+
+extern inline u32 tsi108_read_reg(u32 reg_offset)
+{
+       return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset));
+}
+
+extern inline void tsi108_write_reg(u32 reg_offset, u32 val)
+{
+       out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val);
+}
+
+#endif                         /* __PPC_KERNEL_TSI108_H */
diff --git a/include/asm-powerpc/tsi108_irq.h b/include/asm-powerpc/tsi108_irq.h
new file mode 100644 (file)
index 0000000..3e4d04e
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2005 Tundra Semiconductor Corp.
+ * Alex Bounine, <alexandreb at tundra.com).
+ *
+ * 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
+ */
+
+/*
+ * definitions for interrupt controller initialization and external interrupt
+ * demultiplexing on TSI108EMU/SVB boards.
+ */
+
+#ifndef _ASM_PPC_TSI108_IRQ_H
+#define _ASM_PPC_TSI108_IRQ_H
+
+/*
+ * Tsi108 interrupts
+ */
+#ifndef TSI108_IRQ_REG_BASE
+#define TSI108_IRQ_REG_BASE            0
+#endif
+
+#define TSI108_IRQ(x)          (TSI108_IRQ_REG_BASE + (x))
+
+#define TSI108_MAX_VECTORS     (36 + 4)        /* 36 sources + PCI INT demux */
+#define MAX_TASK_PRIO  0xF
+
+#define TSI108_IRQ_SPURIOUS    (TSI108_MAX_VECTORS)
+
+#define DEFAULT_PRIO_LVL       10      /* initial priority level */
+
+/* Interrupt vectors assignment to external and internal
+ * sources of requests. */
+
+/* EXTERNAL INTERRUPT SOURCES */
+
+#define IRQ_TSI108_EXT_INT0    TSI108_IRQ(0)   /* External Source at INT[0] */
+#define IRQ_TSI108_EXT_INT1    TSI108_IRQ(1)   /* External Source at INT[1] */
+#define IRQ_TSI108_EXT_INT2    TSI108_IRQ(2)   /* External Source at INT[2] */
+#define IRQ_TSI108_EXT_INT3    TSI108_IRQ(3)   /* External Source at INT[3] */
+
+/* INTERNAL INTERRUPT SOURCES */
+
+#define IRQ_TSI108_RESERVED0   TSI108_IRQ(4)   /* Reserved IRQ */
+#define IRQ_TSI108_RESERVED1   TSI108_IRQ(5)   /* Reserved IRQ */
+#define IRQ_TSI108_RESERVED2   TSI108_IRQ(6)   /* Reserved IRQ */
+#define IRQ_TSI108_RESERVED3   TSI108_IRQ(7)   /* Reserved IRQ */
+#define IRQ_TSI108_DMA0                TSI108_IRQ(8)   /* DMA0 */
+#define IRQ_TSI108_DMA1                TSI108_IRQ(9)   /* DMA1 */
+#define IRQ_TSI108_DMA2                TSI108_IRQ(10)  /* DMA2 */
+#define IRQ_TSI108_DMA3                TSI108_IRQ(11)  /* DMA3 */
+#define IRQ_TSI108_UART0       TSI108_IRQ(12)  /* UART0 */
+#define IRQ_TSI108_UART1       TSI108_IRQ(13)  /* UART1 */
+#define IRQ_TSI108_I2C         TSI108_IRQ(14)  /* I2C */
+#define IRQ_TSI108_GPIO                TSI108_IRQ(15)  /* GPIO */
+#define IRQ_TSI108_GIGE0       TSI108_IRQ(16)  /* GIGE0 */
+#define IRQ_TSI108_GIGE1       TSI108_IRQ(17)  /* GIGE1 */
+#define IRQ_TSI108_RESERVED4   TSI108_IRQ(18)  /* Reserved IRQ */
+#define IRQ_TSI108_HLP         TSI108_IRQ(19)  /* HLP */
+#define IRQ_TSI108_SDRAM       TSI108_IRQ(20)  /* SDC */
+#define IRQ_TSI108_PROC_IF     TSI108_IRQ(21)  /* Processor IF */
+#define IRQ_TSI108_RESERVED5   TSI108_IRQ(22)  /* Reserved IRQ */
+#define IRQ_TSI108_PCI         TSI108_IRQ(23)  /* PCI/X block */
+
+#define IRQ_TSI108_MBOX0       TSI108_IRQ(24)  /* Mailbox 0 register */
+#define IRQ_TSI108_MBOX1       TSI108_IRQ(25)  /* Mailbox 1 register */
+#define IRQ_TSI108_MBOX2       TSI108_IRQ(26)  /* Mailbox 2 register */
+#define IRQ_TSI108_MBOX3       TSI108_IRQ(27)  /* Mailbox 3 register */
+
+#define IRQ_TSI108_DBELL0      TSI108_IRQ(28)  /* Doorbell 0 */
+#define IRQ_TSI108_DBELL1      TSI108_IRQ(29)  /* Doorbell 1 */
+#define IRQ_TSI108_DBELL2      TSI108_IRQ(30)  /* Doorbell 2 */
+#define IRQ_TSI108_DBELL3      TSI108_IRQ(31)  /* Doorbell 3 */
+
+#define IRQ_TSI108_TIMER0      TSI108_IRQ(32)  /* Global Timer 0 */
+#define IRQ_TSI108_TIMER1      TSI108_IRQ(33)  /* Global Timer 1 */
+#define IRQ_TSI108_TIMER2      TSI108_IRQ(34)  /* Global Timer 2 */
+#define IRQ_TSI108_TIMER3      TSI108_IRQ(35)  /* Global Timer 3 */
+
+/*
+ * PCI bus INTA# - INTD# lines demultiplexor
+ */
+#define IRQ_PCI_INTAD_BASE     TSI108_IRQ(36)
+#define IRQ_PCI_INTA           (IRQ_PCI_INTAD_BASE + 0)
+#define IRQ_PCI_INTB           (IRQ_PCI_INTAD_BASE + 1)
+#define IRQ_PCI_INTC           (IRQ_PCI_INTAD_BASE + 2)
+#define IRQ_PCI_INTD           (IRQ_PCI_INTAD_BASE + 3)
+#define NUM_PCI_IRQS           (4)
+
+/* number of entries in vector dispatch table */
+#define IRQ_TSI108_TAB_SIZE    (TSI108_MAX_VECTORS + 1)
+
+/* Mapping of MPIC outputs to processors' interrupt pins */
+
+#define IDIR_INT_OUT0          0x1
+#define IDIR_INT_OUT1          0x2
+#define IDIR_INT_OUT2          0x4
+#define IDIR_INT_OUT3          0x8
+
+/*---------------------------------------------------------------
+ * IRQ line configuration parameters */
+
+/* Interrupt delivery modes */
+typedef enum {
+       TSI108_IRQ_DIRECTED,
+       TSI108_IRQ_DISTRIBUTED,
+} TSI108_IRQ_MODE;
+#endif                         /*  _ASM_PPC_TSI108_IRQ_H */
diff --git a/include/asm-s390/Kbuild b/include/asm-s390/Kbuild
new file mode 100644 (file)
index 0000000..14158a4
--- /dev/null
@@ -0,0 +1,11 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += dasd.h
+header-y += qeth.h
+header-y += tape390.h
+header-y += ucontext.h
+header-y += vtoc.h
+header-y += z90crypt.h
+
+unifdef-y += cmb.h
+unifdef-y += debug.h
diff --git a/include/asm-s390/irqflags.h b/include/asm-s390/irqflags.h
new file mode 100644 (file)
index 0000000..3b566a5
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  include/asm-s390/irqflags.h
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#ifndef __ASM_IRQFLAGS_H
+#define __ASM_IRQFLAGS_H
+
+#ifdef __KERNEL__
+
+/* interrupt control.. */
+#define raw_local_irq_enable() ({ \
+       unsigned long  __dummy; \
+       __asm__ __volatile__ ( \
+               "stosm 0(%1),0x03" \
+               : "=m" (__dummy) : "a" (&__dummy) : "memory" ); \
+       })
+
+#define raw_local_irq_disable() ({ \
+       unsigned long __flags; \
+       __asm__ __volatile__ ( \
+               "stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \
+       __flags; \
+       })
+
+#define raw_local_save_flags(x)                                                        \
+do {                                                                           \
+       typecheck(unsigned long, x);                                            \
+       __asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) );  \
+} while (0)
+
+#define raw_local_irq_restore(x)                                               \
+do {                                                                           \
+       typecheck(unsigned long, x);                                            \
+       __asm__ __volatile__("ssm   0(%0)" : : "a" (&x), "m" (x) : "memory");   \
+} while (0)
+
+#define raw_irqs_disabled()            \
+({                                     \
+       unsigned long flags;            \
+       raw_local_save_flags(flags);    \
+       !((flags >> __FLAG_SHIFT) & 3); \
+})
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return !((flags >> __FLAG_SHIFT) & 3);
+}
+
+/* For spinlocks etc */
+#define raw_local_irq_save(x)  ((x) = raw_local_irq_disable())
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_IRQFLAGS_H */
diff --git a/include/asm-s390/tracehook.h b/include/asm-s390/tracehook.h
new file mode 100644 (file)
index 0000000..8fc8c38
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Tracing hooks, s390/s390x support.
+ */
+
+#ifndef _ASM_TRACEHOOK_H
+#define _ASM_TRACEHOOK_H       1
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/*
+ * See linux/tracehook.h for the descriptions of what these need to do.
+ */
+
+#define ARCH_HAS_SINGLE_STEP   (1)
+
+/* These three are defined in arch/s390/kernel/ptrace.c.  */
+void tracehook_enable_single_step(struct task_struct *tsk);
+void tracehook_disable_single_step(struct task_struct *tsk);
+int tracehook_single_step_enabled(struct task_struct *tsk);
+
+
+static inline void tracehook_enable_syscall_trace(struct task_struct *tsk)
+{
+       set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_disable_syscall_trace(struct task_struct *tsk)
+{
+       clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_abort_syscall(struct pt_regs *regs)
+{
+       regs->gprs[2] = -1L;
+}
+
+
+extern const struct utrace_regset_view utrace_s390_native_view;
+static inline const struct utrace_regset_view *
+utrace_native_view(struct task_struct *tsk)
+{
+#ifdef CONFIG_COMPAT
+        extern const struct utrace_regset_view utrace_s390_compat_view;
+
+        if (test_tsk_thread_flag(tsk, TIF_31BIT))
+                return &utrace_s390_compat_view;
+#endif
+        return &utrace_s390_native_view;
+}
+
+
+#endif
diff --git a/include/asm-s390/z90crypt.h b/include/asm-s390/z90crypt.h
new file mode 100644 (file)
index 0000000..31a2439
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *  include/asm-s390/z90crypt.h
+ *
+ *  z90crypt 1.3.3 (user-visible header)
+ *
+ *  Copyright (C)  2001, 2005 IBM Corporation
+ *  Author(s): Robert Burroughs
+ *             Eric Rossman (edrossma@us.ibm.com)
+ *
+ *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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 __ASM_S390_Z90CRYPT_H
+#define __ASM_S390_Z90CRYPT_H
+#include <linux/ioctl.h>
+
+#define z90crypt_VERSION 1
+#define z90crypt_RELEASE 3     // 2 = PCIXCC, 3 = rewrite for coding standards
+#define z90crypt_VARIANT 3     // 3 = CEX2A support
+
+/**
+ * struct ica_rsa_modexpo
+ *
+ * Requirements:
+ * - outputdatalength is at least as large as inputdatalength.
+ * - All key parts are right justified in their fields, padded on
+ *   the left with zeroes.
+ * - length(b_key) = inputdatalength
+ * - length(n_modulus) = inputdatalength
+ */
+struct ica_rsa_modexpo {
+       char __user *   inputdata;
+       unsigned int    inputdatalength;
+       char __user *   outputdata;
+       unsigned int    outputdatalength;
+       char __user *   b_key;
+       char __user *   n_modulus;
+};
+
+/**
+ * struct ica_rsa_modexpo_crt
+ *
+ * Requirements:
+ * - inputdatalength is even.
+ * - outputdatalength is at least as large as inputdatalength.
+ * - All key parts are right justified in their fields, padded on
+ *   the left with zeroes.
+ * - length(bp_key)    = inputdatalength/2 + 8
+ * - length(bq_key)    = inputdatalength/2
+ * - length(np_key)    = inputdatalength/2 + 8
+ * - length(nq_key)    = inputdatalength/2
+ * - length(u_mult_inv) = inputdatalength/2 + 8
+ */
+struct ica_rsa_modexpo_crt {
+       char __user *   inputdata;
+       unsigned int    inputdatalength;
+       char __user *   outputdata;
+       unsigned int    outputdatalength;
+       char __user *   bp_key;
+       char __user *   bq_key;
+       char __user *   np_prime;
+       char __user *   nq_prime;
+       char __user *   u_mult_inv;
+};
+
+#define Z90_IOCTL_MAGIC 'z'  // NOTE:  Need to allocate from linux folks
+
+/**
+ * Interface notes:
+ *
+ * The ioctl()s which are implemented (along with relevant details)
+ * are:
+ *
+ *   ICARSAMODEXPO
+ *     Perform an RSA operation using a Modulus-Exponent pair
+ *     This takes an ica_rsa_modexpo struct as its arg.
+ *
+ *     NOTE: please refer to the comments preceding this structure
+ *           for the implementation details for the contents of the
+ *           block
+ *
+ *   ICARSACRT
+ *     Perform an RSA operation using a Chinese-Remainder Theorem key
+ *     This takes an ica_rsa_modexpo_crt struct as its arg.
+ *
+ *     NOTE: please refer to the comments preceding this structure
+ *           for the implementation details for the contents of the
+ *           block
+ *
+ *   Z90STAT_TOTALCOUNT
+ *     Return an integer count of all device types together.
+ *
+ *   Z90STAT_PCICACOUNT
+ *     Return an integer count of all PCICAs.
+ *
+ *   Z90STAT_PCICCCOUNT
+ *     Return an integer count of all PCICCs.
+ *
+ *   Z90STAT_PCIXCCMCL2COUNT
+ *     Return an integer count of all MCL2 PCIXCCs.
+ *
+ *   Z90STAT_PCIXCCMCL3COUNT
+ *     Return an integer count of all MCL3 PCIXCCs.
+ *
+ *   Z90STAT_CEX2CCOUNT
+ *     Return an integer count of all CEX2Cs.
+ *
+ *   Z90STAT_CEX2ACOUNT
+ *     Return an integer count of all CEX2As.
+ *
+ *   Z90STAT_REQUESTQ_COUNT
+ *     Return an integer count of the number of entries waiting to be
+ *     sent to a device.
+ *
+ *   Z90STAT_PENDINGQ_COUNT
+ *     Return an integer count of the number of entries sent to a
+ *     device awaiting the reply.
+ *
+ *   Z90STAT_TOTALOPEN_COUNT
+ *     Return an integer count of the number of open file handles.
+ *
+ *   Z90STAT_DOMAIN_INDEX
+ *     Return the integer value of the Cryptographic Domain.
+ *
+ *   Z90STAT_STATUS_MASK
+ *     Return an 64 element array of unsigned chars for the status of
+ *     all devices.
+ *       0x01: PCICA
+ *       0x02: PCICC
+ *       0x03: PCIXCC_MCL2
+ *       0x04: PCIXCC_MCL3
+ *       0x05: CEX2C
+ *       0x06: CEX2A
+ *       0x0d: device is disabled via the proc filesystem
+ *
+ *   Z90STAT_QDEPTH_MASK
+ *     Return an 64 element array of unsigned chars for the queue
+ *     depth of all devices.
+ *
+ *   Z90STAT_PERDEV_REQCNT
+ *     Return an 64 element array of unsigned integers for the number
+ *     of successfully completed requests per device since the device
+ *     was detected and made available.
+ *
+ *   ICAZ90STATUS (deprecated)
+ *     Return some device driver status in a ica_z90_status struct
+ *     This takes an ica_z90_status struct as its arg.
+ *
+ *     NOTE: this ioctl() is deprecated, and has been replaced with
+ *           single ioctl()s for each type of status being requested
+ *
+ *   Z90STAT_PCIXCCCOUNT (deprecated)
+ *     Return an integer count of all PCIXCCs (MCL2 + MCL3).
+ *     This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
+ *     MCL2 PCIXCCs.
+ *
+ *   Z90QUIESCE (not recommended)
+ *     Quiesce the driver.  This is intended to stop all new
+ *     requests from being processed.  Its use is NOT recommended,
+ *     except in circumstances where there is no other way to stop
+ *     callers from accessing the driver.  Its original use was to
+ *     allow the driver to be "drained" of work in preparation for
+ *     a system shutdown.
+ *
+ *     NOTE: once issued, this ban on new work cannot be undone
+ *           except by unloading and reloading the driver.
+ */
+
+/**
+ * Supported ioctl calls
+ */
+#define ICARSAMODEXPO  _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
+#define ICARSACRT      _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
+
+/* DEPRECATED status calls (bound for removal at some point) */
+#define ICAZ90STATUS   _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
+#define Z90STAT_PCIXCCCOUNT    _IOR(Z90_IOCTL_MAGIC, 0x43, int)
+
+/* unrelated to ICA callers */
+#define Z90QUIESCE     _IO(Z90_IOCTL_MAGIC, 0x11)
+
+/* New status calls */
+#define Z90STAT_TOTALCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x40, int)
+#define Z90STAT_PCICACOUNT     _IOR(Z90_IOCTL_MAGIC, 0x41, int)
+#define Z90STAT_PCICCCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x42, int)
+#define Z90STAT_PCIXCCMCL2COUNT        _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
+#define Z90STAT_PCIXCCMCL3COUNT        _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
+#define Z90STAT_CEX2CCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
+#define Z90STAT_CEX2ACOUNT     _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
+#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
+#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
+#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
+#define Z90STAT_DOMAIN_INDEX   _IOR(Z90_IOCTL_MAGIC, 0x47, int)
+#define Z90STAT_STATUS_MASK    _IOR(Z90_IOCTL_MAGIC, 0x48, char[64])
+#define Z90STAT_QDEPTH_MASK    _IOR(Z90_IOCTL_MAGIC, 0x49, char[64])
+#define Z90STAT_PERDEV_REQCNT  _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64])
+
+#endif /* __ASM_S390_Z90CRYPT_H */
diff --git a/include/asm-sh/Kbuild b/include/asm-sh/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-sh64/Kbuild b/include/asm-sh64/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild
new file mode 100644 (file)
index 0000000..c6a55cf
--- /dev/null
@@ -0,0 +1,15 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += apc.h
+header-y += asi.h
+header-y += bpp.h
+header-y += jsflash.h
+header-y += openpromio.h
+header-y += pconf.h
+header-y += reg.h
+header-y += traps.h
+header-y += vfc_ioctls.h
+
+unifdef-y += fbio.h
+unifdef-y += perfctr.h
+unifdef-y += psr.h
diff --git a/include/asm-sparc/of_device.h b/include/asm-sparc/of_device.h
new file mode 100644 (file)
index 0000000..80ea31f
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _ASM_SPARC_OF_DEVICE_H
+#define _ASM_SPARC_OF_DEVICE_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <asm/openprom.h>
+#include <asm/prom.h>
+
+extern struct bus_type ebus_bus_type;
+extern struct bus_type sbus_bus_type;
+extern struct bus_type of_bus_type;
+
+/*
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties.
+ */
+struct of_device
+{
+       struct device_node              *node;
+       struct device                   dev;
+       struct resource                 resource[PROMREG_MAX];
+       unsigned int                    irqs[PROMINTR_MAX];
+       int                             num_irqs;
+
+       void                            *sysdata;
+
+       int                             slot;
+       int                             portid;
+       int                             clock_freq;
+};
+#define        to_of_device(d) container_of(d, struct of_device, dev)
+
+extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
+extern void of_iounmap(void __iomem *base, unsigned long size);
+
+extern struct of_device *of_find_device_by_node(struct device_node *);
+
+extern const struct of_device_id *of_match_device(
+       const struct of_device_id *matches, const struct of_device *dev);
+
+extern struct of_device *of_dev_get(struct of_device *dev);
+extern void of_dev_put(struct of_device *dev);
+
+/*
+ * An of_platform_driver driver is attached to a basic of_device on
+ * the ISA, EBUS, and SBUS busses on sparc64.
+ */
+struct of_platform_driver
+{
+       char                    *name;
+       struct of_device_id     *match_table;
+       struct module           *owner;
+
+       int     (*probe)(struct of_device* dev, const struct of_device_id *match);
+       int     (*remove)(struct of_device* dev);
+
+       int     (*suspend)(struct of_device* dev, pm_message_t state);
+       int     (*resume)(struct of_device* dev);
+       int     (*shutdown)(struct of_device* dev);
+
+       struct device_driver    driver;
+};
+#define        to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
+
+extern int of_register_driver(struct of_platform_driver *drv,
+                             struct bus_type *bus);
+extern void of_unregister_driver(struct of_platform_driver *drv);
+extern int of_device_register(struct of_device *ofdev);
+extern void of_device_unregister(struct of_device *ofdev);
+extern struct of_device *of_platform_device_create(struct device_node *np,
+                                                  const char *bus_id,
+                                                  struct device *parent,
+                                                  struct bus_type *bus);
+extern void of_release_dev(struct device *dev);
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_SPARC_OF_DEVICE_H */
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
new file mode 100644 (file)
index 0000000..86c13dc
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef _SPARC_PROM_H
+#define _SPARC_PROM_H
+#ifdef __KERNEL__
+
+
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC32 by David S. Miller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+
+typedef u32 phandle;
+typedef u32 ihandle;
+
+struct property {
+       char    *name;
+       int     length;
+       void    *value;
+       struct property *next;
+       unsigned long _flags;
+       unsigned int unique_id;
+};
+
+struct device_node {
+       char    *name;
+       char    *type;
+       phandle node;
+       char    *path_component_name;
+       char    *full_name;
+
+       struct  property *properties;
+       struct  property *deadprops; /* removed properties */
+       struct  device_node *parent;
+       struct  device_node *child;
+       struct  device_node *sibling;
+       struct  device_node *next;      /* next device of same type */
+       struct  device_node *allnext;   /* next in list of all nodes */
+       struct  proc_dir_entry *pde;    /* this node's proc directory */
+       struct  kref kref;
+       unsigned long _flags;
+       void    *data;
+       unsigned int unique_id;
+};
+
+/* flag descriptions */
+#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+
+#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
+#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+
+#define OF_BAD_ADDR    ((u64)-1)
+
+static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
+{
+       dn->pde = de;
+}
+
+extern struct device_node *of_find_node_by_name(struct device_node *from,
+       const char *name);
+#define for_each_node_by_name(dn, name) \
+       for (dn = of_find_node_by_name(NULL, name); dn; \
+            dn = of_find_node_by_name(dn, name))
+extern struct device_node *of_find_node_by_type(struct device_node *from,
+       const char *type);
+#define for_each_node_by_type(dn, type) \
+       for (dn = of_find_node_by_type(NULL, type); dn; \
+            dn = of_find_node_by_type(dn, type))
+extern struct device_node *of_find_compatible_node(struct device_node *from,
+       const char *type, const char *compat);
+extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
+extern struct device_node *of_get_parent(const struct device_node *node);
+extern struct device_node *of_get_next_child(const struct device_node *node,
+                                            struct device_node *prev);
+extern struct property *of_find_property(struct device_node *np,
+                                        const char *name,
+                                        int *lenp);
+extern int of_device_is_compatible(struct device_node *device, const char *);
+extern void *of_get_property(struct device_node *node, const char *name,
+                            int *lenp);
+extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
+extern int of_getintprop_default(struct device_node *np,
+                                const char *name,
+                                int def);
+extern int of_n_addr_cells(struct device_node *np);
+extern int of_n_size_cells(struct device_node *np);
+
+extern void prom_build_devicetree(void);
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC_PROM_H */
diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild
new file mode 100644 (file)
index 0000000..a7f4440
--- /dev/null
@@ -0,0 +1,26 @@
+include include/asm-generic/Kbuild.asm
+
+ALTARCH := sparc
+ARCHDEF := defined __sparc__ && defined __arch64__
+ALTARCHDEF := defined __sparc__ && !defined __arch64__
+
+header-y += apb.h
+header-y += asi.h
+header-y += bbc.h
+header-y += bpp.h
+header-y += const.h
+header-y += display7seg.h
+header-y += envctrl.h
+header-y += ipc.h
+header-y += openprom.h
+header-y += openpromio.h
+header-y += pconf.h
+header-y += psrcompat.h
+header-y += pstate.h
+header-y += reg.h
+header-y += uctx.h
+header-y += utrap.h
+header-y += watchdog.h
+
+unifdef-y += fbio.h
+unifdef-y += perfctr.h
diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h
new file mode 100644 (file)
index 0000000..a62c7b9
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef _ASM_SPARC64_OF_DEVICE_H
+#define _ASM_SPARC64_OF_DEVICE_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <asm/openprom.h>
+#include <asm/prom.h>
+
+extern struct bus_type isa_bus_type;
+extern struct bus_type ebus_bus_type;
+extern struct bus_type sbus_bus_type;
+extern struct bus_type of_bus_type;
+
+/*
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties.
+ */
+struct of_device
+{
+       struct device_node              *node;
+       struct device                   dev;
+       struct resource                 resource[PROMREG_MAX];
+       unsigned int                    irqs[PROMINTR_MAX];
+       int                             num_irqs;
+
+       void                            *sysdata;
+
+       int                             slot;
+       int                             portid;
+       int                             clock_freq;
+};
+#define        to_of_device(d) container_of(d, struct of_device, dev)
+
+extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
+extern void of_iounmap(void __iomem *base, unsigned long size);
+
+extern struct of_device *of_find_device_by_node(struct device_node *);
+
+extern const struct of_device_id *of_match_device(
+       const struct of_device_id *matches, const struct of_device *dev);
+
+extern struct of_device *of_dev_get(struct of_device *dev);
+extern void of_dev_put(struct of_device *dev);
+
+/*
+ * An of_platform_driver driver is attached to a basic of_device on
+ * the ISA, EBUS, and SBUS busses on sparc64.
+ */
+struct of_platform_driver
+{
+       char                    *name;
+       struct of_device_id     *match_table;
+       struct module           *owner;
+
+       int     (*probe)(struct of_device* dev, const struct of_device_id *match);
+       int     (*remove)(struct of_device* dev);
+
+       int     (*suspend)(struct of_device* dev, pm_message_t state);
+       int     (*resume)(struct of_device* dev);
+       int     (*shutdown)(struct of_device* dev);
+
+       struct device_driver    driver;
+};
+#define        to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
+
+extern int of_register_driver(struct of_platform_driver *drv,
+                             struct bus_type *bus);
+extern void of_unregister_driver(struct of_platform_driver *drv);
+extern int of_device_register(struct of_device *ofdev);
+extern void of_device_unregister(struct of_device *ofdev);
+extern struct of_device *of_platform_device_create(struct device_node *np,
+                                                  const char *bus_id,
+                                                  struct device *parent,
+                                                  struct bus_type *bus);
+extern void of_release_dev(struct device *dev);
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_SPARC64_OF_DEVICE_H */
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
new file mode 100644 (file)
index 0000000..99671ed
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef _SPARC64_PROM_H
+#define _SPARC64_PROM_H
+#ifdef __KERNEL__
+
+
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC64 by David S. Miller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+
+typedef u32 phandle;
+typedef u32 ihandle;
+
+struct property {
+       char    *name;
+       int     length;
+       void    *value;
+       struct property *next;
+       unsigned long _flags;
+       unsigned int unique_id;
+};
+
+struct of_irq_controller;
+struct device_node {
+       char    *name;
+       char    *type;
+       phandle node;
+       char    *path_component_name;
+       char    *full_name;
+
+       struct  property *properties;
+       struct  property *deadprops; /* removed properties */
+       struct  device_node *parent;
+       struct  device_node *child;
+       struct  device_node *sibling;
+       struct  device_node *next;      /* next device of same type */
+       struct  device_node *allnext;   /* next in list of all nodes */
+       struct  proc_dir_entry *pde;    /* this node's proc directory */
+       struct  kref kref;
+       unsigned long _flags;
+       void    *data;
+       unsigned int unique_id;
+
+       struct of_irq_controller *irq_trans;
+};
+
+struct of_irq_controller {
+       unsigned int    (*irq_build)(struct device_node *, unsigned int, void *);
+       void            *data;
+};
+
+/* flag descriptions */
+#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+
+#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
+#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+
+#define OF_BAD_ADDR    ((u64)-1)
+
+static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
+{
+       dn->pde = de;
+}
+
+extern struct device_node *of_find_node_by_name(struct device_node *from,
+       const char *name);
+#define for_each_node_by_name(dn, name) \
+       for (dn = of_find_node_by_name(NULL, name); dn; \
+            dn = of_find_node_by_name(dn, name))
+extern struct device_node *of_find_node_by_type(struct device_node *from,
+       const char *type);
+#define for_each_node_by_type(dn, type) \
+       for (dn = of_find_node_by_type(NULL, type); dn; \
+            dn = of_find_node_by_type(dn, type))
+extern struct device_node *of_find_compatible_node(struct device_node *from,
+       const char *type, const char *compat);
+extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
+extern struct device_node *of_get_parent(const struct device_node *node);
+extern struct device_node *of_get_next_child(const struct device_node *node,
+                                            struct device_node *prev);
+extern struct property *of_find_property(struct device_node *np,
+                                        const char *name,
+                                        int *lenp);
+extern int of_device_is_compatible(struct device_node *device, const char *);
+extern void *of_get_property(struct device_node *node, const char *name,
+                            int *lenp);
+extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
+extern int of_getintprop_default(struct device_node *np,
+                                const char *name,
+                                int def);
+extern int of_n_addr_cells(struct device_node *np);
+extern int of_n_size_cells(struct device_node *np);
+
+extern void prom_build_devicetree(void);
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC64_PROM_H */
diff --git a/include/asm-sparc64/tracehook.h b/include/asm-sparc64/tracehook.h
new file mode 100644 (file)
index 0000000..fbcdae1
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Tracing hooks, SPARC64 CPU support
+ */
+
+#ifndef _ASM_TRACEHOOK_H
+#define _ASM_TRACEHOOK_H       1
+
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/*
+ * See linux/tracehook.h for the descriptions of what these need to do.
+ */
+
+
+static inline void tracehook_enable_syscall_trace(struct task_struct *tsk)
+{
+       set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_disable_syscall_trace(struct task_struct *tsk)
+{
+       clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_abort_syscall(struct pt_regs *regs)
+{
+       regs->u_regs[UREG_G1] = -1L;
+}
+
+extern const struct utrace_regset_view utrace_sparc64_native_view;
+static inline const struct utrace_regset_view *
+utrace_native_view(struct task_struct *tsk)
+{
+#ifdef CONFIG_COMPAT
+       extern const struct utrace_regset_view utrace_sparc32_view;
+       if (test_tsk_thread_flag(tsk, TIF_32BIT))
+               return &utrace_sparc32_view;
+#endif
+       return &utrace_sparc64_native_view;
+}
+
+#endif
diff --git a/include/asm-v850/Kbuild b/include/asm-v850/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/asm-x86_64/Kbuild b/include/asm-x86_64/Kbuild
new file mode 100644 (file)
index 0000000..40f2f13
--- /dev/null
@@ -0,0 +1,21 @@
+include include/asm-generic/Kbuild.asm
+
+ALTARCH := i386
+ARCHDEF := defined __x86_64__
+ALTARCHDEF := defined __i386__
+
+header-y += boot.h
+header-y += bootsetup.h
+header-y += cpufeature.h
+header-y += debugreg.h
+header-y += ldt.h
+header-y += msr.h
+header-y += prctl.h
+header-y += setup.h
+header-y += sigcontext32.h
+header-y += ucontext.h
+header-y += vsyscall32.h
+
+unifdef-y += mce.h
+unifdef-y += mtrr.h
+unifdef-y += vsyscall.h
diff --git a/include/asm-x86_64/alternative-asm.i b/include/asm-x86_64/alternative-asm.i
new file mode 100644 (file)
index 0000000..0b3f1a2
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef CONFIG_SMP
+       .macro LOCK_PREFIX
+1:     lock
+       .section .smp_locks,"a"
+       .align 8
+       .quad 1b
+       .previous
+       .endm
+#else
+       .macro LOCK_PREFIX
+       .endm
+#endif
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
new file mode 100644 (file)
index 0000000..a584826
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef _X86_64_ALTERNATIVE_H
+#define _X86_64_ALTERNATIVE_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/cpufeature.h>
+
+struct alt_instr {
+       u8 *instr;              /* original instruction */
+       u8 *replacement;
+       u8  cpuid;              /* cpuid bit set for replacement */
+       u8  instrlen;           /* length of original instruction */
+       u8  replacementlen;     /* length of new instruction, <= instrlen */
+       u8  pad[5];
+};
+
+extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
+
+struct module;
+
+#ifdef CONFIG_SMP
+extern void alternatives_smp_module_add(struct module *mod, char *name,
+                                       void *locks, void *locks_end,
+                                       void *text, void *text_end);
+extern void alternatives_smp_module_del(struct module *mod);
+extern void alternatives_smp_switch(int smp);
+#else
+static inline void alternatives_smp_module_add(struct module *mod, char *name,
+                                       void *locks, void *locks_end,
+                                       void *text, void *text_end) {}
+static inline void alternatives_smp_module_del(struct module *mod) {}
+static inline void alternatives_smp_switch(int smp) {}
+#endif
+
+#endif
+
+/*
+ * Alternative instructions for different CPU types or capabilities.
+ *
+ * This allows to use optimized instructions even on generic binary
+ * kernels.
+ *
+ * length of oldinstr must be longer or equal the length of newinstr
+ * It can be padded with nops as needed.
+ *
+ * For non barrier like inlines please define new variants
+ * without volatile and memory clobber.
+ */
+#define alternative(oldinstr, newinstr, feature)       \
+       asm volatile ("661:\n\t" oldinstr "\n662:\n"                 \
+                     ".section .altinstructions,\"a\"\n"            \
+                     "  .align 8\n"                                   \
+                     "  .quad 661b\n"            /* label */          \
+                     "  .quad 663f\n"            /* new instruction */ \
+                     "  .byte %c0\n"             /* feature bit */    \
+                     "  .byte 662b-661b\n"       /* sourcelen */      \
+                     "  .byte 664f-663f\n"       /* replacementlen */ \
+                     ".previous\n"                                     \
+                     ".section .altinstr_replacement,\"ax\"\n"         \
+                     "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+                     ".previous" :: "i" (feature) : "memory")
+
+/*
+ * Alternative inline assembly with input.
+ *
+ * Pecularities:
+ * No memory clobber here.
+ * Argument numbers start with 1.
+ * Best is to use constraints that are fixed size (like (%1) ... "r")
+ * If you use variable sized constraints like "m" or "g" in the
+ * replacement make sure to pad to the worst case length.
+ */
+#define alternative_input(oldinstr, newinstr, feature, input...)       \
+       asm volatile ("661:\n\t" oldinstr "\n662:\n"                    \
+                     ".section .altinstructions,\"a\"\n"               \
+                     "  .align 8\n"                                    \
+                     "  .quad 661b\n"            /* label */           \
+                     "  .quad 663f\n"            /* new instruction */ \
+                     "  .byte %c0\n"             /* feature bit */     \
+                     "  .byte 662b-661b\n"       /* sourcelen */       \
+                     "  .byte 664f-663f\n"       /* replacementlen */  \
+                     ".previous\n"                                     \
+                     ".section .altinstr_replacement,\"ax\"\n"         \
+                     "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+                     ".previous" :: "i" (feature), ##input)
+
+/* Like alternative_input, but with a single output argument */
+#define alternative_io(oldinstr, newinstr, feature, output, input...) \
+       asm volatile ("661:\n\t" oldinstr "\n662:\n"                    \
+                     ".section .altinstructions,\"a\"\n"               \
+                     "  .align 8\n"                                    \
+                     "  .quad 661b\n"            /* label */           \
+                     "  .quad 663f\n"            /* new instruction */ \
+                     "  .byte %c[feat]\n"        /* feature bit */     \
+                     "  .byte 662b-661b\n"       /* sourcelen */       \
+                     "  .byte 664f-663f\n"       /* replacementlen */  \
+                     ".previous\n"                                     \
+                     ".section .altinstr_replacement,\"ax\"\n"         \
+                     "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+                     ".previous" : output : [feat] "i" (feature), ##input)
+
+/*
+ * Alternative inline assembly for SMP.
+ *
+ * The LOCK_PREFIX macro defined here replaces the LOCK and
+ * LOCK_PREFIX macros used everywhere in the source tree.
+ *
+ * SMP alternatives use the same data structures as the other
+ * alternatives and the X86_FEATURE_UP flag to indicate the case of a
+ * UP system running a SMP kernel.  The existing apply_alternatives()
+ * works fine for patching a SMP kernel for UP.
+ *
+ * The SMP alternative tables can be kept after boot and contain both
+ * UP and SMP versions of the instructions to allow switching back to
+ * SMP at runtime, when hotplugging in a new CPU, which is especially
+ * useful in virtualized environments.
+ *
+ * The very common lock prefix is handled as special case in a
+ * separate table which is a pure address list without replacement ptr
+ * and size information.  That keeps the table sizes small.
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX \
+               ".section .smp_locks,\"a\"\n"   \
+               "  .align 8\n"                  \
+               "  .quad 661f\n" /* address */  \
+               ".previous\n"                   \
+               "661:\n\tlock; "
+
+#else /* ! CONFIG_SMP */
+#define LOCK_PREFIX ""
+#endif
+
+#endif /* _X86_64_ALTERNATIVE_H */
diff --git a/include/asm-x86_64/calgary.h b/include/asm-x86_64/calgary.h
new file mode 100644 (file)
index 0000000..82d8de7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Derived from include/asm-powerpc/iommu.h
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Jon Mason <jdmason@us.ibm.com>
+ * Author: Muli Ben-Yehuda <muli@il.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _ASM_X86_64_CALGARY_H
+#define _ASM_X86_64_CALGARY_H
+
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/types.h>
+
+struct iommu_table {
+       unsigned long  it_base;      /* mapped address of tce table */
+       unsigned long  it_hint;      /* Hint for next alloc */
+       unsigned long *it_map;       /* A simple allocation bitmap for now */
+       spinlock_t     it_lock;      /* Protects it_map */
+       unsigned int   it_size;      /* Size of iommu table in entries */
+       unsigned char  it_busno;     /* Bus number this table belongs to */
+       void __iomem  *bbar;
+       u64            tar_val;
+       struct timer_list watchdog_timer;
+};
+
+#define TCE_TABLE_SIZE_UNSPECIFIED     ~0
+#define TCE_TABLE_SIZE_64K             0
+#define TCE_TABLE_SIZE_128K            1
+#define TCE_TABLE_SIZE_256K            2
+#define TCE_TABLE_SIZE_512K            3
+#define TCE_TABLE_SIZE_1M              4
+#define TCE_TABLE_SIZE_2M              5
+#define TCE_TABLE_SIZE_4M              6
+#define TCE_TABLE_SIZE_8M              7
+
+#ifdef CONFIG_CALGARY_IOMMU
+extern int calgary_iommu_init(void);
+extern void detect_calgary(void);
+#else
+static inline int calgary_iommu_init(void) { return 1; }
+static inline void detect_calgary(void) { return; }
+#endif
+
+#endif /* _ASM_X86_64_CALGARY_H */
diff --git a/include/asm-x86_64/intel_arch_perfmon.h b/include/asm-x86_64/intel_arch_perfmon.h
new file mode 100644 (file)
index 0000000..59c3964
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef X86_64_INTEL_ARCH_PERFMON_H
+#define X86_64_INTEL_ARCH_PERFMON_H 1
+
+#define MSR_ARCH_PERFMON_PERFCTR0              0xc1
+#define MSR_ARCH_PERFMON_PERFCTR1              0xc2
+
+#define MSR_ARCH_PERFMON_EVENTSEL0             0x186
+#define MSR_ARCH_PERFMON_EVENTSEL1             0x187
+
+#define ARCH_PERFMON_EVENTSEL0_ENABLE      (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_INT          (1 << 20)
+#define ARCH_PERFMON_EVENTSEL_OS           (1 << 17)
+#define ARCH_PERFMON_EVENTSEL_USR          (1 << 16)
+
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL  (0x3c)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK        (0x00 << 8)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0)
+
+#endif /* X86_64_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-x86_64/irqflags.h b/include/asm-x86_64/irqflags.h
new file mode 100644 (file)
index 0000000..cce6937
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * include/asm-x86_64/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+/*
+ * Interrupt control:
+ */
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__(
+               "# __raw_save_flags\n\t"
+               "pushfq ; popq %q0"
+               : "=g" (flags)
+               : /* no input */
+               : "memory"
+       );
+
+       return flags;
+}
+
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+       __asm__ __volatile__(
+               "pushq %0 ; popfq"
+               : /* no output */
+               :"g" (flags)
+               :"memory", "cc"
+       );
+}
+
+#ifdef CONFIG_X86_VSMP
+
+/*
+ * Interrupt control for the VSMP architecture:
+ */
+
+static inline void raw_local_irq_disable(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       raw_local_irq_restore((flags & ~(1 << 9)) | (1 << 18));
+}
+
+static inline void raw_local_irq_enable(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       raw_local_irq_restore((flags | (1 << 9)) & ~(1 << 18));
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (1<<9)) || (flags & (1 << 18));
+}
+
+#else /* CONFIG_X86_VSMP */
+
+static inline void raw_local_irq_disable(void)
+{
+       __asm__ __volatile__("cli" : : : "memory");
+}
+
+static inline void raw_local_irq_enable(void)
+{
+       __asm__ __volatile__("sti" : : : "memory");
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return !(flags & (1 << 9));
+}
+
+#endif
+
+/*
+ * For spinlocks, etc.:
+ */
+
+static inline unsigned long __raw_local_irq_save(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       raw_local_irq_disable();
+
+       return flags;
+}
+
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+static inline int raw_irqs_disabled(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       return raw_irqs_disabled_flags(flags);
+}
+
+/*
+ * Used in the idle loop; sti takes one instruction cycle
+ * to complete:
+ */
+static inline void raw_safe_halt(void)
+{
+       __asm__ __volatile__("sti; hlt" : : : "memory");
+}
+
+/*
+ * Used when interrupts are already enabled or to
+ * shutdown the processor:
+ */
+static inline void halt(void)
+{
+       __asm__ __volatile__("hlt": : :"memory");
+}
+
+#else /* __ASSEMBLY__: */
+# ifdef CONFIG_TRACE_IRQFLAGS
+#  define TRACE_IRQS_ON                call trace_hardirqs_on_thunk
+#  define TRACE_IRQS_OFF       call trace_hardirqs_off_thunk
+# else
+#  define TRACE_IRQS_ON
+#  define TRACE_IRQS_OFF
+# endif
+#endif
+
+#endif
diff --git a/include/asm-x86_64/k8.h b/include/asm-x86_64/k8.h
new file mode 100644 (file)
index 0000000..699dd69
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _ASM_K8_H
+#define _ASM_K8_H 1
+
+#include <linux/pci.h>
+
+extern struct pci_device_id k8_nb_ids[];
+
+extern int early_is_k8_nb(u32 value);
+extern struct pci_dev **k8_northbridges;
+extern int num_k8_northbridges;
+extern int cache_k8_northbridges(void);
+extern void k8_flush_garts(void);
+
+#endif
diff --git a/include/asm-x86_64/mach-xen/asm/irqflags.h b/include/asm-x86_64/mach-xen/asm/irqflags.h
new file mode 100644 (file)
index 0000000..7b03e7a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * include/asm-x86_64/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+/*
+ * Interrupt control:
+ */
+
+unsigned long __raw_local_save_flags(void);
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+void raw_local_irq_restore(unsigned long flags);
+void raw_local_irq_disable(void);
+void raw_local_irq_enable(void);
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return flags != 0;
+}
+
+/*
+ * For spinlocks, etc.:
+ */
+
+unsigned long __raw_local_irq_save(void);
+
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+int raw_irqs_disabled(void);
+
+/*
+ * Used in the idle loop; sti takes one instruction cycle
+ * to complete:
+ */
+void raw_safe_halt(void);
+
+
+/*
+ * Used when interrupts are already enabled or to
+ * shutdown the processor:
+ */
+void halt(void);
+
+#else /* __ASSEMBLY__: */
+# ifdef CONFIG_TRACE_IRQFLAGS
+#  define TRACE_IRQS_ON                call trace_hardirqs_on_thunk
+#  define TRACE_IRQS_OFF       call trace_hardirqs_off_thunk
+# else
+#  define TRACE_IRQS_ON
+#  define TRACE_IRQS_OFF
+# endif
+#endif
+
+#endif
diff --git a/include/asm-x86_64/mach-xen/asm/maddr.h b/include/asm-x86_64/mach-xen/asm/maddr.h
new file mode 100644 (file)
index 0000000..0104de8
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef _X86_64_MADDR_H
+#define _X86_64_MADDR_H
+
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+#define INVALID_P2M_ENTRY      (~0UL)
+#define FOREIGN_FRAME_BIT      (1UL<<63)
+#define FOREIGN_FRAME(m)       ((m) | FOREIGN_FRAME_BIT)
+
+#ifdef CONFIG_XEN
+
+extern unsigned long *phys_to_machine_mapping;
+
+#undef machine_to_phys_mapping
+extern unsigned long *machine_to_phys_mapping;
+extern unsigned int   machine_to_phys_order;
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return pfn;
+       return phys_to_machine_mapping[(unsigned int)(pfn)] &
+               ~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return 1;
+       return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+       unsigned long pfn;
+
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return mfn;
+
+       if (unlikely((mfn >> machine_to_phys_order) != 0))
+               return end_pfn;
+
+       /* The array access can fail (e.g., device space beyond end of RAM). */
+       asm (
+               "1:     movq %1,%0\n"
+               "2:\n"
+               ".section .fixup,\"ax\"\n"
+               "3:     movq %2,%0\n"
+               "       jmp  2b\n"
+               ".previous\n"
+               ".section __ex_table,\"a\"\n"
+               "       .align 8\n"
+               "       .quad 1b,3b\n"
+               ".previous"
+               : "=r" (pfn)
+               : "m" (machine_to_phys_mapping[mfn]), "m" (end_pfn) );
+
+       return pfn;
+}
+
+/*
+ * We detect special mappings in one of two ways:
+ *  1. If the MFN is an I/O page then Xen will set the m2p entry
+ *     to be outside our maximum possible pseudophys range.
+ *  2. If the MFN belongs to a different domain then we will certainly
+ *     not have MFN in our p2m table. Conversely, if the page is ours,
+ *     then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
+ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+       unsigned long pfn = mfn_to_pfn(mfn);
+       if ((pfn < end_pfn)
+           && !xen_feature(XENFEAT_auto_translated_physmap)
+           && (phys_to_machine_mapping[pfn] != mfn))
+               return end_pfn; /* force !pfn_valid() */
+       return pfn;
+}
+
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+               BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+               return;
+       }
+       phys_to_machine_mapping[pfn] = mfn;
+}
+
+#else /* !CONFIG_XEN */
+
+#define pfn_to_mfn(pfn) (pfn)
+#define mfn_to_pfn(mfn) (mfn)
+#define mfn_to_local_pfn(mfn) (mfn)
+#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
+#define phys_to_machine_mapping_valid(pfn) (1)
+
+#endif /* !CONFIG_XEN */
+
+/* Definitions for machine and pseudophysical addresses. */
+typedef unsigned long paddr_t;
+typedef unsigned long maddr_t;
+
+static inline maddr_t phys_to_machine(paddr_t phys)
+{
+       maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+       machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+       return machine;
+}
+
+static inline paddr_t machine_to_phys(maddr_t machine)
+{
+       paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+       phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+       return phys;
+}
+
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)     (phys_to_machine(__pa(v)))
+#define virt_to_mfn(v)         (pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
+#define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+#define __pte_ma(x)     ((pte_t) { (x) } )
+#define pfn_pte_ma(pfn, prot)  __pte_ma((((pfn) << PAGE_SHIFT) | pgprot_val(prot)) & __supported_pte_mask)
+
+#endif /* _X86_64_MADDR_H */
+
diff --git a/include/asm-x86_64/mach-xen/asm/stacktrace.h b/include/asm-x86_64/mach-xen/asm/stacktrace.h
new file mode 100644 (file)
index 0000000..5eb9799
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_STACKTRACE_H
+#define _ASM_STACKTRACE_H 1
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+       void (*warning)(void *data, char *msg);
+       /* msg must contain %s for the symbol */
+       void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+       void (*address)(void *data, unsigned long address);
+       /* On negative return stop dumping */
+       int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
+               struct stacktrace_ops *ops, void *data);
+
+#endif
diff --git a/include/asm-x86_64/stacktrace.h b/include/asm-x86_64/stacktrace.h
new file mode 100644 (file)
index 0000000..5eb9799
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_STACKTRACE_H
+#define _ASM_STACKTRACE_H 1
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+       void (*warning)(void *data, char *msg);
+       /* msg must contain %s for the symbol */
+       void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+       void (*address)(void *data, unsigned long address);
+       /* On negative return stop dumping */
+       int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
+               struct stacktrace_ops *ops, void *data);
+
+#endif
diff --git a/include/asm-x86_64/tce.h b/include/asm-x86_64/tce.h
new file mode 100644 (file)
index 0000000..53e9a68
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This file is derived from asm-powerpc/tce.h.
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Muli Ben-Yehuda <muli@il.ibm.com>
+ * Author: Jon Mason <jdmason@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _ASM_X86_64_TCE_H
+#define _ASM_X86_64_TCE_H
+
+extern void* tce_table_kva[];
+extern unsigned int specified_table_size;
+struct iommu_table;
+
+#define TCE_ENTRY_SIZE   8   /* in bytes */
+
+#define TCE_READ_SHIFT   0
+#define TCE_WRITE_SHIFT  1
+#define TCE_HUBID_SHIFT  2   /* unused */
+#define TCE_RSVD_SHIFT   8   /* unused */
+#define TCE_RPN_SHIFT    12
+#define TCE_UNUSED_SHIFT 48  /* unused */
+
+#define TCE_RPN_MASK     0x0000fffffffff000ULL
+
+extern void tce_build(struct iommu_table *tbl, unsigned long index,
+        unsigned int npages, unsigned long uaddr, int direction);
+extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages);
+extern void* alloc_tce_table(void);
+extern void free_tce_table(void *tbl);
+extern int build_tce_table(struct pci_dev *dev, void __iomem *bbar);
+
+#endif /* _ASM_X86_64_TCE_H */
diff --git a/include/asm-x86_64/tracehook.h b/include/asm-x86_64/tracehook.h
new file mode 100644 (file)
index 0000000..d7588bf
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Tracing hooks, x86-64 CPU support
+ */
+
+#ifndef _ASM_TRACEHOOK_H
+#define _ASM_TRACEHOOK_H       1
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/proto.h>
+
+/*
+ * See linux/tracehook.h for the descriptions of what these need to do.
+ */
+
+#define ARCH_HAS_SINGLE_STEP   (1)
+
+/* These two are defined in arch/x86_64/kernel/ptrace.c.  */
+void tracehook_enable_single_step(struct task_struct *tsk);
+void tracehook_disable_single_step(struct task_struct *tsk);
+
+static inline int tracehook_single_step_enabled(struct task_struct *tsk)
+{
+       return test_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+}
+
+static inline void tracehook_enable_syscall_trace(struct task_struct *tsk)
+{
+       set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_disable_syscall_trace(struct task_struct *tsk)
+{
+       clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE);
+}
+
+static inline void tracehook_abort_syscall(struct pt_regs *regs)
+{
+       regs->orig_rax = -1L;
+}
+
+extern const struct utrace_regset_view utrace_x86_64_native, utrace_ia32_view;
+static inline const struct utrace_regset_view *
+utrace_native_view(struct task_struct *tsk)
+{
+#ifdef CONFIG_IA32_EMULATION
+       if (test_tsk_thread_flag(tsk, TIF_IA32))
+               return &utrace_ia32_view;
+#endif
+       return &utrace_x86_64_native;
+}
+
+
+#endif
diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h
new file mode 100644 (file)
index 0000000..3b45060
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef _ASM_X86_64_UNWIND_H
+#define _ASM_X86_64_UNWIND_H
+
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *     Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ */
+
+#ifdef CONFIG_STACK_UNWIND
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+#include <asm/vsyscall.h>
+
+struct unwind_frame_info
+{
+       struct pt_regs regs;
+       struct task_struct *task;
+};
+
+#define UNW_PC(frame)        (frame)->regs.rip
+#define UNW_SP(frame)        (frame)->regs.rsp
+#ifdef CONFIG_FRAME_POINTER
+#define UNW_FP(frame)        (frame)->regs.rbp
+#define FRAME_RETADDR_OFFSET 8
+#define FRAME_LINK_OFFSET    0
+#define STACK_BOTTOM(tsk)    (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
+#define STACK_TOP(tsk)       ((tsk)->thread.rsp0)
+#endif
+/* Might need to account for the special exception and interrupt handling
+   stacks here, since normally
+       EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
+   but the construct is needed only for getting across the stack switch to
+   the interrupt stack - thus considering the IRQ stack itself is unnecessary,
+   and the overhead of comparing against all exception handling stacks seems
+   not desirable. */
+#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
+
+#define UNW_REGISTER_INFO \
+       PTREGS_INFO(rax), \
+       PTREGS_INFO(rdx), \
+       PTREGS_INFO(rcx), \
+       PTREGS_INFO(rbx), \
+       PTREGS_INFO(rsi), \
+       PTREGS_INFO(rdi), \
+       PTREGS_INFO(rbp), \
+       PTREGS_INFO(rsp), \
+       PTREGS_INFO(r8), \
+       PTREGS_INFO(r9), \
+       PTREGS_INFO(r10), \
+       PTREGS_INFO(r11), \
+       PTREGS_INFO(r12), \
+       PTREGS_INFO(r13), \
+       PTREGS_INFO(r14), \
+       PTREGS_INFO(r15), \
+       PTREGS_INFO(rip)
+
+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+                                            /*const*/ struct pt_regs *regs)
+{
+       info->regs = *regs;
+}
+
+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+{
+       extern const char thread_return[];
+
+       memset(&info->regs, 0, sizeof(info->regs));
+       info->regs.rip = (unsigned long)thread_return;
+       info->regs.cs = __KERNEL_CS;
+       __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
+       info->regs.rsp = info->task->thread.rsp;
+       info->regs.ss = __KERNEL_DS;
+}
+
+extern int arch_unwind_init_running(struct unwind_frame_info *,
+                                    int (*callback)(struct unwind_frame_info *,
+                                                    void *arg),
+                                    void *arg);
+
+static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+{
+#if 0 /* This can only work when selector register saves/restores
+         are properly annotated (and tracked in UNW_REGISTER_INFO). */
+       return user_mode(&info->regs);
+#else
+       return (long)info->regs.rip >= 0
+              || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
+              || (long)info->regs.rsp >= 0;
+#endif
+}
+
+#else
+
+#define UNW_PC(frame) ((void)(frame), 0UL)
+#define UNW_SP(frame) ((void)(frame), 0UL)
+
+static inline int arch_unw_user_mode(const void *info)
+{
+       return 0;
+}
+
+#endif
+
+#endif /* _ASM_X86_64_UNWIND_H */
diff --git a/include/asm-xtensa/Kbuild b/include/asm-xtensa/Kbuild
new file mode 100644 (file)
index 0000000..c68e168
--- /dev/null
@@ -0,0 +1 @@
+include include/asm-generic/Kbuild.asm
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
new file mode 100644 (file)
index 0000000..10d2ca0
--- /dev/null
@@ -0,0 +1,343 @@
+header-y += byteorder/
+header-y += dvb/
+header-y += hdlc/
+header-y += isdn/
+header-y += nfsd/
+header-y += raid/
+header-y += sunrpc/
+header-y += tc_act/
+header-y += netfilter/
+header-y += netfilter_arp/
+header-y += netfilter_bridge/
+header-y += netfilter_ipv4/
+header-y += netfilter_ipv6/
+
+header-y += affs_fs.h
+header-y += affs_hardblocks.h
+header-y += aio_abi.h
+header-y += a.out.h
+header-y += arcfb.h
+header-y += atmapi.h
+header-y += atmbr2684.h
+header-y += atmclip.h
+header-y += atm_eni.h
+header-y += atm_he.h
+header-y += atm_idt77105.h
+header-y += atmioc.h
+header-y += atmlec.h
+header-y += atmmpc.h
+header-y += atm_nicstar.h
+header-y += atmppp.h
+header-y += atmsap.h
+header-y += atmsvc.h
+header-y += atm_zatm.h
+header-y += auto_fs4.h
+header-y += auxvec.h
+header-y += awe_voice.h
+header-y += ax25.h
+header-y += b1lli.h
+header-y += baycom.h
+header-y += bfs_fs.h
+header-y += blkpg.h
+header-y += bpqether.h
+header-y += cdk.h
+header-y += chio.h
+header-y += coda_psdev.h
+header-y += coff.h
+header-y += comstats.h
+header-y += consolemap.h
+header-y += cycx_cfm.h
+header-y += dm-ioctl.h
+header-y += dn.h
+header-y += dqblk_v1.h
+header-y += dqblk_v2.h
+header-y += dqblk_xfs.h
+header-y += efs_fs_sb.h
+header-y += elf-fdpic.h
+header-y += elf.h
+header-y += elf-em.h
+header-y += fadvise.h
+header-y += fd.h
+header-y += fdreg.h
+header-y += ftape-header-segment.h
+header-y += ftape-vendors.h
+header-y += fuse.h
+header-y += futex.h
+header-y += genetlink.h
+header-y += gen_stats.h
+header-y += gigaset_dev.h
+header-y += hdsmart.h
+header-y += hpfs_fs.h
+header-y += hysdn_if.h
+header-y += i2c-dev.h
+header-y += i8k.h
+header-y += icmp.h
+header-y += if_arcnet.h
+header-y += if_arp.h
+header-y += if_bonding.h
+header-y += if_cablemodem.h
+header-y += if_fc.h
+header-y += if_fddi.h
+header-y += if.h
+header-y += if_hippi.h
+header-y += if_infiniband.h
+header-y += if_packet.h
+header-y += if_plip.h
+header-y += if_ppp.h
+header-y += if_slip.h
+header-y += if_strip.h
+header-y += if_tunnel.h
+header-y += in6.h
+header-y += in_route.h
+header-y += ioctl.h
+header-y += ip.h
+header-y += ipmi_msgdefs.h
+header-y += ip_mp_alg.h
+header-y += ipsec.h
+header-y += ipx.h
+header-y += irda.h
+header-y += isdn_divertif.h
+header-y += iso_fs.h
+header-y += ite_gpio.h
+header-y += ixjuser.h
+header-y += jffs2.h
+header-y += keyctl.h
+header-y += limits.h
+header-y += major.h
+header-y += matroxfb.h
+header-y += meye.h
+header-y += minix_fs.h
+header-y += mmtimer.h
+header-y += mqueue.h
+header-y += mtio.h
+header-y += ncp_no.h
+header-y += netfilter_arp.h
+header-y += netrom.h
+header-y += nfs2.h
+header-y += nfs4_mount.h
+header-y += nfs_mount.h
+header-y += openprom_fs.h
+header-y += param.h
+header-y += pci_ids.h
+header-y += pci_regs.h
+header-y += personality.h
+header-y += pfkeyv2.h
+header-y += pg.h
+header-y += pkt_cls.h
+header-y += pkt_sched.h
+header-y += posix_types.h
+header-y += ppdev.h
+header-y += prctl.h
+header-y += ps2esdi.h
+header-y += qic117.h
+header-y += qnxtypes.h
+header-y += quotaio_v1.h
+header-y += quotaio_v2.h
+header-y += radeonfb.h
+header-y += raw.h
+header-y += resource.h
+header-y += rose.h
+header-y += sctp.h
+header-y += smbno.h
+header-y += snmp.h
+header-y += sockios.h
+header-y += som.h
+header-y += sound.h
+header-y += synclink.h
+header-y += telephony.h
+header-y += termios.h
+header-y += ticable.h
+header-y += times.h
+header-y += tiocl.h
+header-y += tipc.h
+header-y += toshiba.h
+header-y += ultrasound.h
+header-y += un.h
+header-y += utime.h
+header-y += utsname.h
+header-y += video_decoder.h
+header-y += video_encoder.h
+header-y += videotext.h
+header-y += vt.h
+header-y += wavefront.h
+header-y += wireless.h
+header-y += xattr.h
+header-y += x25.h
+header-y += zorro_ids.h
+
+unifdef-y += acct.h
+unifdef-y += adb.h
+unifdef-y += adfs_fs.h
+unifdef-y += agpgart.h
+unifdef-y += apm_bios.h
+unifdef-y += atalk.h
+unifdef-y += atmarp.h
+unifdef-y += atmdev.h
+unifdef-y += atm.h
+unifdef-y += atm_tcp.h
+unifdef-y += audit.h
+unifdef-y += auto_fs.h
+unifdef-y += binfmts.h
+unifdef-y += capability.h
+unifdef-y += capi.h
+unifdef-y += cciss_ioctl.h
+unifdef-y += cdrom.h
+unifdef-y += cm4000_cs.h
+unifdef-y += cn_proc.h
+unifdef-y += coda.h
+unifdef-y += connector.h
+unifdef-y += cramfs_fs.h
+unifdef-y += cuda.h
+unifdef-y += cyclades.h
+unifdef-y += dccp.h
+unifdef-y += dirent.h
+unifdef-y += divert.h
+unifdef-y += elfcore.h
+unifdef-y += errno.h
+unifdef-y += errqueue.h
+unifdef-y += ethtool.h
+unifdef-y += eventpoll.h
+unifdef-y += ext2_fs.h
+unifdef-y += ext3_fs.h
+unifdef-y += fb.h
+unifdef-y += fcntl.h
+unifdef-y += filter.h
+unifdef-y += flat.h
+unifdef-y += fs.h
+unifdef-y += ftape.h
+unifdef-y += gameport.h
+unifdef-y += generic_serial.h
+unifdef-y += genhd.h
+unifdef-y += hayesesp.h
+unifdef-y += hdlcdrv.h
+unifdef-y += hdlc.h
+unifdef-y += hdreg.h
+unifdef-y += hiddev.h
+unifdef-y += hpet.h
+unifdef-y += i2c.h
+unifdef-y += i2o-dev.h
+unifdef-y += icmpv6.h
+unifdef-y += if_bridge.h
+unifdef-y += if_ec.h
+unifdef-y += if_eql.h
+unifdef-y += if_ether.h
+unifdef-y += if_frad.h
+unifdef-y += if_ltalk.h
+unifdef-y += if_pppox.h
+unifdef-y += if_shaper.h
+unifdef-y += if_tr.h
+unifdef-y += if_tun.h
+unifdef-y += if_vlan.h
+unifdef-y += if_wanpipe.h
+unifdef-y += igmp.h
+unifdef-y += inet_diag.h
+unifdef-y += in.h
+unifdef-y += inotify.h
+unifdef-y += input.h
+unifdef-y += ipc.h
+unifdef-y += ipmi.h
+unifdef-y += ipv6.h
+unifdef-y += ipv6_route.h
+unifdef-y += isdn.h
+unifdef-y += isdnif.h
+unifdef-y += isdn_ppp.h
+unifdef-y += isicom.h
+unifdef-y += jbd.h
+unifdef-y += joystick.h
+unifdef-y += kdev_t.h
+unifdef-y += kd.h
+unifdef-y += kernelcapi.h
+unifdef-y += kernel.h
+unifdef-y += keyboard.h
+unifdef-y += llc.h
+unifdef-y += loop.h
+unifdef-y += lp.h
+unifdef-y += mempolicy.h
+unifdef-y += mii.h
+unifdef-y += mman.h
+unifdef-y += mroute.h
+unifdef-y += msdos_fs.h
+unifdef-y += msg.h
+unifdef-y += nbd.h
+unifdef-y += ncp_fs.h
+unifdef-y += ncp.h
+unifdef-y += ncp_mount.h
+unifdef-y += netdevice.h
+unifdef-y += netfilter_bridge.h
+unifdef-y += netfilter_decnet.h
+unifdef-y += netfilter.h
+unifdef-y += netfilter_ipv4.h
+unifdef-y += netfilter_ipv6.h
+unifdef-y += netfilter_logging.h
+unifdef-y += net.h
+unifdef-y += netlink.h
+unifdef-y += nfs3.h
+unifdef-y += nfs4.h
+unifdef-y += nfsacl.h
+unifdef-y += nfs_fs.h
+unifdef-y += nfs.h
+unifdef-y += nfs_idmap.h
+unifdef-y += n_r3964.h
+unifdef-y += nubus.h
+unifdef-y += nvram.h
+unifdef-y += parport.h
+unifdef-y += patchkey.h
+unifdef-y += pci.h
+unifdef-y += pktcdvd.h
+unifdef-y += pmu.h
+unifdef-y += poll.h
+unifdef-y += ppp_defs.h
+unifdef-y += ppp-comp.h
+unifdef-y += ptrace.h
+unifdef-y += qnx4_fs.h
+unifdef-y += quota.h
+unifdef-y += random.h
+unifdef-y += reboot.h
+unifdef-y += reiserfs_fs.h
+unifdef-y += reiserfs_xattr.h
+unifdef-y += romfs_fs.h
+unifdef-y += route.h
+unifdef-y += rtc.h
+unifdef-y += rtnetlink.h
+unifdef-y += scc.h
+unifdef-y += sched.h
+unifdef-y += sdla.h
+unifdef-y += selinux_netlink.h
+unifdef-y += sem.h
+unifdef-y += serial_core.h
+unifdef-y += serial.h
+unifdef-y += serio.h
+unifdef-y += shm.h
+unifdef-y += signal.h
+unifdef-y += smb_fs.h
+unifdef-y += smb.h
+unifdef-y += smb_mount.h
+unifdef-y += socket.h
+unifdef-y += sonet.h
+unifdef-y += sonypi.h
+unifdef-y += soundcard.h
+unifdef-y += stat.h
+unifdef-y += stddef.h
+unifdef-y += sysctl.h
+unifdef-y += tcp.h
+unifdef-y += time.h
+unifdef-y += timex.h
+unifdef-y += tty.h
+unifdef-y += types.h
+unifdef-y += udf_fs_i.h
+unifdef-y += udp.h
+unifdef-y += uinput.h
+unifdef-y += uio.h
+unifdef-y += unistd.h
+unifdef-y += usb_ch9.h
+unifdef-y += usbdevice_fs.h
+unifdef-y += user.h
+unifdef-y += videodev2.h
+unifdef-y += videodev.h
+unifdef-y += wait.h
+unifdef-y += wanrouter.h
+unifdef-y += watchdog.h
+unifdef-y += xfrm.h
+unifdef-y += zftape.h
+
+objhdr-y += version.h
diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild
new file mode 100644 (file)
index 0000000..56499ab
--- /dev/null
@@ -0,0 +1,7 @@
+header-y += big_endian.h
+header-y += little_endian.h
+header-y += pdp_endian.h
+
+unifdef-y += generic.h
+unifdef-y += swabb.h
+unifdef-y += swab.h
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
new file mode 100644 (file)
index 0000000..d852024
--- /dev/null
@@ -0,0 +1,185 @@
+/*  linux/include/linux/clocksource.h
+ *
+ *  This file contains the structure definitions for clocksources.
+ *
+ *  If you are not a clocksource, or timekeeping code, you should
+ *  not be including this file!
+ */
+#ifndef _LINUX_CLOCKSOURCE_H
+#define _LINUX_CLOCKSOURCE_H
+
+#include <linux/types.h>
+#include <linux/timex.h>
+#include <linux/time.h>
+#include <linux/list.h>
+#include <asm/div64.h>
+#include <asm/io.h>
+
+/* clocksource cycle base type */
+typedef u64 cycle_t;
+
+/**
+ * struct clocksource - hardware abstraction for a free running counter
+ *     Provides mostly state-free accessors to the underlying hardware.
+ *
+ * @name:              ptr to clocksource name
+ * @list:              list head for registration
+ * @rating:            rating value for selection (higher is better)
+ *                     To avoid rating inflation the following
+ *                     list should give you a guide as to how
+ *                     to assign your clocksource a rating
+ *                     1-99: Unfit for real use
+ *                             Only available for bootup and testing purposes.
+ *                     100-199: Base level usability.
+ *                             Functional for real use, but not desired.
+ *                     200-299: Good.
+ *                             A correct and usable clocksource.
+ *                     300-399: Desired.
+ *                             A reasonably fast and accurate clocksource.
+ *                     400-499: Perfect
+ *                             The ideal clocksource. A must-use where
+ *                             available.
+ * @read:              returns a cycle value
+ * @mask:              bitmask for two's complement
+ *                     subtraction of non 64 bit counters
+ * @mult:              cycle to nanosecond multiplier
+ * @shift:             cycle to nanosecond divisor (power of two)
+ * @update_callback:   called when safe to alter clocksource values
+ * @is_continuous:     defines if clocksource is free-running.
+ * @cycle_interval:    Used internally by timekeeping core, please ignore.
+ * @xtime_interval:    Used internally by timekeeping core, please ignore.
+ */
+struct clocksource {
+       char *name;
+       struct list_head list;
+       int rating;
+       cycle_t (*read)(void);
+       cycle_t mask;
+       u32 mult;
+       u32 shift;
+       int (*update_callback)(void);
+       int is_continuous;
+
+       /* timekeeping specific data, ignore */
+       cycle_t cycle_last, cycle_interval;
+       u64 xtime_nsec, xtime_interval;
+       s64 error;
+};
+
+/* simplify initialization of mask field */
+#define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
+
+/**
+ * clocksource_khz2mult - calculates mult from khz and shift
+ * @khz:               Clocksource frequency in KHz
+ * @shift_constant:    Clocksource shift factor
+ *
+ * Helper functions that converts a khz counter frequency to a timsource
+ * multiplier, given the clocksource shift value
+ */
+static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
+{
+       /*  khz = cyc/(Million ns)
+        *  mult/2^shift  = ns/cyc
+        *  mult = ns/cyc * 2^shift
+        *  mult = 1Million/khz * 2^shift
+        *  mult = 1000000 * 2^shift / khz
+        *  mult = (1000000<<shift) / khz
+        */
+       u64 tmp = ((u64)1000000) << shift_constant;
+
+       tmp += khz/2; /* round for do_div */
+       do_div(tmp, khz);
+
+       return (u32)tmp;
+}
+
+/**
+ * clocksource_hz2mult - calculates mult from hz and shift
+ * @hz:                        Clocksource frequency in Hz
+ * @shift_constant:    Clocksource shift factor
+ *
+ * Helper functions that converts a hz counter
+ * frequency to a timsource multiplier, given the
+ * clocksource shift value
+ */
+static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
+{
+       /*  hz = cyc/(Billion ns)
+        *  mult/2^shift  = ns/cyc
+        *  mult = ns/cyc * 2^shift
+        *  mult = 1Billion/hz * 2^shift
+        *  mult = 1000000000 * 2^shift / hz
+        *  mult = (1000000000<<shift) / hz
+        */
+       u64 tmp = ((u64)1000000000) << shift_constant;
+
+       tmp += hz/2; /* round for do_div */
+       do_div(tmp, hz);
+
+       return (u32)tmp;
+}
+
+/**
+ * clocksource_read: - Access the clocksource's current cycle value
+ * @cs:                pointer to clocksource being read
+ *
+ * Uses the clocksource to return the current cycle_t value
+ */
+static inline cycle_t clocksource_read(struct clocksource *cs)
+{
+       return cs->read();
+}
+
+/**
+ * cyc2ns - converts clocksource cycles to nanoseconds
+ * @cs:                Pointer to clocksource
+ * @cycles:    Cycles
+ *
+ * Uses the clocksource and ntp ajdustment to convert cycle_ts to nanoseconds.
+ *
+ * XXX - This could use some mult_lxl_ll() asm optimization
+ */
+static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles)
+{
+       u64 ret = (u64)cycles;
+       ret = (ret * cs->mult) >> cs->shift;
+       return ret;
+}
+
+/**
+ * clocksource_calculate_interval - Calculates a clocksource interval struct
+ *
+ * @c:         Pointer to clocksource.
+ * @length_nsec: Desired interval length in nanoseconds.
+ *
+ * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment
+ * pair and interval request.
+ *
+ * Unless you're the timekeeping code, you should not be using this!
+ */
+static inline void clocksource_calculate_interval(struct clocksource *c,
+                                               unsigned long length_nsec)
+{
+       u64 tmp;
+
+       /* XXX - All of this could use a whole lot of optimization */
+       tmp = length_nsec;
+       tmp <<= c->shift;
+       tmp += c->mult/2;
+       do_div(tmp, c->mult);
+
+       c->cycle_interval = (cycle_t)tmp;
+       if (c->cycle_interval == 0)
+               c->cycle_interval = 1;
+
+       c->xtime_interval = (u64)c->cycle_interval * c->mult;
+}
+
+
+/* used to install a new clocksource */
+int clocksource_register(struct clocksource*);
+void clocksource_reselect(void);
+struct clocksource* clocksource_get_next(void);
+
+#endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
new file mode 100644 (file)
index 0000000..88dafa2
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __LINUX_DEBUG_LOCKING_H
+#define __LINUX_DEBUG_LOCKING_H
+
+struct task_struct;
+
+extern int debug_locks;
+extern int debug_locks_silent;
+
+/*
+ * Generic 'turn off all lock debugging' function:
+ */
+extern int debug_locks_off(void);
+
+/*
+ * In the debug case we carry the caller's instruction pointer into
+ * other functions, but we dont want the function argument overhead
+ * in the nondebug case - hence these macros:
+ */
+#define _RET_IP_               (unsigned long)__builtin_return_address(0)
+#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
+
+#define DEBUG_LOCKS_WARN_ON(c)                                         \
+({                                                                     \
+       int __ret = 0;                                                  \
+                                                                       \
+       if (unlikely(c)) {                                              \
+               if (debug_locks_off())                                  \
+                       WARN_ON(1);                                     \
+               __ret = 1;                                              \
+       }                                                               \
+       __ret;                                                          \
+})
+
+#ifdef CONFIG_SMP
+# define SMP_DEBUG_LOCKS_WARN_ON(c)                    DEBUG_LOCKS_WARN_ON(c)
+#else
+# define SMP_DEBUG_LOCKS_WARN_ON(c)                    do { } while (0)
+#endif
+
+#ifdef CONFIG_DEBUG_LOCKING_API_SELFTESTS
+  extern void locking_selftest(void);
+#else
+# define locking_selftest()    do { } while (0)
+#endif
+
+#ifdef CONFIG_LOCKDEP
+extern void debug_show_all_locks(void);
+extern void debug_show_held_locks(struct task_struct *task);
+extern void debug_check_no_locks_freed(const void *from, unsigned long len);
+extern void debug_check_no_locks_held(struct task_struct *task);
+#else
+static inline void debug_show_all_locks(void)
+{
+}
+
+static inline void debug_show_held_locks(struct task_struct *task)
+{
+}
+
+static inline void
+debug_check_no_locks_freed(const void *from, unsigned long len)
+{
+}
+
+static inline void
+debug_check_no_locks_held(struct task_struct *task)
+{
+}
+#endif
+
+#endif
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
new file mode 100644 (file)
index 0000000..561e2a7
--- /dev/null
@@ -0,0 +1,121 @@
+/* delayacct.h - per-task delay accounting
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2006
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 _LINUX_DELAYACCT_H
+#define _LINUX_DELAYACCT_H
+
+#include <linux/sched.h>
+#include <linux/taskstats_kern.h>
+
+/*
+ * Per-task flags relevant to delay accounting
+ * maintained privately to avoid exhausting similar flags in sched.h:PF_*
+ * Used to set current->delays->flags
+ */
+#define DELAYACCT_PF_SWAPIN    0x00000001      /* I am doing a swapin */
+
+#ifdef CONFIG_TASK_DELAY_ACCT
+
+extern int delayacct_on;       /* Delay accounting turned on/off */
+extern kmem_cache_t *delayacct_cache;
+extern void delayacct_init(void);
+extern void __delayacct_tsk_init(struct task_struct *);
+extern void __delayacct_tsk_exit(struct task_struct *);
+extern void __delayacct_blkio_start(void);
+extern void __delayacct_blkio_end(void);
+extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
+extern __u64 __delayacct_blkio_ticks(struct task_struct *);
+
+static inline void delayacct_set_flag(int flag)
+{
+       if (current->delays)
+               current->delays->flags |= flag;
+}
+
+static inline void delayacct_clear_flag(int flag)
+{
+       if (current->delays)
+               current->delays->flags &= ~flag;
+}
+
+static inline void delayacct_tsk_init(struct task_struct *tsk)
+{
+       /* reinitialize in case parent's non-null pointer was dup'ed*/
+       tsk->delays = NULL;
+       if (delayacct_on)
+               __delayacct_tsk_init(tsk);
+}
+
+/* Free tsk->delays. Called from bad fork and __put_task_struct
+ * where there's no risk of tsk->delays being accessed elsewhere
+ */
+static inline void delayacct_tsk_free(struct task_struct *tsk)
+{
+       if (tsk->delays)
+               kmem_cache_free(delayacct_cache, tsk->delays);
+       tsk->delays = NULL;
+}
+
+static inline void delayacct_blkio_start(void)
+{
+       if (current->delays)
+               __delayacct_blkio_start();
+}
+
+static inline void delayacct_blkio_end(void)
+{
+       if (current->delays)
+               __delayacct_blkio_end();
+}
+
+static inline int delayacct_add_tsk(struct taskstats *d,
+                                       struct task_struct *tsk)
+{
+       if (!delayacct_on || !tsk->delays)
+               return 0;
+       return __delayacct_add_tsk(d, tsk);
+}
+
+static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
+{
+       if (tsk->delays)
+               return __delayacct_blkio_ticks(tsk);
+       return 0;
+}
+
+#else
+static inline void delayacct_set_flag(int flag)
+{}
+static inline void delayacct_clear_flag(int flag)
+{}
+static inline void delayacct_init(void)
+{}
+static inline void delayacct_tsk_init(struct task_struct *tsk)
+{}
+static inline void delayacct_tsk_free(struct task_struct *tsk)
+{}
+static inline void delayacct_blkio_start(void)
+{}
+static inline void delayacct_blkio_end(void)
+{}
+static inline int delayacct_add_tsk(struct taskstats *d,
+                                       struct task_struct *tsk)
+{ return 0; }
+static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
+{ return 0; }
+#endif /* CONFIG_TASK_DELAY_ACCT */
+
+#endif
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
new file mode 100644 (file)
index 0000000..c94d8f1
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef DMAENGINE_H
+#define DMAENGINE_H
+
+#ifdef CONFIG_DMA_ENGINE
+
+#include <linux/device.h>
+#include <linux/uio.h>
+#include <linux/kref.h>
+#include <linux/completion.h>
+#include <linux/rcupdate.h>
+
+/**
+ * enum dma_event - resource PNP/power managment events
+ * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
+ * @DMA_RESOURCE_RESUME: DMA device returning to full power
+ * @DMA_RESOURCE_ADDED: DMA device added to the system
+ * @DMA_RESOURCE_REMOVED: DMA device removed from the system
+ */
+enum dma_event {
+       DMA_RESOURCE_SUSPEND,
+       DMA_RESOURCE_RESUME,
+       DMA_RESOURCE_ADDED,
+       DMA_RESOURCE_REMOVED,
+};
+
+/**
+ * typedef dma_cookie_t - an opaque DMA cookie
+ *
+ * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
+ */
+typedef s32 dma_cookie_t;
+
+#define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0)
+
+/**
+ * enum dma_status - DMA transaction status
+ * @DMA_SUCCESS: transaction completed successfully
+ * @DMA_IN_PROGRESS: transaction not yet processed
+ * @DMA_ERROR: transaction failed
+ */
+enum dma_status {
+       DMA_SUCCESS,
+       DMA_IN_PROGRESS,
+       DMA_ERROR,
+};
+
+/**
+ * struct dma_chan_percpu - the per-CPU part of struct dma_chan
+ * @refcount: local_t used for open-coded "bigref" counting
+ * @memcpy_count: transaction counter
+ * @bytes_transferred: byte counter
+ */
+
+struct dma_chan_percpu {
+       local_t refcount;
+       /* stats */
+       unsigned long memcpy_count;
+       unsigned long bytes_transferred;
+};
+
+/**
+ * struct dma_chan - devices supply DMA channels, clients use them
+ * @client: ptr to the client user of this chan, will be %NULL when unused
+ * @device: ptr to the dma device who supplies this channel, always !%NULL
+ * @cookie: last cookie value returned to client
+ * @chan_id: channel ID for sysfs
+ * @class_dev: class device for sysfs
+ * @refcount: kref, used in "bigref" slow-mode
+ * @slow_ref: indicates that the DMA channel is free
+ * @rcu: the DMA channel's RCU head
+ * @client_node: used to add this to the client chan list
+ * @device_node: used to add this to the device chan list
+ * @local: per-cpu pointer to a struct dma_chan_percpu
+ */
+struct dma_chan {
+       struct dma_client *client;
+       struct dma_device *device;
+       dma_cookie_t cookie;
+
+       /* sysfs */
+       int chan_id;
+       struct class_device class_dev;
+
+       struct kref refcount;
+       int slow_ref;
+       struct rcu_head rcu;
+
+       struct list_head client_node;
+       struct list_head device_node;
+       struct dma_chan_percpu *local;
+};
+
+void dma_chan_cleanup(struct kref *kref);
+
+static inline void dma_chan_get(struct dma_chan *chan)
+{
+       if (unlikely(chan->slow_ref))
+               kref_get(&chan->refcount);
+       else {
+               local_inc(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
+               put_cpu();
+       }
+}
+
+static inline void dma_chan_put(struct dma_chan *chan)
+{
+       if (unlikely(chan->slow_ref))
+               kref_put(&chan->refcount, dma_chan_cleanup);
+       else {
+               local_dec(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
+               put_cpu();
+       }
+}
+
+/*
+ * typedef dma_event_callback - function pointer to a DMA event callback
+ */
+typedef void (*dma_event_callback) (struct dma_client *client,
+               struct dma_chan *chan, enum dma_event event);
+
+/**
+ * struct dma_client - info on the entity making use of DMA services
+ * @event_callback: func ptr to call when something happens
+ * @chan_count: number of chans allocated
+ * @chans_desired: number of chans requested. Can be +/- chan_count
+ * @lock: protects access to the channels list
+ * @channels: the list of DMA channels allocated
+ * @global_node: list_head for global dma_client_list
+ */
+struct dma_client {
+       dma_event_callback      event_callback;
+       unsigned int            chan_count;
+       unsigned int            chans_desired;
+
+       spinlock_t              lock;
+       struct list_head        channels;
+       struct list_head        global_node;
+};
+
+/**
+ * struct dma_device - info on the entity supplying DMA services
+ * @chancnt: how many DMA channels are supported
+ * @channels: the list of struct dma_chan
+ * @global_node: list_head for global dma_device_list
+ * @refcount: reference count
+ * @done: IO completion struct
+ * @dev_id: unique device ID
+ * @device_alloc_chan_resources: allocate resources and return the
+ *     number of allocated descriptors
+ * @device_free_chan_resources: release DMA channel's resources
+ * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
+ * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
+ * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
+ * @device_memcpy_complete: poll the status of an IOAT DMA transaction
+ * @device_memcpy_issue_pending: push appended descriptors to hardware
+ */
+struct dma_device {
+
+       unsigned int chancnt;
+       struct list_head channels;
+       struct list_head global_node;
+
+       struct kref refcount;
+       struct completion done;
+
+       int dev_id;
+
+       int (*device_alloc_chan_resources)(struct dma_chan *chan);
+       void (*device_free_chan_resources)(struct dma_chan *chan);
+       dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
+                       void *dest, void *src, size_t len);
+       dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
+                       struct page *page, unsigned int offset, void *kdata,
+                       size_t len);
+       dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
+                       struct page *dest_pg, unsigned int dest_off,
+                       struct page *src_pg, unsigned int src_off, size_t len);
+       enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+                       dma_cookie_t cookie, dma_cookie_t *last,
+                       dma_cookie_t *used);
+       void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+};
+
+/* --- public DMA engine API --- */
+
+struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+void dma_async_client_unregister(struct dma_client *client);
+void dma_async_client_chan_request(struct dma_client *client,
+               unsigned int number);
+
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages).
+ */
+static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+       void *dest, void *src, size_t len)
+{
+       int cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
+}
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+       struct page *page, unsigned int offset, void *kdata, size_t len)
+{
+       int cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
+                                                    kdata, len);
+}
+
+/**
+ * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
+ * @chan: DMA channel to offload copy to
+ * @dest_pg: destination page
+ * @dest_off: offset in page to copy to
+ * @src_pg: source page
+ * @src_off: offset in page to copy from
+ * @len: length
+ *
+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+ * address according to the DMA mapping API rules for streaming mappings.
+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+ * (kernel memory or locked user space pages).
+ */
+static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+       struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
+       unsigned int src_off, size_t len)
+{
+       int cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
+                                                   src_pg, src_off, len);
+}
+
+/**
+ * dma_async_memcpy_issue_pending - flush pending copies to HW
+ * @chan: target DMA channel
+ *
+ * This allows drivers to push copies to HW in batches,
+ * reducing MMIO writes where possible.
+ */
+static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+{
+       return chan->device->device_memcpy_issue_pending(chan);
+}
+
+/**
+ * dma_async_memcpy_complete - poll for transaction completion
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
+ * @last: returns last completed cookie, can be NULL
+ * @used: returns last issued cookie, can be NULL
+ *
+ * If @last and @used are passed in, upon return they reflect the driver
+ * internal state and can be used with dma_async_is_complete() to check
+ * the status of multiple cookies without re-checking hardware state.
+ */
+static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+       dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+{
+       return chan->device->device_memcpy_complete(chan, cookie, last, used);
+}
+
+/**
+ * dma_async_is_complete - test a cookie against chan state
+ * @cookie: transaction identifier to test status of
+ * @last_complete: last know completed transaction
+ * @last_used: last cookie value handed out
+ *
+ * dma_async_is_complete() is used in dma_async_memcpy_complete()
+ * the test logic is seperated for lightweight testing of multiple cookies
+ */
+static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
+                       dma_cookie_t last_complete, dma_cookie_t last_used)
+{
+       if (last_complete <= last_used) {
+               if ((cookie <= last_complete) || (cookie > last_used))
+                       return DMA_SUCCESS;
+       } else {
+               if ((cookie <= last_complete) && (cookie > last_used))
+                       return DMA_SUCCESS;
+       }
+       return DMA_IN_PROGRESS;
+}
+
+
+/* --- DMA device --- */
+
+int dma_async_device_register(struct dma_device *device);
+void dma_async_device_unregister(struct dma_device *device);
+
+/* --- Helper iov-locking functions --- */
+
+struct dma_page_list {
+       char *base_address;
+       int nr_pages;
+       struct page **pages;
+};
+
+struct dma_pinned_list {
+       int nr_iovecs;
+       struct dma_page_list page_list[0];
+};
+
+struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len);
+void dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list);
+
+dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len);
+dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, struct page *page,
+       unsigned int offset, size_t len);
+
+#endif /* CONFIG_DMA_ENGINE */
+#endif /* DMAENGINE_H */
diff --git a/include/linux/dvb/Kbuild b/include/linux/dvb/Kbuild
new file mode 100644 (file)
index 0000000..d97b3a5
--- /dev/null
@@ -0,0 +1,9 @@
+header-y += ca.h
+header-y += frontend.h
+header-y += net.h
+header-y += osd.h
+header-y += version.h
+
+unifdef-y += audio.h
+unifdef-y += dmx.h
+unifdef-y += video.h
diff --git a/include/linux/elf-em.h b/include/linux/elf-em.h
new file mode 100644 (file)
index 0000000..6a5796c
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _LINUX_ELF_EM_H
+#define _LINUX_ELF_EM_H
+
+/* These constants define the various ELF target machines */
+#define EM_NONE                0
+#define EM_M32         1
+#define EM_SPARC       2
+#define EM_386         3
+#define EM_68K         4
+#define EM_88K         5
+#define EM_486         6       /* Perhaps disused */
+#define EM_860         7
+#define EM_MIPS                8       /* MIPS R3000 (officially, big-endian only) */
+                               /* Next two are historical and binaries and
+                                  modules of these types will be rejected by
+                                  Linux.  */
+#define EM_MIPS_RS3_LE 10      /* MIPS R3000 little-endian */
+#define EM_MIPS_RS4_BE 10      /* MIPS R4000 big-endian */
+
+#define EM_PARISC      15      /* HPPA */
+#define EM_SPARC32PLUS 18      /* Sun's "v8plus" */
+#define EM_PPC         20      /* PowerPC */
+#define EM_PPC64       21       /* PowerPC64 */
+#define EM_SH          42      /* SuperH */
+#define EM_SPARCV9     43      /* SPARC v9 64-bit */
+#define EM_IA_64       50      /* HP/Intel IA-64 */
+#define EM_X86_64      62      /* AMD x86-64 */
+#define EM_S390                22      /* IBM S/390 */
+#define EM_CRIS                76      /* Axis Communications 32-bit embedded processor */
+#define EM_V850                87      /* NEC v850 */
+#define EM_M32R                88      /* Renesas M32R */
+#define EM_H8_300      46      /* Renesas H8/300,300H,H8S */
+#define EM_FRV         0x5441  /* Fujitsu FR-V */
+
+/*
+ * This is an interim value that we will use until the committee comes
+ * up with a final number.
+ */
+#define EM_ALPHA       0x9026
+
+/* Bogus old v850 magic number, used by old tools. */
+#define EM_CYGNUS_V850 0x9080
+/* Bogus old m32r magic number, used by old tools. */
+#define EM_CYGNUS_M32R 0x9041
+/* This is the old interim value for S/390 architecture */
+#define EM_S390_OLD    0xA390
+
+
+#endif /* _LINUX_ELF_EM_H */
diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h
new file mode 100644 (file)
index 0000000..67396db
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef _LINUX_ELFNOTE_H
+#define _LINUX_ELFNOTE_H
+/*
+ * Helper macros to generate ELF Note structures, which are put into a
+ * PT_NOTE segment of the final vmlinux image.  These are useful for
+ * including name-value pairs of metadata into the kernel binary (or
+ * modules?) for use by external programs.
+ *
+ * Each note has three parts: a name, a type and a desc.  The name is
+ * intended to distinguish the note's originator, so it would be a
+ * company, project, subsystem, etc; it must be in a suitable form for
+ * use in a section name.  The type is an integer which is used to tag
+ * the data, and is considered to be within the "name" namespace (so
+ * "FooCo"'s type 42 is distinct from "BarProj"'s type 42).  The
+ * "desc" field is the actual data.  There are no constraints on the
+ * desc field's contents, though typically they're fairly small.
+ *
+ * All notes from a given NAME are put into a section named
+ * .note.NAME.  When the kernel image is finally linked, all the notes
+ * are packed into a single .notes section, which is mapped into the
+ * PT_NOTE segment.  Because notes for a given name are grouped into
+ * the same section, they'll all be adjacent the output file.
+ *
+ * This file defines macros for both C and assembler use.  Their
+ * syntax is slightly different, but they're semantically similar.
+ *
+ * See the ELF specification for more detail about ELF notes.
+ */
+
+#ifdef __ASSEMBLER__
+/*
+ * Generate a structure with the same shape as Elf{32,64}_Nhdr (which
+ * turn out to be the same size and shape), followed by the name and
+ * desc data with appropriate padding.  The 'desctype' argument is the
+ * assembler pseudo op defining the type of the data e.g. .asciz while
+ * 'descdata' is the data itself e.g.  "hello, world".
+ *
+ * e.g. ELFNOTE(XYZCo, 42, .asciz, "forty-two")
+ *      ELFNOTE(XYZCo, 12, .long, 0xdeadbeef)
+ */
+#define ELFNOTE(name, type, desctype, descdata)        \
+.pushsection .note.name                        ;       \
+  .align 4                             ;       \
+  .long 2f - 1f                /* namesz */    ;       \
+  .long 4f - 3f                /* descsz */    ;       \
+  .long type                           ;       \
+1:.asciz "name"                                ;       \
+2:.align 4                             ;       \
+3:desctype descdata                    ;       \
+4:.align 4                             ;       \
+.popsection                            ;
+#else  /* !__ASSEMBLER__ */
+#include <linux/elf.h>
+/*
+ * Use an anonymous structure which matches the shape of
+ * Elf{32,64}_Nhdr, but includes the name and desc data.  The size and
+ * type of name and desc depend on the macro arguments.  "name" must
+ * be a literal string, and "desc" must be passed by value.  You may
+ * only define one note per line, since __LINE__ is used to generate
+ * unique symbols.
+ */
+#define _ELFNOTE_PASTE(a,b)    a##b
+#define _ELFNOTE(size, name, unique, type, desc)                       \
+       static const struct {                                           \
+               struct elf##size##_note _nhdr;                          \
+               unsigned char _name[sizeof(name)]                       \
+               __attribute__((aligned(sizeof(Elf##size##_Word))));     \
+               typeof(desc) _desc                                      \
+                            __attribute__((aligned(sizeof(Elf##size##_Word)))); \
+       } _ELFNOTE_PASTE(_note_, unique)                                \
+               __attribute_used__                                      \
+               __attribute__((section(".note." name),                  \
+                              aligned(sizeof(Elf##size##_Word)),       \
+                              unused)) = {                             \
+               {                                                       \
+                       sizeof(name),                                   \
+                       sizeof(desc),                                   \
+                       type,                                           \
+               },                                                      \
+               name,                                                   \
+               desc                                                    \
+       }
+#define ELFNOTE(size, name, type, desc)                \
+       _ELFNOTE(size, name, __LINE__, type, desc)
+
+#define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc)
+#define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc)
+#endif /* __ASSEMBLER__ */
+
+#endif /* _LINUX_ELFNOTE_H */
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
new file mode 100644 (file)
index 0000000..e229fed
--- /dev/null
@@ -0,0 +1,243 @@
+/* fscache-cache.h: general filesystem caching backing cache interface
+ *
+ * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * NOTE!!! See:
+ *
+ *     Documentation/filesystems/caching/backend-api.txt
+ *
+ * for a description of the cache backend interface declared here.
+ */
+
+#ifndef _LINUX_FSCACHE_CACHE_H
+#define _LINUX_FSCACHE_CACHE_H
+
+#include <linux/fscache.h>
+
+#define NR_MAXCACHES BITS_PER_LONG
+
+struct fscache_cache;
+struct fscache_cache_ops;
+struct fscache_object;
+
+/*
+ * cache tag definition
+ */
+struct fscache_cache_tag {
+       struct list_head                link;
+       struct fscache_cache            *cache;         /* cache referred to by this tag */
+       atomic_t                        usage;
+       char                            name[0];        /* tag name */
+};
+
+/*
+ * cache definition
+ */
+struct fscache_cache {
+       struct fscache_cache_ops        *ops;
+       struct fscache_cache_tag        *tag;           /* tag representing this cache */
+       struct list_head                link;           /* link in list of caches */
+       struct rw_semaphore             withdrawal_sem; /* withdrawal control sem */
+       size_t                          max_index_size; /* maximum size of index data */
+       char                            identifier[32]; /* cache label */
+
+       /* node management */
+       struct list_head                object_list;    /* list of data/index objects */
+       spinlock_t                      object_list_lock;
+       struct fscache_object           *fsdef;         /* object for the fsdef index */
+       unsigned long                   flags;
+#define FSCACHE_IOERROR                        0       /* cache stopped on I/O error */
+};
+
+extern void fscache_init_cache(struct fscache_cache *cache,
+                              struct fscache_cache_ops *ops,
+                              const char *idfmt,
+                              ...) __attribute__ ((format (printf,3,4)));
+
+extern int fscache_add_cache(struct fscache_cache *cache,
+                            struct fscache_object *fsdef,
+                            const char *tagname);
+extern void fscache_withdraw_cache(struct fscache_cache *cache);
+
+extern void fscache_io_error(struct fscache_cache *cache);
+
+/*****************************************************************************/
+/*
+ * cache operations
+ */
+struct fscache_cache_ops {
+       /* name of cache provider */
+       const char *name;
+
+       /* look up the object for a cookie, creating it on disc if necessary */
+       struct fscache_object *(*lookup_object)(struct fscache_cache *cache,
+                                               struct fscache_object *parent,
+                                               struct fscache_cookie *cookie);
+
+       /* increment the usage count on this object (may fail if unmounting) */
+       struct fscache_object *(*grab_object)(struct fscache_object *object);
+
+       /* lock a semaphore on an object */
+       void (*lock_object)(struct fscache_object *object);
+
+       /* unlock a semaphore on an object */
+       void (*unlock_object)(struct fscache_object *object);
+
+       /* pin an object in the cache */
+       int (*pin_object)(struct fscache_object *object);
+
+       /* unpin an object in the cache */
+       void (*unpin_object)(struct fscache_object *object);
+
+       /* store the updated auxilliary data on an object */
+       void (*update_object)(struct fscache_object *object);
+
+       /* dispose of a reference to an object */
+       void (*put_object)(struct fscache_object *object);
+
+       /* sync a cache */
+       void (*sync_cache)(struct fscache_cache *cache);
+
+       /* set the data size of an object */
+       int (*set_i_size)(struct fscache_object *object, loff_t i_size);
+
+       /* reserve space for an object's data and associated metadata */
+       int (*reserve_space)(struct fscache_object *object, loff_t i_size);
+
+       /* request a backing block for a page be read or allocated in the
+        * cache */
+       int (*read_or_alloc_page)(struct fscache_object *object,
+                                 struct page *page,
+                                 fscache_rw_complete_t end_io_func,
+                                 void *context,
+                                 unsigned long gfp);
+
+       /* request backing blocks for a list of pages be read or allocated in
+        * the cache */
+       int (*read_or_alloc_pages)(struct fscache_object *object,
+                                  struct address_space *mapping,
+                                  struct list_head *pages,
+                                  unsigned *nr_pages,
+                                  fscache_rw_complete_t end_io_func,
+                                  void *context,
+                                  unsigned long gfp);
+
+       /* request a backing block for a page be allocated in the cache so that
+        * it can be written directly */
+       int (*allocate_page)(struct fscache_object *object,
+                            struct page *page,
+                            unsigned long gfp);
+
+       /* write a page to its backing block in the cache */
+       int (*write_page)(struct fscache_object *object,
+                         struct page *page,
+                         fscache_rw_complete_t end_io_func,
+                         void *context,
+                         unsigned long gfp);
+
+       /* write several pages to their backing blocks in the cache */
+       int (*write_pages)(struct fscache_object *object,
+                          struct pagevec *pagevec,
+                          fscache_rw_complete_t end_io_func,
+                          void *context,
+                          unsigned long gfp);
+
+       /* detach backing block from a bunch of pages */
+       void (*uncache_pages)(struct fscache_object *object,
+                            struct pagevec *pagevec);
+
+       /* dissociate a cache from all the pages it was backing */
+       void (*dissociate_pages)(struct fscache_cache *cache);
+};
+
+/*****************************************************************************/
+/*
+ * data file or index object cookie
+ * - a file will only appear in one cache
+ * - a request to cache a file may or may not be honoured, subject to
+ *   constraints such as disc space
+ * - indexes files are created on disc just-in-time
+ */
+struct fscache_cookie {
+       atomic_t                        usage;          /* number of users of this cookie */
+       atomic_t                        children;       /* number of children of this cookie */
+       struct rw_semaphore             sem;            /* list creation vs scan lock */
+       struct hlist_head               backing_objects; /* object(s) backing this file/index */
+       struct fscache_cookie_def       *def;           /* definition */
+       struct fscache_cookie           *parent;        /* parent of this entry */
+       struct fscache_netfs            *netfs;         /* owner network fs definition */
+       void                            *netfs_data;    /* back pointer to netfs */
+};
+
+extern struct fscache_cookie fscache_fsdef_index;
+
+/*****************************************************************************/
+/*
+ * on-disc cache file or index handle
+ */
+struct fscache_object {
+       unsigned long                   flags;
+#define FSCACHE_OBJECT_RELEASING       0       /* T if object is being released */
+#define FSCACHE_OBJECT_RECYCLING       1       /* T if object is being retired */
+#define FSCACHE_OBJECT_WITHDRAWN       2       /* T if object has been withdrawn */
+
+       struct list_head                cache_link;     /* link in cache->object_list */
+       struct hlist_node               cookie_link;    /* link in cookie->backing_objects */
+       struct fscache_cache            *cache;         /* cache that supplied this object */
+       struct fscache_cookie           *cookie;        /* netfs's file/index object */
+};
+
+static inline
+void fscache_object_init(struct fscache_object *object)
+{
+       object->flags = 0;
+       INIT_LIST_HEAD(&object->cache_link);
+       INIT_HLIST_NODE(&object->cookie_link);
+       object->cache = NULL;
+       object->cookie = NULL;
+}
+
+/* find the parent index object for a object */
+static inline
+struct fscache_object *fscache_find_parent_object(struct fscache_object *object)
+{
+       struct fscache_object *parent;
+       struct fscache_cookie *cookie = object->cookie;
+       struct fscache_cache *cache = object->cache;
+       struct hlist_node *_p;
+
+       hlist_for_each_entry(parent, _p,
+                            &cookie->parent->backing_objects,
+                            cookie_link
+                            ) {
+               if (parent->cache == cache)
+                       return parent;
+       }
+
+       return NULL;
+}
+
+/* get an extra reference to a context */
+static inline
+void *fscache_get_context(struct fscache_cookie *cookie, void *context)
+{
+       if (cookie->def->get_context)
+               cookie->def->get_context(cookie->netfs_data, context);
+       return context;
+}
+
+/* release an extra reference to a context */
+static inline
+void fscache_put_context(struct fscache_cookie *cookie, void *context)
+{
+       if (cookie->def->put_context)
+               cookie->def->put_context(cookie->netfs_data, context);
+}
+
+#endif /* _LINUX_FSCACHE_CACHE_H */
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
new file mode 100644 (file)
index 0000000..867ab9e
--- /dev/null
@@ -0,0 +1,495 @@
+/* fscache.h: general filesystem caching interface
+ *
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * NOTE!!! See:
+ *
+ *     Documentation/filesystems/caching/netfs-api.txt
+ *
+ * for a description of the network filesystem interface declared here.
+ */
+
+#ifndef _LINUX_FSCACHE_H
+#define _LINUX_FSCACHE_H
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/pagemap.h>
+#include <linux/pagevec.h>
+
+struct pagevec;
+struct fscache_cache_tag;
+struct fscache_cookie;
+struct fscache_netfs;
+struct fscache_netfs_operations;
+
+typedef void (*fscache_rw_complete_t)(struct page *page,
+                                     void *context,
+                                     int error);
+
+/* result of index entry consultation */
+typedef enum {
+       FSCACHE_CHECKAUX_OKAY,          /* entry okay as is */
+       FSCACHE_CHECKAUX_NEEDS_UPDATE,  /* entry requires update */
+       FSCACHE_CHECKAUX_OBSOLETE,      /* entry requires deletion */
+} fscache_checkaux_t;
+
+/*****************************************************************************/
+/*
+ * fscache cookie definition
+ */
+struct fscache_cookie_def
+{
+       /* name of cookie type */
+       char name[16];
+
+       /* cookie type */
+       uint8_t type;
+#define FSCACHE_COOKIE_TYPE_INDEX      0
+#define FSCACHE_COOKIE_TYPE_DATAFILE   1
+
+       /* select the cache into which to insert an entry in this index
+        * - optional
+        * - should return a cache identifier or NULL to cause the cache to be
+        *   inherited from the parent if possible or the first cache picked
+        *   for a non-index file if not
+        */
+       struct fscache_cache_tag *(*select_cache)(const void *parent_netfs_data,
+                                                 const void *cookie_netfs_data);
+
+       /* get an index key
+        * - should store the key data in the buffer
+        * - should return the amount of amount stored
+        * - not permitted to return an error
+        * - the netfs data from the cookie being used as the source is
+        *   presented
+        */
+       uint16_t (*get_key)(const void *cookie_netfs_data,
+                           void *buffer,
+                           uint16_t bufmax);
+
+       /* get certain file attributes from the netfs data
+        * - this function can be absent for an index
+        * - not permitted to return an error
+        * - the netfs data from the cookie being used as the source is
+        *   presented
+        */
+       void (*get_attr)(const void *cookie_netfs_data, uint64_t *size);
+
+       /* get the auxilliary data from netfs data
+        * - this function can be absent if the index carries no state data
+        * - should store the auxilliary data in the buffer
+        * - should return the amount of amount stored
+        * - not permitted to return an error
+        * - the netfs data from the cookie being used as the source is
+        *   presented
+        */
+       uint16_t (*get_aux)(const void *cookie_netfs_data,
+                           void *buffer,
+                           uint16_t bufmax);
+
+       /* consult the netfs about the state of an object
+        * - this function can be absent if the index carries no state data
+        * - the netfs data from the cookie being used as the target is
+        *   presented, as is the auxilliary data
+        */
+       fscache_checkaux_t (*check_aux)(void *cookie_netfs_data,
+                                       const void *data,
+                                       uint16_t datalen);
+
+       /* get an extra reference on a read context
+        * - this function can be absent if the completion function doesn't
+        *   require a context
+        */
+       void (*get_context)(void *cookie_netfs_data, void *context);
+
+       /* release an extra reference on a read context
+        * - this function can be absent if the completion function doesn't
+        *   require a context
+        */
+       void (*put_context)(void *cookie_netfs_data, void *context);
+
+       /* indicate pages that now have cache metadata retained
+        * - this function should mark the specified pages as now being cached
+        */
+       void (*mark_pages_cached)(void *cookie_netfs_data,
+                                 struct address_space *mapping,
+                                 struct pagevec *cached_pvec);
+
+       /* indicate the cookie is no longer cached
+        * - this function is called when the backing store currently caching
+        *   a cookie is removed
+        * - the netfs should use this to clean up any markers indicating
+        *   cached pages
+        * - this is mandatory for any object that may have data
+        */
+       void (*now_uncached)(void *cookie_netfs_data);
+};
+
+/* pattern used to fill dead space in an index entry */
+#define FSCACHE_INDEX_DEADFILL_PATTERN 0x79
+
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern struct fscache_cookie *__fscache_acquire_cookie(struct fscache_cookie *parent,
+                                                      struct fscache_cookie_def *def,
+                                                      void *netfs_data);
+
+extern void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
+                                       int retire);
+
+extern void __fscache_update_cookie(struct fscache_cookie *cookie);
+#endif
+
+static inline
+struct fscache_cookie *fscache_acquire_cookie(struct fscache_cookie *parent,
+                                             struct fscache_cookie_def *def,
+                                             void *netfs_data)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (parent)
+               return __fscache_acquire_cookie(parent, def, netfs_data);
+#endif
+       return NULL;
+}
+
+static inline
+void fscache_relinquish_cookie(struct fscache_cookie *cookie,
+                              int retire)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               __fscache_relinquish_cookie(cookie, retire);
+#endif
+}
+
+static inline
+void fscache_update_cookie(struct fscache_cookie *cookie)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               __fscache_update_cookie(cookie);
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * pin or unpin a cookie in a cache
+ * - only available for data cookies
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_pin_cookie(struct fscache_cookie *cookie);
+extern void __fscache_unpin_cookie(struct fscache_cookie *cookie);
+#endif
+
+static inline
+int fscache_pin_cookie(struct fscache_cookie *cookie)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_pin_cookie(cookie);
+#endif
+       return -ENOBUFS;
+}
+
+static inline
+void fscache_unpin_cookie(struct fscache_cookie *cookie)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               __fscache_unpin_cookie(cookie);
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * fscache cached network filesystem type
+ * - name, version and ops must be filled in before registration
+ * - all other fields will be set during registration
+ */
+struct fscache_netfs
+{
+       uint32_t                        version;        /* indexing version */
+       const char                      *name;          /* filesystem name */
+       struct fscache_cookie           *primary_index;
+       struct fscache_netfs_operations *ops;
+       struct list_head                link;           /* internal link */
+};
+
+struct fscache_netfs_operations
+{
+};
+
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_register_netfs(struct fscache_netfs *netfs);
+extern void __fscache_unregister_netfs(struct fscache_netfs *netfs);
+#endif
+
+static inline
+int fscache_register_netfs(struct fscache_netfs *netfs)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       return __fscache_register_netfs(netfs);
+#else
+       return 0;
+#endif
+}
+
+static inline
+void fscache_unregister_netfs(struct fscache_netfs *netfs)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       __fscache_unregister_netfs(netfs);
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * look up a cache tag
+ * - cache tags are used to select specific caches in which to cache indexes
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name);
+extern void __fscache_release_cache_tag(struct fscache_cache_tag *tag);
+#endif
+
+static inline
+struct fscache_cache_tag *fscache_lookup_cache_tag(const char *name)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       return __fscache_lookup_cache_tag(name);
+#else
+       return NULL;
+#endif
+}
+
+static inline
+void fscache_release_cache_tag(struct fscache_cache_tag *tag)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       __fscache_release_cache_tag(tag);
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * set the data size on a cached object
+ * - no pages beyond the end of the object will be accessible
+ * - returns -ENOBUFS if the file is not backed
+ * - returns -ENOSPC if a pinned file of that size can't be stored
+ * - returns 0 if okay
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size);
+#endif
+
+static inline
+int fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_set_i_size(cookie, i_size);
+#endif
+       return -ENOBUFS;
+}
+
+/*****************************************************************************/
+/*
+ * reserve data space for a cached object
+ * - returns -ENOBUFS if the file is not backed
+ * - returns -ENOSPC if there isn't enough space to honour the reservation
+ * - returns 0 if okay
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_reserve_space(struct fscache_cookie *cookie, loff_t size);
+#endif
+
+static inline
+int fscache_reserve_space(struct fscache_cookie *cookie, loff_t size)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_reserve_space(cookie, size);
+#endif
+       return -ENOBUFS;
+}
+
+/*****************************************************************************/
+/*
+ * read a page from the cache or allocate a block in which to store it
+ * - if the page is not backed by a file:
+ *   - -ENOBUFS will be returned and nothing more will be done
+ * - else if the page is backed by a block in the cache:
+ *   - a read will be started which will call end_io_func on completion
+ * - else if the page is unbacked:
+ *   - a block will be allocated
+ *   - -ENODATA will be returned
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
+                                       struct page *page,
+                                       fscache_rw_complete_t end_io_func,
+                                       void *context,
+                                       gfp_t gfp);
+#endif
+
+static inline
+int fscache_read_or_alloc_page(struct fscache_cookie *cookie,
+                              struct page *page,
+                              fscache_rw_complete_t end_io_func,
+                              void *context,
+                              gfp_t gfp)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_read_or_alloc_page(cookie, page, end_io_func,
+                                                   context, gfp);
+#endif
+       return -ENOBUFS;
+}
+
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
+                                        struct address_space *mapping,
+                                        struct list_head *pages,
+                                        unsigned *nr_pages,
+                                        fscache_rw_complete_t end_io_func,
+                                        void *context,
+                                        gfp_t gfp);
+#endif
+
+static inline
+int fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
+                               struct address_space *mapping,
+                               struct list_head *pages,
+                               unsigned *nr_pages,
+                               fscache_rw_complete_t end_io_func,
+                               void *context,
+                               gfp_t gfp)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_read_or_alloc_pages(cookie, mapping, pages,
+                                                    nr_pages, end_io_func,
+                                                    context, gfp);
+#endif
+       return -ENOBUFS;
+}
+
+/*
+ * allocate a block in which to store a page
+ * - if the page is not backed by a file:
+ *   - -ENOBUFS will be returned and nothing more will be done
+ * - else
+ *   - a block will be allocated if there isn't one
+ *   - 0 will be returned
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_alloc_page(struct fscache_cookie *cookie,
+                               struct page *page,
+                               gfp_t gfp);
+#endif
+
+static inline
+int fscache_alloc_page(struct fscache_cookie *cookie,
+                      struct page *page,
+                      gfp_t gfp)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_alloc_page(cookie, page, gfp);
+#endif
+       return -ENOBUFS;
+}
+
+/*
+ * request a page be stored in the cache
+ * - this request may be ignored if no cache block is currently allocated, in
+ *   which case it:
+ *   - returns -ENOBUFS
+ * - if a cache block was already allocated:
+ *   - a BIO will be dispatched to write the page (end_io_func will be called
+ *     from the completion function)
+ *   - returns 0
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern int __fscache_write_page(struct fscache_cookie *cookie,
+                               struct page *page,
+                               fscache_rw_complete_t end_io_func,
+                               void *context,
+                               gfp_t gfp);
+
+extern int __fscache_write_pages(struct fscache_cookie *cookie,
+                                struct pagevec *pagevec,
+                                fscache_rw_complete_t end_io_func,
+                                void *context,
+                                gfp_t gfp);
+#endif
+
+static inline
+int fscache_write_page(struct fscache_cookie *cookie,
+                      struct page *page,
+                      fscache_rw_complete_t end_io_func,
+                      void *context,
+                      gfp_t gfp)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_write_page(cookie, page, end_io_func,
+                                           context, gfp);
+#endif
+       return -ENOBUFS;
+}
+
+static inline
+int fscache_write_pages(struct fscache_cookie *cookie,
+                       struct pagevec *pagevec,
+                       fscache_rw_complete_t end_io_func,
+                       void *context,
+                       gfp_t gfp)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               return __fscache_write_pages(cookie, pagevec, end_io_func,
+                                            context, gfp);
+#endif
+       return -ENOBUFS;
+}
+
+/*
+ * indicate that caching is no longer required on a page
+ * - note: cannot cancel any outstanding BIOs between this page and the cache
+ */
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+extern void __fscache_uncache_page(struct fscache_cookie *cookie,
+                                  struct page *page);
+extern void __fscache_uncache_pages(struct fscache_cookie *cookie,
+                                   struct pagevec *pagevec);
+#endif
+
+static inline
+void fscache_uncache_page(struct fscache_cookie *cookie,
+                         struct page *page)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               __fscache_uncache_page(cookie, page);
+#endif
+}
+
+static inline
+void fscache_uncache_pagevec(struct fscache_cookie *cookie,
+                            struct pagevec *pagevec)
+{
+#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE)
+       if (cookie)
+               __fscache_uncache_pages(cookie, pagevec);
+#endif
+}
+
+#endif /* _LINUX_FSCACHE_H */
diff --git a/include/linux/hdlc/Kbuild b/include/linux/hdlc/Kbuild
new file mode 100644 (file)
index 0000000..1fb2644
--- /dev/null
@@ -0,0 +1 @@
+header-y += ioctl.h
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
new file mode 100644 (file)
index 0000000..21ea761
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+       Hardware Random Number Generator
+
+       Please read Documentation/hw_random.txt for details on use.
+
+       ----------------------------------------------------------
+       This software may be used and distributed according to the terms
+        of the GNU General Public License, incorporated herein by reference.
+
+ */
+
+#ifndef LINUX_HWRANDOM_H_
+#define LINUX_HWRANDOM_H_
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+/**
+ * struct hwrng - Hardware Random Number Generator driver
+ * @name:              Unique RNG name.
+ * @init:              Initialization callback (can be NULL).
+ * @cleanup:           Cleanup callback (can be NULL).
+ * @data_present:      Callback to determine if data is available
+ *                     on the RNG. If NULL, it is assumed that
+ *                     there is always data available.
+ * @data_read:         Read data from the RNG device.
+ *                     Returns the number of lower random bytes in "data".
+ *                     Must not be NULL.
+ * @priv:              Private data, for use by the RNG driver.
+ */
+struct hwrng {
+       const char *name;
+       int (*init)(struct hwrng *rng);
+       void (*cleanup)(struct hwrng *rng);
+       int (*data_present)(struct hwrng *rng);
+       int (*data_read)(struct hwrng *rng, u32 *data);
+       unsigned long priv;
+
+       /* internal. */
+       struct list_head list;
+};
+
+/** Register a new Hardware Random Number Generator driver. */
+extern int hwrng_register(struct hwrng *rng);
+/** Unregister a Hardware Random Number Generator driver. */
+extern void hwrng_unregister(struct hwrng *rng);
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_HWRANDOM_H_ */
diff --git a/include/linux/i2c-ocores.h b/include/linux/i2c-ocores.h
new file mode 100644 (file)
index 0000000..8ed591b
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * i2c-ocores.h - definitions for the i2c-ocores interface
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_I2C_OCORES_H
+#define _LINUX_I2C_OCORES_H
+
+struct ocores_i2c_platform_data {
+       u32 regstep;   /* distance between registers */
+       u32 clock_khz; /* input clock in kHz */
+};
+
+#endif /* _LINUX_I2C_OCORES_H */
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
new file mode 100644 (file)
index 0000000..412e025
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * include/linux/irqflags.h
+ *
+ * IRQ flags tracing: follow the state of the hardirq and softirq flags and
+ * provide callbacks for transitions between ON and OFF states.
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() macros from the lowlevel headers.
+ */
+#ifndef _LINUX_TRACE_IRQFLAGS_H
+#define _LINUX_TRACE_IRQFLAGS_H
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+  extern void trace_hardirqs_on(void);
+  extern void trace_hardirqs_off(void);
+  extern void trace_softirqs_on(unsigned long ip);
+  extern void trace_softirqs_off(unsigned long ip);
+# define trace_hardirq_context(p)      ((p)->hardirq_context)
+# define trace_softirq_context(p)      ((p)->softirq_context)
+# define trace_hardirqs_enabled(p)     ((p)->hardirqs_enabled)
+# define trace_softirqs_enabled(p)     ((p)->softirqs_enabled)
+# define trace_hardirq_enter() do { current->hardirq_context++; } while (0)
+# define trace_hardirq_exit()  do { current->hardirq_context--; } while (0)
+# define trace_softirq_enter() do { current->softirq_context++; } while (0)
+# define trace_softirq_exit()  do { current->softirq_context--; } while (0)
+# define INIT_TRACE_IRQFLAGS   .softirqs_enabled = 1,
+#else
+# define trace_hardirqs_on()           do { } while (0)
+# define trace_hardirqs_off()          do { } while (0)
+# define trace_softirqs_on(ip)         do { } while (0)
+# define trace_softirqs_off(ip)                do { } while (0)
+# define trace_hardirq_context(p)      0
+# define trace_softirq_context(p)      0
+# define trace_hardirqs_enabled(p)     0
+# define trace_softirqs_enabled(p)     0
+# define trace_hardirq_enter()         do { } while (0)
+# define trace_hardirq_exit()          do { } while (0)
+# define trace_softirq_enter()         do { } while (0)
+# define trace_softirq_exit()          do { } while (0)
+# define INIT_TRACE_IRQFLAGS
+#endif
+
+#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
+
+#include <asm/irqflags.h>
+
+#define local_irq_enable() \
+       do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
+#define local_irq_disable() \
+       do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
+#define local_irq_save(flags) \
+       do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0)
+
+#define local_irq_restore(flags)                               \
+       do {                                                    \
+               if (raw_irqs_disabled_flags(flags)) {           \
+                       raw_local_irq_restore(flags);           \
+                       trace_hardirqs_off();                   \
+               } else {                                        \
+                       trace_hardirqs_on();                    \
+                       raw_local_irq_restore(flags);           \
+               }                                               \
+       } while (0)
+#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
+/*
+ * The local_irq_*() APIs are equal to the raw_local_irq*()
+ * if !TRACE_IRQFLAGS.
+ */
+# define raw_local_irq_disable()       local_irq_disable()
+# define raw_local_irq_enable()                local_irq_enable()
+# define raw_local_irq_save(flags)     local_irq_save(flags)
+# define raw_local_irq_restore(flags)  local_irq_restore(flags)
+#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
+
+#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
+#define safe_halt()                                            \
+       do {                                                    \
+               trace_hardirqs_on();                            \
+               raw_safe_halt();                                \
+       } while (0)
+
+#define local_save_flags(flags)                raw_local_save_flags(flags)
+
+#define irqs_disabled()                                                \
+({                                                             \
+       unsigned long flags;                                    \
+                                                               \
+       raw_local_save_flags(flags);                            \
+       raw_irqs_disabled_flags(flags);                         \
+})
+
+#define irqs_disabled_flags(flags)     raw_irqs_disabled_flags(flags)
+#endif         /* CONFIG_X86 */
+
+#endif
diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h
new file mode 100644 (file)
index 0000000..881883c
--- /dev/null
@@ -0,0 +1,25 @@
+/* irqreturn.h */
+#ifndef _LINUX_IRQRETURN_H
+#define _LINUX_IRQRETURN_H
+
+/*
+ * For 2.4.x compatibility, 2.4.x can use
+ *
+ *     typedef void irqreturn_t;
+ *     #define IRQ_NONE
+ *     #define IRQ_HANDLED
+ *     #define IRQ_RETVAL(x)
+ *
+ * To mix old-style and new-style irq handler returns.
+ *
+ * IRQ_NONE means we didn't handle it.
+ * IRQ_HANDLED means that we did have a valid interrupt and handled it.
+ * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled)
+ */
+typedef int irqreturn_t;
+
+#define IRQ_NONE       (0)
+#define IRQ_HANDLED    (1)
+#define IRQ_RETVAL(x)  ((x) != 0)
+
+#endif
diff --git a/include/linux/isa.h b/include/linux/isa.h
new file mode 100644 (file)
index 0000000..1b85533
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * ISA bus.
+ */
+
+#ifndef __LINUX_ISA_H
+#define __LINUX_ISA_H
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+struct isa_driver {
+       int (*match)(struct device *, unsigned int);
+       int (*probe)(struct device *, unsigned int);
+       int (*remove)(struct device *, unsigned int);
+       void (*shutdown)(struct device *, unsigned int);
+       int (*suspend)(struct device *, unsigned int, pm_message_t);
+       int (*resume)(struct device *, unsigned int);
+
+       struct device_driver driver;
+       struct device *devices;
+};
+
+#define to_isa_driver(x) container_of((x), struct isa_driver, driver)
+
+int isa_register_driver(struct isa_driver *, unsigned int);
+void isa_unregister_driver(struct isa_driver *);
+
+#endif /* __LINUX_ISA_H */
diff --git a/include/linux/isdn/Kbuild b/include/linux/isdn/Kbuild
new file mode 100644 (file)
index 0000000..991cdb2
--- /dev/null
@@ -0,0 +1 @@
+header-y += capicmd.h
diff --git a/include/linux/license.h b/include/linux/license.h
new file mode 100644 (file)
index 0000000..decdbf4
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __LICENSE_H
+#define __LICENSE_H
+
+static inline int license_is_gpl_compatible(const char *license)
+{
+       return (strcmp(license, "GPL") == 0
+               || strcmp(license, "GPL v2") == 0
+               || strcmp(license, "GPL and additional rights") == 0
+               || strcmp(license, "Dual BSD/GPL") == 0
+               || strcmp(license, "Dual MIT/GPL") == 0
+               || strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+#endif
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
new file mode 100644 (file)
index 0000000..7167872
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Runtime locking correctness validator
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * see Documentation/lockdep-design.txt for more details.
+ */
+#ifndef __LINUX_LOCKDEP_H
+#define __LINUX_LOCKDEP_H
+
+#include <linux/linkage.h>
+#include <linux/list.h>
+#include <linux/debug_locks.h>
+#include <linux/stacktrace.h>
+
+#ifdef CONFIG_LOCKDEP
+
+/*
+ * Lock-class usage-state bits:
+ */
+enum lock_usage_bit
+{
+       LOCK_USED = 0,
+       LOCK_USED_IN_HARDIRQ,
+       LOCK_USED_IN_SOFTIRQ,
+       LOCK_ENABLED_SOFTIRQS,
+       LOCK_ENABLED_HARDIRQS,
+       LOCK_USED_IN_HARDIRQ_READ,
+       LOCK_USED_IN_SOFTIRQ_READ,
+       LOCK_ENABLED_SOFTIRQS_READ,
+       LOCK_ENABLED_HARDIRQS_READ,
+       LOCK_USAGE_STATES
+};
+
+/*
+ * Usage-state bitmasks:
+ */
+#define LOCKF_USED                     (1 << LOCK_USED)
+#define LOCKF_USED_IN_HARDIRQ          (1 << LOCK_USED_IN_HARDIRQ)
+#define LOCKF_USED_IN_SOFTIRQ          (1 << LOCK_USED_IN_SOFTIRQ)
+#define LOCKF_ENABLED_HARDIRQS         (1 << LOCK_ENABLED_HARDIRQS)
+#define LOCKF_ENABLED_SOFTIRQS         (1 << LOCK_ENABLED_SOFTIRQS)
+
+#define LOCKF_ENABLED_IRQS (LOCKF_ENABLED_HARDIRQS | LOCKF_ENABLED_SOFTIRQS)
+#define LOCKF_USED_IN_IRQ (LOCKF_USED_IN_HARDIRQ | LOCKF_USED_IN_SOFTIRQ)
+
+#define LOCKF_USED_IN_HARDIRQ_READ     (1 << LOCK_USED_IN_HARDIRQ_READ)
+#define LOCKF_USED_IN_SOFTIRQ_READ     (1 << LOCK_USED_IN_SOFTIRQ_READ)
+#define LOCKF_ENABLED_HARDIRQS_READ    (1 << LOCK_ENABLED_HARDIRQS_READ)
+#define LOCKF_ENABLED_SOFTIRQS_READ    (1 << LOCK_ENABLED_SOFTIRQS_READ)
+
+#define LOCKF_ENABLED_IRQS_READ \
+               (LOCKF_ENABLED_HARDIRQS_READ | LOCKF_ENABLED_SOFTIRQS_READ)
+#define LOCKF_USED_IN_IRQ_READ \
+               (LOCKF_USED_IN_HARDIRQ_READ | LOCKF_USED_IN_SOFTIRQ_READ)
+
+#define MAX_LOCKDEP_SUBCLASSES         8UL
+
+/*
+ * Lock-classes are keyed via unique addresses, by embedding the
+ * lockclass-key into the kernel (or module) .data section. (For
+ * static locks we use the lock address itself as the key.)
+ */
+struct lockdep_subclass_key {
+       char __one_byte;
+} __attribute__ ((__packed__));
+
+struct lock_class_key {
+       struct lockdep_subclass_key     subkeys[MAX_LOCKDEP_SUBCLASSES];
+};
+
+/*
+ * The lock-class itself:
+ */
+struct lock_class {
+       /*
+        * class-hash:
+        */
+       struct list_head                hash_entry;
+
+       /*
+        * global list of all lock-classes:
+        */
+       struct list_head                lock_entry;
+
+       struct lockdep_subclass_key     *key;
+       unsigned int                    subclass;
+
+       /*
+        * IRQ/softirq usage tracking bits:
+        */
+       unsigned long                   usage_mask;
+       struct stack_trace              usage_traces[LOCK_USAGE_STATES];
+
+       /*
+        * These fields represent a directed graph of lock dependencies,
+        * to every node we attach a list of "forward" and a list of
+        * "backward" graph nodes.
+        */
+       struct list_head                locks_after, locks_before;
+
+       /*
+        * Generation counter, when doing certain classes of graph walking,
+        * to ensure that we check one node only once:
+        */
+       unsigned int                    version;
+
+       /*
+        * Statistics counter:
+        */
+       unsigned long                   ops;
+
+       const char                      *name;
+       int                             name_version;
+};
+
+/*
+ * Map the lock object (the lock instance) to the lock-class object.
+ * This is embedded into specific lock instances:
+ */
+struct lockdep_map {
+       struct lock_class_key           *key;
+       struct lock_class               *class_cache;
+       const char                      *name;
+};
+
+/*
+ * Every lock has a list of other locks that were taken after it.
+ * We only grow the list, never remove from it:
+ */
+struct lock_list {
+       struct list_head                entry;
+       struct lock_class               *class;
+       struct stack_trace              trace;
+};
+
+/*
+ * We record lock dependency chains, so that we can cache them:
+ */
+struct lock_chain {
+       struct list_head                entry;
+       u64                             chain_key;
+};
+
+struct held_lock {
+       /*
+        * One-way hash of the dependency chain up to this point. We
+        * hash the hashes step by step as the dependency chain grows.
+        *
+        * We use it for dependency-caching and we skip detection
+        * passes and dependency-updates if there is a cache-hit, so
+        * it is absolutely critical for 100% coverage of the validator
+        * to have a unique key value for every unique dependency path
+        * that can occur in the system, to make a unique hash value
+        * as likely as possible - hence the 64-bit width.
+        *
+        * The task struct holds the current hash value (initialized
+        * with zero), here we store the previous hash value:
+        */
+       u64                             prev_chain_key;
+       struct lock_class               *class;
+       unsigned long                   acquire_ip;
+       struct lockdep_map              *instance;
+
+       /*
+        * The lock-stack is unified in that the lock chains of interrupt
+        * contexts nest ontop of process context chains, but we 'separate'
+        * the hashes by starting with 0 if we cross into an interrupt
+        * context, and we also keep do not add cross-context lock
+        * dependencies - the lock usage graph walking covers that area
+        * anyway, and we'd just unnecessarily increase the number of
+        * dependencies otherwise. [Note: hardirq and softirq contexts
+        * are separated from each other too.]
+        *
+        * The following field is used to detect when we cross into an
+        * interrupt context:
+        */
+       int                             irq_context;
+       int                             trylock;
+       int                             read;
+       int                             check;
+       int                             hardirqs_off;
+};
+
+/*
+ * Initialization, self-test and debugging-output methods:
+ */
+extern void lockdep_init(void);
+extern void lockdep_info(void);
+extern void lockdep_reset(void);
+extern void lockdep_reset_lock(struct lockdep_map *lock);
+extern void lockdep_free_key_range(void *start, unsigned long size);
+
+extern void lockdep_off(void);
+extern void lockdep_on(void);
+extern int lockdep_internal(void);
+
+/*
+ * These methods are used by specific locking variants (spinlocks,
+ * rwlocks, mutexes and rwsems) to pass init/acquire/release events
+ * to lockdep:
+ */
+
+extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
+                            struct lock_class_key *key, int subclass);
+
+/*
+ * Reinitialize a lock key - for cases where there is special locking or
+ * special initialization of locks so that the validator gets the scope
+ * of dependencies wrong: they are either too broad (they need a class-split)
+ * or they are too narrow (they suffer from a false class-split):
+ */
+#define lockdep_set_class(lock, key) \
+               lockdep_init_map(&(lock)->dep_map, #key, key, 0)
+#define lockdep_set_class_and_name(lock, key, name) \
+               lockdep_init_map(&(lock)->dep_map, name, key, 0)
+#define lockdep_set_class_and_subclass(lock, key, sub) \
+               lockdep_init_map(&(lock)->dep_map, #key, key, sub)
+
+/*
+ * Acquire a lock.
+ *
+ * Values for "read":
+ *
+ *   0: exclusive (write) acquire
+ *   1: read-acquire (no recursion allowed)
+ *   2: read-acquire with same-instance recursion allowed
+ *
+ * Values for check:
+ *
+ *   0: disabled
+ *   1: simple checks (freeing, held-at-exit-time, etc.)
+ *   2: full validation
+ */
+extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+                        int trylock, int read, int check, unsigned long ip);
+
+extern void lock_release(struct lockdep_map *lock, int nested,
+                        unsigned long ip);
+
+# define INIT_LOCKDEP                          .lockdep_recursion = 0,
+
+#else /* !LOCKDEP */
+
+static inline void lockdep_off(void)
+{
+}
+
+static inline void lockdep_on(void)
+{
+}
+
+static inline int lockdep_internal(void)
+{
+       return 0;
+}
+
+# define lock_acquire(l, s, t, r, c, i)                do { } while (0)
+# define lock_release(l, n, i)                 do { } while (0)
+# define lockdep_init()                                do { } while (0)
+# define lockdep_info()                                do { } while (0)
+# define lockdep_init_map(lock, name, key, sub)        do { (void)(key); } while (0)
+# define lockdep_set_class(lock, key)          do { (void)(key); } while (0)
+# define lockdep_set_class_and_name(lock, key, name) \
+               do { (void)(key); } while (0)
+#define lockdep_set_class_and_subclass(lock, key, sub) \
+               do { (void)(key); } while (0)
+# define INIT_LOCKDEP
+# define lockdep_reset()               do { debug_locks = 1; } while (0)
+# define lockdep_free_key_range(start, size)   do { } while (0)
+/*
+ * The class key takes no space if lockdep is disabled:
+ */
+struct lock_class_key { };
+#endif /* !LOCKDEP */
+
+#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
+extern void early_init_irq_lock_class(void);
+#else
+# define early_init_irq_lock_class()           do { } while (0)
+#endif
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+extern void early_boot_irqs_off(void);
+extern void early_boot_irqs_on(void);
+#else
+# define early_boot_irqs_off()                 do { } while (0)
+# define early_boot_irqs_on()                  do { } while (0)
+#endif
+
+/*
+ * For trivial one-depth nesting of a lock-class, the following
+ * global define can be used. (Subsystems with multiple levels
+ * of nesting should define their own lock-nesting subclasses.)
+ */
+#define SINGLE_DEPTH_NESTING                   1
+
+/*
+ * Map the dependency ops to NOP or to real lockdep ops, depending
+ * on the per lock-class debug mode:
+ */
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# ifdef CONFIG_PROVE_LOCKING
+#  define spin_acquire(l, s, t, i)             lock_acquire(l, s, t, 0, 2, i)
+# else
+#  define spin_acquire(l, s, t, i)             lock_acquire(l, s, t, 0, 1, i)
+# endif
+# define spin_release(l, n, i)                 lock_release(l, n, i)
+#else
+# define spin_acquire(l, s, t, i)              do { } while (0)
+# define spin_release(l, n, i)                 do { } while (0)
+#endif
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# ifdef CONFIG_PROVE_LOCKING
+#  define rwlock_acquire(l, s, t, i)           lock_acquire(l, s, t, 0, 2, i)
+#  define rwlock_acquire_read(l, s, t, i)      lock_acquire(l, s, t, 2, 2, i)
+# else
+#  define rwlock_acquire(l, s, t, i)           lock_acquire(l, s, t, 0, 1, i)
+#  define rwlock_acquire_read(l, s, t, i)      lock_acquire(l, s, t, 2, 1, i)
+# endif
+# define rwlock_release(l, n, i)               lock_release(l, n, i)
+#else
+# define rwlock_acquire(l, s, t, i)            do { } while (0)
+# define rwlock_acquire_read(l, s, t, i)       do { } while (0)
+# define rwlock_release(l, n, i)               do { } while (0)
+#endif
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# ifdef CONFIG_PROVE_LOCKING
+#  define mutex_acquire(l, s, t, i)            lock_acquire(l, s, t, 0, 2, i)
+# else
+#  define mutex_acquire(l, s, t, i)            lock_acquire(l, s, t, 0, 1, i)
+# endif
+# define mutex_release(l, n, i)                        lock_release(l, n, i)
+#else
+# define mutex_acquire(l, s, t, i)             do { } while (0)
+# define mutex_release(l, n, i)                        do { } while (0)
+#endif
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# ifdef CONFIG_PROVE_LOCKING
+#  define rwsem_acquire(l, s, t, i)            lock_acquire(l, s, t, 0, 2, i)
+#  define rwsem_acquire_read(l, s, t, i)       lock_acquire(l, s, t, 1, 2, i)
+# else
+#  define rwsem_acquire(l, s, t, i)            lock_acquire(l, s, t, 0, 1, i)
+#  define rwsem_acquire_read(l, s, t, i)       lock_acquire(l, s, t, 1, 1, i)
+# endif
+# define rwsem_release(l, n, i)                        lock_release(l, n, i)
+#else
+# define rwsem_acquire(l, s, t, i)             do { } while (0)
+# define rwsem_acquire_read(l, s, t, i)                do { } while (0)
+# define rwsem_release(l, n, i)                        do { } while (0)
+#endif
+
+#endif /* __LINUX_LOCKDEP_H */
diff --git a/include/linux/m41t00.h b/include/linux/m41t00.h
new file mode 100644 (file)
index 0000000..b423360
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Definitions for the ST M41T00 family of i2c rtc chips.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _M41T00_H
+#define _M41T00_H
+
+#define        M41T00_DRV_NAME         "m41t00"
+#define        M41T00_I2C_ADDR         0x68
+
+#define        M41T00_TYPE_M41T00      0
+#define        M41T00_TYPE_M41T81      81
+#define        M41T00_TYPE_M41T85      85
+
+struct m41t00_platform_data {
+       u8      type;
+       u8      i2c_addr;
+       u8      sqw_freq;
+};
+
+/* SQW output disabled, this is default value by power on */
+#define M41T00_SQW_DISABLE     (0)
+
+#define M41T00_SQW_32KHZ       (1<<4)          /* 32.768 KHz */
+#define M41T00_SQW_8KHZ                (2<<4)          /* 8.192 KHz */
+#define M41T00_SQW_4KHZ                (3<<4)          /* 4.096 KHz */
+#define M41T00_SQW_2KHZ                (4<<4)          /* 2.048 KHz */
+#define M41T00_SQW_1KHZ                (5<<4)          /* 1.024 KHz */
+#define M41T00_SQW_512HZ       (6<<4)          /* 512 Hz */
+#define M41T00_SQW_256HZ       (7<<4)          /* 256 Hz */
+#define M41T00_SQW_128HZ       (8<<4)          /* 128 Hz */
+#define M41T00_SQW_64HZ                (9<<4)          /* 64 Hz */
+#define M41T00_SQW_32HZ                (10<<4)         /* 32 Hz */
+#define M41T00_SQW_16HZ                (11<<4)         /* 16 Hz */
+#define M41T00_SQW_8HZ         (12<<4)         /* 8 Hz */
+#define M41T00_SQW_4HZ         (13<<4)         /* 4 Hz */
+#define M41T00_SQW_2HZ         (14<<4)         /* 2 Hz */
+#define M41T00_SQW_1HZ         (15<<4)         /* 1 Hz */
+
+extern ulong m41t00_get_rtc_time(void);
+extern int m41t00_set_rtc_time(ulong nowtime);
+
+#endif /* _M41T00_H */
diff --git a/include/linux/mtd/ndfc.h b/include/linux/mtd/ndfc.h
new file mode 100644 (file)
index 0000000..d0558a9
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  linux/include/linux/mtd/ndfc.h
+ *
+ *  Copyright (c) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Info:
+ *   Contains defines, datastructures for ndfc nand controller
+ *
+ */
+#ifndef __LINUX_MTD_NDFC_H
+#define __LINUX_MTD_NDFC_H
+
+/* NDFC Register definitions */
+#define NDFC_CMD               0x00
+#define NDFC_ALE               0x04
+#define NDFC_DATA              0x08
+#define NDFC_ECC               0x10
+#define NDFC_BCFG0             0x30
+#define NDFC_BCFG1             0x34
+#define NDFC_BCFG2             0x38
+#define NDFC_BCFG3             0x3c
+#define NDFC_CCR               0x40
+#define NDFC_STAT              0x44
+#define NDFC_HWCTL             0x48
+#define NDFC_REVID             0x50
+
+#define NDFC_STAT_IS_READY     0x01000000
+
+#define NDFC_CCR_RESET_CE      0x80000000 /* CE Reset */
+#define NDFC_CCR_RESET_ECC     0x40000000 /* ECC Reset */
+#define NDFC_CCR_RIE           0x20000000 /* Interrupt Enable on Device Rdy */
+#define NDFC_CCR_REN           0x10000000 /* Enable wait for Rdy in LinearR */
+#define NDFC_CCR_ROMEN         0x08000000 /* Enable ROM In LinearR */
+#define NDFC_CCR_ARE           0x04000000 /* Auto-Read Enable */
+#define NDFC_CCR_BS(x)         (((x) & 0x3) << 24) /* Select Bank on CE[x] */
+#define NDFC_CCR_BS_MASK       0x03000000 /* Select Bank */
+#define NDFC_CCR_ARAC0         0x00000000 /* 3 Addr, 1 Col 2 Row 512b page */
+#define NDFC_CCR_ARAC1         0x00001000 /* 4 Addr, 1 Col 3 Row 512b page */
+#define NDFC_CCR_ARAC2         0x00002000 /* 4 Addr, 2 Col 2 Row 2K page */
+#define NDFC_CCR_ARAC3         0x00003000 /* 5 Addr, 2 Col 3 Row 2K page */
+#define NDFC_CCR_ARAC_MASK     0x00003000 /* Auto-Read mode Addr Cycles */
+#define NDFC_CCR_RPG           0x0000C000 /* Auto-Read Page */
+#define NDFC_CCR_EBCC          0x00000004 /* EBC Configuration Completed */
+#define NDFC_CCR_DHC           0x00000002 /* Direct Hardware Control Enable */
+
+#define NDFC_BxCFG_EN          0x80000000 /* Bank Enable */
+#define NDFC_BxCFG_CED         0x40000000 /* nCE Style */
+#define NDFC_BxCFG_SZ_MASK     0x08000000 /* Bank Size */
+#define NDFC_BxCFG_SZ_8BIT     0x00000000 /* 8bit */
+#define NDFC_BxCFG_SZ_16BIT    0x08000000 /* 16bit */
+
+#define NDFC_MAX_BANKS         4
+
+struct ndfc_controller_settings {
+       uint32_t        ccr_settings;
+       uint64_t        ndfc_erpn;
+};
+
+struct ndfc_chip_settings {
+       uint32_t        bank_settings;
+};
+
+#endif
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
new file mode 100644 (file)
index 0000000..9a285ce
--- /dev/null
@@ -0,0 +1,38 @@
+header-y += nf_conntrack_sctp.h
+header-y += nf_conntrack_tuple_common.h
+header-y += nfnetlink_conntrack.h
+header-y += nfnetlink_log.h
+header-y += nfnetlink_queue.h
+header-y += xt_CLASSIFY.h
+header-y += xt_comment.h
+header-y += xt_connbytes.h
+header-y += xt_connmark.h
+header-y += xt_CONNMARK.h
+header-y += xt_conntrack.h
+header-y += xt_dccp.h
+header-y += xt_esp.h
+header-y += xt_helper.h
+header-y += xt_length.h
+header-y += xt_limit.h
+header-y += xt_mac.h
+header-y += xt_mark.h
+header-y += xt_MARK.h
+header-y += xt_multiport.h
+header-y += xt_NFQUEUE.h
+header-y += xt_pkttype.h
+header-y += xt_policy.h
+header-y += xt_realm.h
+header-y += xt_sctp.h
+header-y += xt_state.h
+header-y += xt_string.h
+header-y += xt_tcpmss.h
+header-y += xt_tcpudp.h
+header-y += xt_SECMARK.h
+header-y += xt_CONNSECMARK.h
+
+unifdef-y += nf_conntrack_common.h
+unifdef-y += nf_conntrack_ftp.h
+unifdef-y += nf_conntrack_tcp.h
+unifdef-y += nfnetlink.h
+unifdef-y += x_tables.h
+unifdef-y += xt_physdev.h
diff --git a/include/linux/netfilter/xt_CONNSECMARK.h b/include/linux/netfilter/xt_CONNSECMARK.h
new file mode 100644 (file)
index 0000000..c6bd754
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _XT_CONNSECMARK_H_target
+#define _XT_CONNSECMARK_H_target
+
+enum {
+       CONNSECMARK_SAVE = 1,
+       CONNSECMARK_RESTORE,
+};
+
+struct xt_connsecmark_target_info {
+       u_int8_t mode;
+};
+
+#endif /*_XT_CONNSECMARK_H_target */
diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h
new file mode 100644 (file)
index 0000000..c53fbff
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _XT_SECMARK_H_target
+#define _XT_SECMARK_H_target
+
+/*
+ * This is intended for use by various security subsystems (but not
+ * at the same time).
+ *
+ * 'mode' refers to the specific security subsystem which the
+ * packets are being marked for.
+ */
+#define SECMARK_MODE_SEL       0x01            /* SELinux */
+#define SECMARK_SELCTX_MAX     256
+
+struct xt_secmark_target_selinux_info {
+       u_int32_t selsid;
+       char selctx[SECMARK_SELCTX_MAX];
+};
+
+struct xt_secmark_target_info {
+       u_int8_t mode;
+       union {
+               struct xt_secmark_target_selinux_info sel;
+       } u;
+};
+
+#endif /*_XT_SECMARK_H_target */
diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h
new file mode 100644 (file)
index 0000000..acd7fd7
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _XT_QUOTA_H
+#define _XT_QUOTA_H
+
+enum xt_quota_flags {
+       XT_QUOTA_INVERT         = 0x1,
+};
+#define XT_QUOTA_MASK          0x1
+
+struct xt_quota_info {
+       u_int32_t               flags;
+       u_int32_t               pad;
+       aligned_u64             quota;
+       struct xt_quota_info    *master;
+};
+
+#endif /* _XT_QUOTA_H */
diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h
new file mode 100644 (file)
index 0000000..c344e99
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _XT_STATISTIC_H
+#define _XT_STATISTIC_H
+
+enum xt_statistic_mode {
+       XT_STATISTIC_MODE_RANDOM,
+       XT_STATISTIC_MODE_NTH,
+       __XT_STATISTIC_MODE_MAX
+};
+#define XT_STATISTIC_MODE_MAX (__XT_STATISTIC_MODE_MAX - 1)
+
+enum xt_statistic_flags {
+       XT_STATISTIC_INVERT             = 0x1,
+};
+#define XT_STATISTIC_MASK              0x1
+
+struct xt_statistic_info {
+       u_int16_t                       mode;
+       u_int16_t                       flags;
+       union {
+               struct {
+                       u_int32_t       probability;
+               } random;
+               struct {
+                       u_int32_t       every;
+                       u_int32_t       packet;
+                       u_int32_t       count;
+               } nth;
+       } u;
+       struct xt_statistic_info        *master __attribute__((aligned(8)));
+};
+
+#endif /* _XT_STATISTIC_H */
diff --git a/include/linux/netfilter_arp/Kbuild b/include/linux/netfilter_arp/Kbuild
new file mode 100644 (file)
index 0000000..4f13dfc
--- /dev/null
@@ -0,0 +1,3 @@
+header-y += arpt_mangle.h
+
+unifdef-y += arp_tables.h
diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild
new file mode 100644 (file)
index 0000000..76ff4c4
--- /dev/null
@@ -0,0 +1,17 @@
+header-y += ebt_among.h
+header-y += ebt_arp.h
+header-y += ebt_arpreply.h
+header-y += ebt_ip.h
+header-y += ebt_limit.h
+header-y += ebt_log.h
+header-y += ebt_mark_m.h
+header-y += ebt_mark_t.h
+header-y += ebt_nat.h
+header-y += ebt_pkttype.h
+header-y += ebt_redirect.h
+header-y += ebt_stp.h
+header-y += ebt_ulog.h
+header-y += ebt_vlan.h
+
+unifdef-y += ebtables.h
+unifdef-y += ebt_802_3.h
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
new file mode 100644 (file)
index 0000000..591c1a8
--- /dev/null
@@ -0,0 +1,63 @@
+header-y += ip_conntrack_helper.h
+header-y += ip_conntrack_helper_h323_asn1.h
+header-y += ip_conntrack_helper_h323_types.h
+header-y += ip_conntrack_protocol.h
+header-y += ip_conntrack_sctp.h
+header-y += ip_conntrack_tcp.h
+header-y += ip_conntrack_tftp.h
+header-y += ip_nat_pptp.h
+header-y += ipt_addrtype.h
+header-y += ipt_ah.h
+header-y += ipt_CLASSIFY.h
+header-y += ipt_CLUSTERIP.h
+header-y += ipt_comment.h
+header-y += ipt_connbytes.h
+header-y += ipt_connmark.h
+header-y += ipt_CONNMARK.h
+header-y += ipt_conntrack.h
+header-y += ipt_dccp.h
+header-y += ipt_dscp.h
+header-y += ipt_DSCP.h
+header-y += ipt_ecn.h
+header-y += ipt_ECN.h
+header-y += ipt_esp.h
+header-y += ipt_hashlimit.h
+header-y += ipt_helper.h
+header-y += ipt_iprange.h
+header-y += ipt_length.h
+header-y += ipt_limit.h
+header-y += ipt_LOG.h
+header-y += ipt_mac.h
+header-y += ipt_mark.h
+header-y += ipt_MARK.h
+header-y += ipt_multiport.h
+header-y += ipt_NFQUEUE.h
+header-y += ipt_owner.h
+header-y += ipt_physdev.h
+header-y += ipt_pkttype.h
+header-y += ipt_policy.h
+header-y += ipt_realm.h
+header-y += ipt_recent.h
+header-y += ipt_REJECT.h
+header-y += ipt_SAME.h
+header-y += ipt_sctp.h
+header-y += ipt_state.h
+header-y += ipt_string.h
+header-y += ipt_tcpmss.h
+header-y += ipt_TCPMSS.h
+header-y += ipt_tos.h
+header-y += ipt_TOS.h
+header-y += ipt_ttl.h
+header-y += ipt_TTL.h
+header-y += ipt_ULOG.h
+
+unifdef-y += ip_conntrack.h
+unifdef-y += ip_conntrack_h323.h
+unifdef-y += ip_conntrack_irc.h
+unifdef-y += ip_conntrack_pptp.h
+unifdef-y += ip_conntrack_proto_gre.h
+unifdef-y += ip_conntrack_tuple.h
+unifdef-y += ip_nat.h
+unifdef-y += ip_nat_rule.h
+unifdef-y += ip_queue.h
+unifdef-y += ip_tables.h
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
new file mode 100644 (file)
index 0000000..913dad6
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __IP_CONNTRACK_SIP_H__
+#define __IP_CONNTRACK_SIP_H__
+#ifdef __KERNEL__
+
+#define SIP_PORT       5060
+#define SIP_TIMEOUT    3600
+
+#define POS_VIA                0
+#define POS_CONTACT    1
+#define POS_CONTENT    2
+#define POS_MEDIA      3
+#define POS_OWNER      4
+#define POS_CONNECTION 5
+#define POS_REQ_HEADER 6
+#define POS_SDP_HEADER 7
+
+struct sip_header_nfo {
+       const char      *lname;
+       const char      *sname;
+       const char      *ln_str;
+       size_t          lnlen;
+       size_t          snlen;
+       size_t          ln_strlen;
+       int             (*match_len)(const char *, const char *, int *);
+};
+
+extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+                                      enum ip_conntrack_info ctinfo,
+                                      struct ip_conntrack *ct,
+                                      const char **dptr);
+extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
+                                      enum ip_conntrack_info ctinfo,
+                                      struct ip_conntrack_expect *exp,
+                                      const char *dptr);
+
+extern int ct_sip_get_info(const char *dptr, size_t dlen,
+                          unsigned int *matchoff,
+                          unsigned int *matchlen,
+                          struct sip_header_nfo *hnfo);
+extern int ct_sip_lnlen(const char *line, const char *limit);
+extern const char *ct_sip_search(const char *needle, const char *haystack,
+                                 size_t needle_len, size_t haystack_len);
+#endif /* __KERNEL__ */
+#endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild
new file mode 100644 (file)
index 0000000..9dd978d
--- /dev/null
@@ -0,0 +1,21 @@
+header-y += ip6t_HL.h
+header-y += ip6t_LOG.h
+header-y += ip6t_MARK.h
+header-y += ip6t_REJECT.h
+header-y += ip6t_ah.h
+header-y += ip6t_esp.h
+header-y += ip6t_frag.h
+header-y += ip6t_hl.h
+header-y += ip6t_ipv6header.h
+header-y += ip6t_length.h
+header-y += ip6t_limit.h
+header-y += ip6t_mac.h
+header-y += ip6t_mark.h
+header-y += ip6t_multiport.h
+header-y += ip6t_opts.h
+header-y += ip6t_owner.h
+header-y += ip6t_policy.h
+header-y += ip6t_physdev.h
+header-y += ip6t_rt.h
+
+unifdef-y += ip6_tables.h
diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
new file mode 100644 (file)
index 0000000..d9c5455
--- /dev/null
@@ -0,0 +1,7 @@
+unifdef-y += const.h
+unifdef-y += export.h
+unifdef-y += stats.h
+unifdef-y += syscall.h
+unifdef-y += nfsfh.h
+unifdef-y += debug.h
+unifdef-y += auth.h
diff --git a/include/linux/nsc_gpio.h b/include/linux/nsc_gpio.h
new file mode 100644 (file)
index 0000000..7da0cf3
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+   nsc_gpio.c
+
+   National Semiconductor GPIO common access methods.
+
+   struct nsc_gpio_ops abstracts the low-level access
+   operations for the GPIO units on 2 NSC chip families; the GEODE
+   integrated CPU, and the PC-8736[03456] integrated PC-peripheral
+   chips.
+
+   The GPIO units on these chips have the same pin architecture, but
+   the access methods differ.  Thus, scx200_gpio and pc8736x_gpio
+   implement their own versions of these routines; and use the common
+   file-operations routines implemented in nsc_gpio module.
+
+   Copyright (c) 2005 Jim Cromie <jim.cromie@gmail.com>
+
+   NB: this work was tested on the Geode SC-1100 and PC-87366 chips.
+   NSC sold the GEODE line to AMD, and the PC-8736x line to Winbond.
+*/
+
+struct nsc_gpio_ops {
+       struct module*  owner;
+       u32     (*gpio_config)  (unsigned iminor, u32 mask, u32 bits);
+       void    (*gpio_dump)    (struct nsc_gpio_ops *amp, unsigned iminor);
+       int     (*gpio_get)     (unsigned iminor);
+       void    (*gpio_set)     (unsigned iminor, int state);
+       void    (*gpio_change)  (unsigned iminor);
+       int     (*gpio_current) (unsigned iminor);
+       struct device*  dev;    /* for dev_dbg() support, set in init  */
+};
+
+extern ssize_t nsc_gpio_write(struct file *file, const char __user *data,
+                             size_t len, loff_t *ppos);
+
+extern ssize_t nsc_gpio_read(struct file *file, char __user *buf,
+                            size_t len, loff_t *ppos);
+
+extern void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index);
+
diff --git a/include/linux/plist.h b/include/linux/plist.h
new file mode 100644 (file)
index 0000000..b95818a
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Descending-priority-sorted double-linked list
+ *
+ * (C) 2002-2003 Intel Corp
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
+ *
+ * 2001-2005 (c) MontaVista Software, Inc.
+ * Daniel Walker <dwalker@mvista.com>
+ *
+ * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Simplifications of the original code by
+ * Oleg Nesterov <oleg@tv-sign.ru>
+ *
+ * Licensed under the FSF's GNU Public License v2 or later.
+ *
+ * Based on simple lists (include/linux/list.h).
+ *
+ * This is a priority-sorted list of nodes; each node has a
+ * priority from INT_MIN (highest) to INT_MAX (lowest).
+ *
+ * Addition is O(K), removal is O(1), change of priority of a node is
+ * O(K) and K is the number of RT priority levels used in the system.
+ * (1 <= K <= 99)
+ *
+ * This list is really a list of lists:
+ *
+ *  - The tier 1 list is the prio_list, different priority nodes.
+ *
+ *  - The tier 2 list is the node_list, serialized nodes.
+ *
+ * Simple ASCII art explanation:
+ *
+ * |HEAD          |
+ * |              |
+ * |prio_list.prev|<------------------------------------|
+ * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-|
+ * |10            |   |10|   |21|   |21|   |21|   |40|   (prio)
+ * |              |   |  |   |  |   |  |   |  |   |  |
+ * |              |   |  |   |  |   |  |   |  |   |  |
+ * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|
+ * |node_list.prev|<------------------------------------|
+ *
+ * The nodes on the prio_list list are sorted by priority to simplify
+ * the insertion of new nodes. There are no nodes with duplicate
+ * priorites on the list.
+ *
+ * The nodes on the node_list is ordered by priority and can contain
+ * entries which have the same priority. Those entries are ordered
+ * FIFO
+ *
+ * Addition means: look for the prio_list node in the prio_list
+ * for the priority of the node and insert it before the node_list
+ * entry of the next prio_list node. If it is the first node of
+ * that priority, add it to the prio_list in the right position and
+ * insert it into the serialized node_list list
+ *
+ * Removal means remove it from the node_list and remove it from
+ * the prio_list if the node_list list_head is non empty. In case
+ * of removal from the prio_list it must be checked whether other
+ * entries of the same priority are on the list or not. If there
+ * is another entry of the same priority then this entry has to
+ * replace the removed entry on the prio_list. If the entry which
+ * is removed is the only entry of this priority then a simple
+ * remove from both list is sufficient.
+ *
+ * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX
+ * is lowest priority.
+ *
+ * No locking is done, up to the caller.
+ *
+ */
+#ifndef _LINUX_PLIST_H_
+#define _LINUX_PLIST_H_
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock_types.h>
+
+struct plist_head {
+       struct list_head prio_list;
+       struct list_head node_list;
+#ifdef CONFIG_DEBUG_PI_LIST
+       spinlock_t *lock;
+#endif
+};
+
+struct plist_node {
+       int                     prio;
+       struct plist_head       plist;
+};
+
+#ifdef CONFIG_DEBUG_PI_LIST
+# define PLIST_HEAD_LOCK_INIT(_lock)   .lock = _lock
+#else
+# define PLIST_HEAD_LOCK_INIT(_lock)
+#endif
+
+/**
+ * #PLIST_HEAD_INIT - static struct plist_head initializer
+ *
+ * @head:      struct plist_head variable name
+ */
+#define PLIST_HEAD_INIT(head, _lock)                   \
+{                                                      \
+       .prio_list = LIST_HEAD_INIT((head).prio_list),  \
+       .node_list = LIST_HEAD_INIT((head).node_list),  \
+       PLIST_HEAD_LOCK_INIT(&(_lock))                  \
+}
+
+/**
+ * #PLIST_NODE_INIT - static struct plist_node initializer
+ *
+ * @node:      struct plist_node variable name
+ * @__prio:    initial node priority
+ */
+#define PLIST_NODE_INIT(node, __prio)                  \
+{                                                      \
+       .prio  = (__prio),                              \
+       .plist = PLIST_HEAD_INIT((node).plist, NULL),   \
+}
+
+/**
+ * plist_head_init - dynamic struct plist_head initializer
+ *
+ * @head:      &struct plist_head pointer
+ */
+static inline void
+plist_head_init(struct plist_head *head, spinlock_t *lock)
+{
+       INIT_LIST_HEAD(&head->prio_list);
+       INIT_LIST_HEAD(&head->node_list);
+#ifdef CONFIG_DEBUG_PI_LIST
+       head->lock = lock;
+#endif
+}
+
+/**
+ * plist_node_init - Dynamic struct plist_node initializer
+ *
+ * @node:      &struct plist_node pointer
+ * @prio:      initial node priority
+ */
+static inline void plist_node_init(struct plist_node *node, int prio)
+{
+       node->prio = prio;
+       plist_head_init(&node->plist, NULL);
+}
+
+extern void plist_add(struct plist_node *node, struct plist_head *head);
+extern void plist_del(struct plist_node *node, struct plist_head *head);
+
+/**
+ * plist_for_each - iterate over the plist
+ *
+ * @pos1:      the type * to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define plist_for_each(pos, head)      \
+        list_for_each_entry(pos, &(head)->node_list, plist.node_list)
+
+/**
+ * plist_for_each_entry_safe - iterate over a plist of given type safe
+ * against removal of list entry
+ *
+ * @pos1:      the type * to use as a loop counter.
+ * @n1:        another type * to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define plist_for_each_safe(pos, n, head)      \
+        list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list)
+
+/**
+ * plist_for_each_entry        - iterate over list of given type
+ *
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define plist_for_each_entry(pos, head, mem)   \
+        list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list)
+
+/**
+ * plist_for_each_entry_safe - iterate over list of given type safe against
+ * removal of list entry
+ *
+ * @pos:       the type * to use as a loop counter.
+ * @n:         another type * to use as temporary storage
+ * @head:      the head for your list.
+ * @m:         the name of the list_struct within the struct.
+ */
+#define plist_for_each_entry_safe(pos, n, head, m)     \
+       list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list)
+
+/**
+ * plist_head_empty - return !0 if a plist_head is empty
+ *
+ * @head:      &struct plist_head pointer
+ */
+static inline int plist_head_empty(const struct plist_head *head)
+{
+       return list_empty(&head->node_list);
+}
+
+/**
+ * plist_node_empty - return !0 if plist_node is not on a list
+ *
+ * @node:      &struct plist_node pointer
+ */
+static inline int plist_node_empty(const struct plist_node *node)
+{
+       return plist_head_empty(&node->plist);
+}
+
+/* All functions below assume the plist_head is not empty. */
+
+/**
+ * plist_first_entry - get the struct for the first entry
+ *
+ * @ptr:       the &struct plist_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#ifdef CONFIG_DEBUG_PI_LIST
+# define plist_first_entry(head, type, member) \
+({ \
+       WARN_ON(plist_head_empty(head)); \
+       container_of(plist_first(head), type, member); \
+})
+#else
+# define plist_first_entry(head, type, member) \
+       container_of(plist_first(head), type, member)
+#endif
+
+/**
+ * plist_first - return the first node (and thus, highest priority)
+ *
+ * @head:      the &struct plist_head pointer
+ *
+ * Assumes the plist is _not_ empty.
+ */
+static inline struct plist_node* plist_first(const struct plist_head *head)
+{
+       return list_entry(head->node_list.next,
+                         struct plist_node, plist.node_list);
+}
+
+#endif
diff --git a/include/linux/poison.h b/include/linux/poison.h
new file mode 100644 (file)
index 0000000..3e628f9
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef _LINUX_POISON_H
+#define _LINUX_POISON_H
+
+/********** include/linux/list.h **********/
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1  ((void *) 0x00100100)
+#define LIST_POISON2  ((void *) 0x00200200)
+
+/********** mm/slab.c **********/
+/*
+ * Magic nums for obj red zoning.
+ * Placed in the first word before and the first word after an obj.
+ */
+#define        RED_INACTIVE    0x5A2CF071UL    /* when obj is inactive */
+#define        RED_ACTIVE      0x170FC2A5UL    /* when obj is active */
+
+/* ...and for poisoning */
+#define        POISON_INUSE    0x5a    /* for use-uninitialised poisoning */
+#define POISON_FREE    0x6b    /* for use-after-free poisoning */
+#define        POISON_END      0xa5    /* end-byte of poisoning */
+
+/********** arch/$ARCH/mm/init.c **********/
+#define POISON_FREE_INITMEM    0xcc
+
+/********** arch/x86_64/mm/init.c **********/
+#define        POISON_FREE_INITDATA    0xba
+
+/********** arch/ia64/hp/common/sba_iommu.c **********/
+/*
+ * arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a
+ * value of "SBAIOMMU POISON\0" for spill-over poisoning.
+ */
+
+/********** fs/jbd/journal.c **********/
+#define JBD_POISON_FREE        0x5b
+
+/********** drivers/base/dmapool.c **********/
+#define        POOL_POISON_FREED       0xa7    /* !inuse */
+#define        POOL_POISON_ALLOCATED   0xa9    /* !initted */
+
+/********** drivers/atm/ **********/
+#define ATM_POISON_FREE                0x12
+#define ATM_POISON             0xdeadbeef
+
+/********** net/ **********/
+#define NEIGHBOR_DEAD          0xdeadbeef
+#define NETFILTER_LINK_POISON  0xdead57ac
+
+/********** kernel/mutexes **********/
+#define MUTEX_DEBUG_INIT       0x11
+#define MUTEX_DEBUG_FREE       0x22
+
+/********** security/ **********/
+#define KEY_DESTROY            0xbd
+
+/********** sound/oss/ **********/
+#define OSS_POISON_FREE                0xAB
+
+#endif
diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild
new file mode 100644 (file)
index 0000000..2415a64
--- /dev/null
@@ -0,0 +1,2 @@
+header-y += md_p.h
+header-y += md_u.h
diff --git a/include/linux/resume-trace.h b/include/linux/resume-trace.h
new file mode 100644 (file)
index 0000000..a376bd4
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef RESUME_TRACE_H
+#define RESUME_TRACE_H
+
+#ifdef CONFIG_PM_TRACE
+
+struct device;
+extern void set_trace_device(struct device *);
+extern void generate_resume_trace(void *tracedata, unsigned int user);
+
+#define TRACE_DEVICE(dev) set_trace_device(dev)
+#define TRACE_RESUME(user) do {                                \
+       void *tracedata;                                \
+       asm volatile("movl $1f,%0\n"                    \
+               ".section .tracedata,\"a\"\n"           \
+               "1:\t.word %c1\n"                       \
+               "\t.long %c2\n"                         \
+               ".previous"                             \
+               :"=r" (tracedata)                       \
+               : "i" (__LINE__), "i" (__FILE__));      \
+       generate_resume_trace(tracedata, user);         \
+} while (0)
+
+#else
+
+#define TRACE_DEVICE(dev) do { } while (0)
+#define TRACE_RESUME(dev) do { } while (0)
+
+#endif
+
+#endif
diff --git a/include/linux/rtc-v3020.h b/include/linux/rtc-v3020.h
new file mode 100644 (file)
index 0000000..bf74e63
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * v3020.h - Registers definition and platform data structure for the v3020 RTC.
+ *
+ * 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) 2006, 8D Technologies inc.
+ */
+#ifndef __LINUX_V3020_H
+#define __LINUX_V3020_H
+
+/* The v3020 has only one data pin but which one
+ * is used depends on the board. */
+struct v3020_platform_data {
+       int leftshift; /* (1<<(leftshift)) & readl() */
+};
+
+#define V3020_STATUS_0 0x00
+#define V3020_STATUS_1 0x01
+#define V3020_SECONDS  0x02
+#define V3020_MINUTES  0x03
+#define V3020_HOURS            0x04
+#define V3020_MONTH_DAY        0x05
+#define V3020_MONTH            0x06
+#define V3020_YEAR             0x07
+#define V3020_WEEK_DAY 0x08
+#define V3020_WEEK             0x09
+
+#define V3020_IS_COMMAND(val) ((val)>=0x0E)
+
+#define V3020_CMD_RAM2CLOCK    0x0E
+#define V3020_CMD_CLOCK2RAM    0x0F
+
+#endif /* __LINUX_V3020_H */
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
new file mode 100644 (file)
index 0000000..5d41dee
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * RT Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains the public data structure and API definitions.
+ */
+
+#ifndef __LINUX_RT_MUTEX_H
+#define __LINUX_RT_MUTEX_H
+
+#include <linux/linkage.h>
+#include <linux/plist.h>
+#include <linux/spinlock_types.h>
+
+/*
+ * The rt_mutex structure
+ *
+ * @wait_lock: spinlock to protect the structure
+ * @wait_list: pilist head to enqueue waiters in priority order
+ * @owner:     the mutex owner
+ */
+struct rt_mutex {
+       spinlock_t              wait_lock;
+       struct plist_head       wait_list;
+       struct task_struct      *owner;
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+       int                     save_state;
+       const char              *name, *file;
+       int                     line;
+       void                    *magic;
+#endif
+};
+
+struct rt_mutex_waiter;
+struct hrtimer_sleeper;
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+ extern int rt_mutex_debug_check_no_locks_freed(const void *from,
+                                               unsigned long len);
+ extern void rt_mutex_debug_check_no_locks_held(struct task_struct *task);
+#else
+ static inline int rt_mutex_debug_check_no_locks_freed(const void *from,
+                                                      unsigned long len)
+ {
+       return 0;
+ }
+# define rt_mutex_debug_check_no_locks_held(task)      do { } while (0)
+#endif
+
+#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__)
+ extern void rt_mutex_debug_task_free(struct task_struct *tsk);
+#else
+# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname)
+# define rt_mutex_init(mutex)                  __rt_mutex_init(mutex, NULL)
+# define rt_mutex_debug_task_free(t)                   do { } while (0)
+#endif
+
+#define __RT_MUTEX_INITIALIZER(mutexname) \
+       { .wait_lock = SPIN_LOCK_UNLOCKED \
+       , .wait_list = PLIST_HEAD_INIT(mutexname.wait_list, mutexname.wait_lock) \
+       , .owner = NULL \
+       __DEBUG_RT_MUTEX_INITIALIZER(mutexname)}
+
+#define DEFINE_RT_MUTEX(mutexname) \
+       struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)
+
+/***
+ * rt_mutex_is_locked - is the mutex locked
+ * @lock: the mutex to be queried
+ *
+ * Returns 1 if the mutex is locked, 0 if unlocked.
+ */
+static inline int rt_mutex_is_locked(struct rt_mutex *lock)
+{
+       return lock->owner != NULL;
+}
+
+extern void __rt_mutex_init(struct rt_mutex *lock, const char *name);
+extern void rt_mutex_destroy(struct rt_mutex *lock);
+
+extern void rt_mutex_lock(struct rt_mutex *lock);
+extern int rt_mutex_lock_interruptible(struct rt_mutex *lock,
+                                               int detect_deadlock);
+extern int rt_mutex_timed_lock(struct rt_mutex *lock,
+                                       struct hrtimer_sleeper *timeout,
+                                       int detect_deadlock);
+
+extern int rt_mutex_trylock(struct rt_mutex *lock);
+
+extern void rt_mutex_unlock(struct rt_mutex *lock);
+
+#ifdef CONFIG_RT_MUTEXES
+# define INIT_RT_MUTEXES(tsk)                                          \
+       .pi_waiters     = PLIST_HEAD_INIT(tsk.pi_waiters, tsk.pi_lock), \
+       INIT_RT_MUTEX_DEBUG(tsk)
+#else
+# define INIT_RT_MUTEXES(tsk)
+#endif
+
+#endif
diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h
new file mode 100644 (file)
index 0000000..50e2b01
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __LINUX_STACKTRACE_H
+#define __LINUX_STACKTRACE_H
+
+#ifdef CONFIG_STACKTRACE
+struct stack_trace {
+       unsigned int nr_entries, max_entries;
+       unsigned long *entries;
+       int skip;       /* input argument: How many entries to skip */
+       int all_contexts; /* input argument: if true do than one stack */
+};
+
+extern void save_stack_trace(struct stack_trace *trace,
+                            struct task_struct *task);
+
+extern void print_stack_trace(struct stack_trace *trace, int spaces);
+#else
+# define save_stack_trace(trace, task)                 do { } while (0)
+# define print_stack_trace(trace)                      do { } while (0)
+#endif
+
+#endif
diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild
new file mode 100644 (file)
index 0000000..fb438f1
--- /dev/null
@@ -0,0 +1 @@
+unifdef-y += debug.h
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
new file mode 100644 (file)
index 0000000..f1cb6cd
--- /dev/null
@@ -0,0 +1,137 @@
+/* taskstats.h - exporting per-task statistics
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2006
+ *           (C) Balbir Singh,   IBM Corp. 2006
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _LINUX_TASKSTATS_H
+#define _LINUX_TASKSTATS_H
+
+/* Format for per-task data returned to userland when
+ *     - a task exits
+ *     - listener requests stats for a task
+ *
+ * The struct is versioned. Newer versions should only add fields to
+ * the bottom of the struct to maintain backward compatibility.
+ *
+ *
+ * To add new fields
+ *     a) bump up TASKSTATS_VERSION
+ *     b) add comment indicating new version number at end of struct
+ *     c) add new fields after version comment; maintain 64-bit alignment
+ */
+
+#define TASKSTATS_VERSION      1
+
+struct taskstats {
+
+       /* Version 1 */
+       __u16   version;
+       __u16   padding[3];     /* Userspace should not interpret the padding
+                                * field which can be replaced by useful
+                                * fields if struct taskstats is extended.
+                                */
+
+       /* Delay accounting fields start
+        *
+        * All values, until comment "Delay accounting fields end" are
+        * available only if delay accounting is enabled, even though the last
+        * few fields are not delays
+        *
+        * xxx_count is the number of delay values recorded
+        * xxx_delay_total is the corresponding cumulative delay in nanoseconds
+        *
+        * xxx_delay_total wraps around to zero on overflow
+        * xxx_count incremented regardless of overflow
+        */
+
+       /* Delay waiting for cpu, while runnable
+        * count, delay_total NOT updated atomically
+        */
+       __u64   cpu_count;
+       __u64   cpu_delay_total;
+
+       /* Following four fields atomically updated using task->delays->lock */
+
+       /* Delay waiting for synchronous block I/O to complete
+        * does not account for delays in I/O submission
+        */
+       __u64   blkio_count;
+       __u64   blkio_delay_total;
+
+       /* Delay waiting for page fault I/O (swap in only) */
+       __u64   swapin_count;
+       __u64   swapin_delay_total;
+
+       /* cpu "wall-clock" running time
+        * On some architectures, value will adjust for cpu time stolen
+        * from the kernel in involuntary waits due to virtualization.
+        * Value is cumulative, in nanoseconds, without a corresponding count
+        * and wraps around to zero silently on overflow
+        */
+       __u64   cpu_run_real_total;
+
+       /* cpu "virtual" running time
+        * Uses time intervals seen by the kernel i.e. no adjustment
+        * for kernel's involuntary waits due to virtualization.
+        * Value is cumulative, in nanoseconds, without a corresponding count
+        * and wraps around to zero silently on overflow
+        */
+       __u64   cpu_run_virtual_total;
+       /* Delay accounting fields end */
+       /* version 1 ends here */
+};
+
+
+/*
+ * Commands sent from userspace
+ * Not versioned. New commands should only be inserted at the enum's end
+ * prior to __TASKSTATS_CMD_MAX
+ */
+
+enum {
+       TASKSTATS_CMD_UNSPEC = 0,       /* Reserved */
+       TASKSTATS_CMD_GET,              /* user->kernel request/get-response */
+       TASKSTATS_CMD_NEW,              /* kernel->user event */
+       __TASKSTATS_CMD_MAX,
+};
+
+#define TASKSTATS_CMD_MAX (__TASKSTATS_CMD_MAX - 1)
+
+enum {
+       TASKSTATS_TYPE_UNSPEC = 0,      /* Reserved */
+       TASKSTATS_TYPE_PID,             /* Process id */
+       TASKSTATS_TYPE_TGID,            /* Thread group id */
+       TASKSTATS_TYPE_STATS,           /* taskstats structure */
+       TASKSTATS_TYPE_AGGR_PID,        /* contains pid + stats */
+       TASKSTATS_TYPE_AGGR_TGID,       /* contains tgid + stats */
+       __TASKSTATS_TYPE_MAX,
+};
+
+#define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1)
+
+enum {
+       TASKSTATS_CMD_ATTR_UNSPEC = 0,
+       TASKSTATS_CMD_ATTR_PID,
+       TASKSTATS_CMD_ATTR_TGID,
+       TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
+       TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
+       __TASKSTATS_CMD_ATTR_MAX,
+};
+
+#define TASKSTATS_CMD_ATTR_MAX (__TASKSTATS_CMD_ATTR_MAX - 1)
+
+/* NETLINK_GENERIC related info */
+
+#define TASKSTATS_GENL_NAME    "TASKSTATS"
+#define TASKSTATS_GENL_VERSION 0x1
+
+#endif /* _LINUX_TASKSTATS_H */
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h
new file mode 100644 (file)
index 0000000..16894b7
--- /dev/null
@@ -0,0 +1,89 @@
+/* taskstats_kern.h - kernel header for per-task statistics interface
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2006
+ *           (C) Balbir Singh,   IBM Corp. 2006
+ */
+
+#ifndef _LINUX_TASKSTATS_KERN_H
+#define _LINUX_TASKSTATS_KERN_H
+
+#include <linux/taskstats.h>
+#include <linux/sched.h>
+#include <net/genetlink.h>
+
+#ifdef CONFIG_TASKSTATS
+extern kmem_cache_t *taskstats_cache;
+extern struct mutex taskstats_exit_mutex;
+
+static inline void taskstats_exit_free(struct taskstats *tidstats)
+{
+       if (tidstats)
+               kmem_cache_free(taskstats_cache, tidstats);
+}
+
+static inline void taskstats_tgid_init(struct signal_struct *sig)
+{
+       spin_lock_init(&sig->stats_lock);
+       sig->stats = NULL;
+}
+
+static inline void taskstats_tgid_alloc(struct signal_struct *sig)
+{
+       struct taskstats *stats;
+       unsigned long flags;
+
+       stats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL);
+       if (!stats)
+               return;
+
+       spin_lock_irqsave(&sig->stats_lock, flags);
+       if (!sig->stats) {
+               sig->stats = stats;
+               stats = NULL;
+       }
+       spin_unlock_irqrestore(&sig->stats_lock, flags);
+
+       if (stats)
+               kmem_cache_free(taskstats_cache, stats);
+}
+
+static inline void taskstats_tgid_free(struct signal_struct *sig)
+{
+       struct taskstats *stats = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sig->stats_lock, flags);
+       if (sig->stats) {
+               stats = sig->stats;
+               sig->stats = NULL;
+       }
+       spin_unlock_irqrestore(&sig->stats_lock, flags);
+       if (stats)
+               kmem_cache_free(taskstats_cache, stats);
+}
+
+extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
+extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int);
+extern void taskstats_init_early(void);
+extern void taskstats_tgid_alloc(struct signal_struct *);
+#else
+static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
+{}
+static inline void taskstats_exit_free(struct taskstats *ptidstats)
+{}
+static inline void taskstats_exit_send(struct task_struct *tsk,
+                                      struct taskstats *tidstats,
+                                      int group_dead, unsigned int cpu)
+{}
+static inline void taskstats_tgid_init(struct signal_struct *sig)
+{}
+static inline void taskstats_tgid_alloc(struct signal_struct *sig)
+{}
+static inline void taskstats_tgid_free(struct signal_struct *sig)
+{}
+static inline void taskstats_init_early(void)
+{}
+#endif /* CONFIG_TASKSTATS */
+
+#endif
+
diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
new file mode 100644 (file)
index 0000000..78dfbac
--- /dev/null
@@ -0,0 +1,4 @@
+header-y += tc_gact.h
+header-y += tc_ipt.h
+header-y += tc_mirred.h
+header-y += tc_pedit.h
diff --git a/include/linux/tc_ematch/Kbuild b/include/linux/tc_ematch/Kbuild
new file mode 100644 (file)
index 0000000..4a58a1c
--- /dev/null
@@ -0,0 +1,4 @@
+header-y += tc_em_cmp.h
+header-y += tc_em_meta.h
+header-y += tc_em_nbyte.h
+header-y += tc_em_text.h
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
new file mode 100644 (file)
index 0000000..3cadfa5
--- /dev/null
@@ -0,0 +1,707 @@
+/*
+ * Tracing hooks
+ *
+ * This file defines hook entry points called by core code where
+ * user tracing/debugging support might need to do something.
+ * These entry points are called tracehook_*.  Each hook declared below
+ * has a detailed comment giving the context (locking et al) from
+ * which it is called, and the meaning of its return value (if any).
+ *
+ * We also declare here tracehook_* functions providing access to low-level
+ * interrogation and control of threads.  These functions must be called
+ * on either the current thread or on a quiescent thread.  We say a
+ * thread is "quiescent" if it is in TASK_STOPPED or TASK_TRACED state,
+ * we are guaranteed it will not be woken up and return to user mode, and
+ * we have called wait_task_inactive on it.
+ */
+
+#ifndef _LINUX_TRACEHOOK_H
+#define _LINUX_TRACEHOOK_H     1
+
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+struct linux_binprm;
+struct pt_regs;
+
+
+/*
+ * The machine-specific asm/tracehook.h file is responsible for declaring
+ * the following entry points.  These can be called only on a quiescent thread,
+ * or the current thread when it is about to return to user mode.
+ *
+ * Single-step control.  When enabled, the next instruction or syscall exit
+ * produces a SIGTRAP.  Enabling or disabling redundantly is harmless.
+ *
+ *     void tracehook_enable_single_step(struct task_struct *tsk);
+ *     void tracehook_disable_single_step(struct task_struct *tsk);
+ *     int tracehook_single_step_enabled(struct task_struct *tsk);
+ *
+ * If those calls are defined, #define ARCH_HAS_SINGLE_STEP to nonzero.
+ * Do not #define it if these calls are never available in this kernel config.
+ * If defined, the value of ARCH_HAS_SINGLE_STEP can be constant or variable.
+ * It should evaluate to nonzero if the hardware is able to support
+ * tracehook_enable_single_step.  If it's a variable expression, it
+ * should be one that can be evaluated in modules, i.e. uses exported symbols.
+ *
+ * Block-step control (trap on control transfer), when available.
+ * tracehook_disable_block_step will be called after tracehook_enable_single_step.
+ * When enabled, the next jump, or other control transfer or syscall exit,
+ * produces a SIGTRAP.  Enabling or disabling redundantly is harmless.
+ *
+ *     void tracehook_enable_block_step(struct task_struct *tsk);
+ *     void tracehook_disable_block_step(struct task_struct *tsk);
+ *     int tracehook_block_step_enabled(struct task_struct *tsk);
+ *
+ * If those calls are defined, #define ARCH_HAS_BLOCK_STEP to nonzero.
+ * Do not #define it if these calls are never available in this kernel config.
+ * If defined, the value of ARCH_HAS_BLOCK_STEP can be constant or variable.
+ * It should evaluate to nonzero if the hardware is able to support
+ * tracehook_enable_block_step.  If it's a variable expression, it
+ * should be one that can be evaluated in modules, i.e. uses exported symbols.
+ *
+ * Control system call tracing.  When enabled a syscall entry or exit
+ * produces a call to tracehook_report_syscall, below.
+ *
+ *     void tracehook_enable_syscall_trace(struct task_struct *tsk);
+ *     void tracehook_disable_syscall_trace(struct task_struct *tsk);
+ *
+ * When stopped in tracehook_report_syscall for syscall entry,
+ * abort the syscall so no kernel function is called.
+ * If the register state was not otherwise updated before,
+ * this produces an -ENOSYS error return as for an invalid syscall number.
+ *
+ *     void tracehook_abort_syscall(struct pt_regs *regs);
+ *
+ * Return the regset view (see below) that is native for the given process.
+ * For example, what it would access when it called ptrace.
+ * Throughout the life of the process, this only changes at exec.
+ *
+ *     const struct utrace_regset_view *utrace_native_view(struct task_struct *);
+ *
+ ***/
+
+
+/*
+ * This data structure describes a machine resource we call a register set.
+ * This is part of the state of an individual thread, not necessarily
+ * actual CPU registers per se.  A register set consists of a number of
+ * similar slots, given by ->n.  Each slot is ->size bytes, and aligned to
+ * ->align bytes (which is at least ->size).
+ *
+ * As described above, these entry points can be called on the current
+ * thread or on a quiescent thread.  The pos argument must be aligned
+ * according to ->align; the count argument must be a multiple of ->size.
+ * These functions are not responsible for checking for invalid arguments.
+ *
+ * When there is a natural value to use as an index, ->bias gives the
+ * difference between the natural index and the slot index for the
+ * register set.  For example, x86 GDT segment descriptors form a regset;
+ * the segment selector produces a natural index, but only a subset of
+ * that index space is available as a regset (the TLS slots); subtracting
+ * ->bias from a segment selector index value computes the regset slot.
+ */
+struct utrace_regset {
+       unsigned int n;         /* Number of slots (registers).  */
+       unsigned int size;      /* Size in bytes of a slot (register).  */
+       unsigned int align;     /* Required alignment, in bytes.  */
+       unsigned int bias;      /* Bias from natural indexing.  */
+
+       /*
+        * Return -ENODEV if not available on the hardware found.
+        * Return 0 if no interesting state in this thread.
+        * Return >0 number of ->size units of interesting state.
+        * Any get call fetching state beyond that number will
+        * see the default initialization state for this data,
+        * so a caller that knows that the default state is need
+        * not copy it all out.
+        * This call is optional; the pointer is NULL if there
+        * so no inexpensive check to yield a value < .n.
+        */
+       int (*active)(struct task_struct *, const struct utrace_regset *);
+
+       /*
+        * Fetch and store register values.  Return 0 on success; -EIO or
+        * -ENODEV are usual failure returns.  The pos and count values are
+        * in bytes, but must be properly aligned.  If kbuf is non-null,
+        * that buffer is used and ubuf is ignored.  If kbuf is NULL, then
+        * ubuf gives a userland pointer to access directly, and an -EFAULT
+        * return value is possible.
+        */
+       int (*get)(struct task_struct *, const struct utrace_regset *,
+                  unsigned int pos, unsigned int count,
+                  void *kbuf, void __user *ubuf);
+       int (*set)(struct task_struct *, const struct utrace_regset *,
+                  unsigned int pos, unsigned int count,
+                  const void *kbuf, const void __user *ubuf);
+
+       /*
+        * This call is optional; usually the pointer is NULL.
+        * When provided, there is some user memory associated
+        * with this regset's hardware, such as memory backing
+        * cached register data on register window machines; the
+        * regset's data controls what user memory is used
+        * (e.g. via the stack pointer value).
+        *
+        * Write register data back to user memory.  If the
+        * immediate flag is nonzero, it must be written to the
+        * user memory so uaccess/access_process_vm can see it
+        * when this call returns; if zero, then it must be
+        * written back by the time the task completes a context
+        * switch (as synchronized with wait_task_inactive).
+        * Return 0 on success or if there was nothing to do,
+        * -EFAULT for a memory problem (bad stack pointer or
+        * whatever), or -EIO for a hardware problem.
+        */
+       int (*writeback)(struct task_struct *, const struct utrace_regset *,
+                        int immediate);
+};
+
+/*
+ * A regset view is a collection of regsets (struct utrace_regset, above).
+ * This describes all the state of a thread that can be seen from a given
+ * architecture/ABI environment.  More than one view might refer to the
+ * same utrace_regset, or more than one regset might refer to the same
+ * machine-specific state in the thread.  For example, a 32-bit thread's
+ * state could be examined from the 32-bit view or from the 64-bit view.
+ * Either method reaches the same thread register state, doing appropriate
+ * widening or truncation.
+ */
+struct utrace_regset_view {
+       const char *name;       /* Identifier, e.g. ELF_PLATFORM string.  */
+
+       const struct utrace_regset *regsets;
+       unsigned int n;
+
+       /*
+        * EM_* value for which this is the native view, if any.
+        */
+       u16 e_machine;
+};
+
+
+/*
+ * These two are helpers for writing regset get/set functions in arch code.
+ * Use one or more calls sequentially for each chunk of regset data stored
+ * contiguously in memory.  Call with constants for start_pos and end_pos,
+ * giving the range of byte positions in the regset that data corresponds
+ * to; end_pos can be -1 if this chunk is at the end of the regset layout.
+ * Each call updates the arguments to point past its chunk.
+ */
+
+static inline int
+utrace_regset_copyout(unsigned int *pos, unsigned int *count,
+                     void **kbuf, void __user **ubuf,
+                     const void *data, int start_pos, int end_pos)
+{
+       if (*count == 0)
+               return 0;
+       BUG_ON(*pos < start_pos);
+       if (end_pos < 0 || *pos < end_pos) {
+               unsigned int copy = (end_pos < 0 ? *count
+                                    : min(*count, end_pos - *pos));
+               data += *pos - start_pos;
+               if (*kbuf) {
+                       memcpy(*kbuf, data, copy);
+                       *kbuf += copy;
+               }
+               else if (copy_to_user(*ubuf, data, copy))
+                       return -EFAULT;
+               else
+                       *ubuf += copy;
+               *pos += copy;
+               *count -= copy;
+       }
+       return 0;
+}
+
+static inline int
+utrace_regset_copyin(unsigned int *pos, unsigned int *count,
+                    const void **kbuf, const void __user **ubuf,
+                    void *data, int start_pos, int end_pos)
+{
+       if (*count == 0)
+               return 0;
+       BUG_ON(*pos < start_pos);
+       if (end_pos < 0 || *pos < end_pos) {
+               unsigned int copy = (end_pos < 0 ? *count
+                                    : min(*count, end_pos - *pos));
+               data += *pos - start_pos;
+               if (*kbuf) {
+                       memcpy(data, *kbuf, copy);
+                       *kbuf += copy;
+               }
+               else if (copy_from_user(data, *ubuf, copy))
+                       return -EFAULT;
+               else
+                       *ubuf += copy;
+               *pos += copy;
+               *count -= copy;
+       }
+       return 0;
+}
+
+/*
+ * These two parallel the two above, but for portions of a regset layout
+ * that always read as all-zero or for which writes are ignored.
+ */
+static inline int
+utrace_regset_copyout_zero(unsigned int *pos, unsigned int *count,
+                          void **kbuf, void __user **ubuf,
+                          int start_pos, int end_pos)
+{
+       if (*count == 0)
+               return 0;
+       BUG_ON(*pos < start_pos);
+       if (end_pos < 0 || *pos < end_pos) {
+               unsigned int copy = (end_pos < 0 ? *count
+                                    : min(*count, end_pos - *pos));
+               if (*kbuf) {
+                       memset(*kbuf, 0, copy);
+                       *kbuf += copy;
+               }
+               else if (clear_user(*ubuf, copy))
+                       return -EFAULT;
+               else
+                       *ubuf += copy;
+               *pos += copy;
+               *count -= copy;
+       }
+       return 0;
+}
+
+static inline int
+utrace_regset_copyin_ignore(unsigned int *pos, unsigned int *count,
+                           const void **kbuf, const void __user **ubuf,
+                           int start_pos, int end_pos)
+{
+       if (*count == 0)
+               return 0;
+       BUG_ON(*pos < start_pos);
+       if (end_pos < 0 || *pos < end_pos) {
+               unsigned int copy = (end_pos < 0 ? *count
+                                    : min(*count, end_pos - *pos));
+               if (*kbuf)
+                       *kbuf += copy;
+               else
+                       *ubuf += copy;
+               *pos += copy;
+               *count -= copy;
+       }
+       return 0;
+}
+
+/**/
+
+
+/***
+ ***
+ *** Following are entry points from core code, where the user debugging
+ *** support can affect the normal behavior.  The locking situation is
+ *** described for each call.
+ ***
+ ***/
+
+#ifdef CONFIG_UTRACE
+#include <linux/utrace.h>
+#endif
+
+
+/*
+ * Called in copy_process when setting up the copied task_struct,
+ * with tasklist_lock held for writing.
+ */
+static inline void tracehook_init_task(struct task_struct *child)
+{
+#ifdef CONFIG_UTRACE
+       child->utrace_flags = 0;
+       child->utrace = NULL;
+#endif
+}
+
+/*
+ * Called from release_task, no locks held.
+ * After this, there should be no tracing entanglements.
+ */
+static inline void tracehook_release_task(struct task_struct *p)
+{
+#ifdef CONFIG_UTRACE
+       smp_mb();
+       if (p->utrace != NULL)
+               utrace_release_task(p);
+#endif
+}
+
+/*
+ * Return nonzero to trigger a BUG_ON crash in release_task.
+ * This should verify that there is no tracing-related state
+ * still affecting the task_struct about to be released.
+ * Called with tasklist_lock held for writing.
+ */
+static inline int tracehook_check_released(struct task_struct *p)
+{
+#ifdef CONFIG_UTRACE
+       return unlikely(p->utrace != NULL);
+#endif
+       return 0;
+}
+
+/*
+ * do_notify_parent_cldstop calls this when it's about to generate a SIGCHLD
+ * for a job control stop.  Return nonzero to prevent that signal generation.
+ * Called with tasklist_lock held for reading, sometimes with irqs disabled.
+ */
+static inline int tracehook_notify_cldstop(struct task_struct *tsk,
+                                          const siginfo_t *info)
+{
+#ifdef CONFIG_UTRACE
+       if (tsk->utrace_flags & UTRACE_ACTION_NOREAP)
+               return 1;
+#endif
+       return 0;
+}
+
+/*
+ * exit_notify calls this with tasklist_lock held for writing.
+ * Return nonzero to prevent any normal SIGCHLD generation for this
+ * thread's death (i.e. when it is not ignored and its thread group is
+ * empty).  This call must set *noreap to 0, or to 1 to force this thread
+ * to become a zombie when it would normally reap itself.
+ * The *death_cookie is passed to tracehook_report_death (below).
+ */
+static inline int tracehook_notify_death(struct task_struct *tsk,
+                                        int *noreap, void **death_cookie)
+{
+       *death_cookie = NULL;
+#ifdef CONFIG_UTRACE
+       *death_cookie = tsk->utrace;
+       if (tsk->utrace_flags & UTRACE_ACTION_NOREAP) {
+               *noreap = 1;
+               return 1;
+       }
+#endif
+       *noreap = 0;
+       return 0;
+}
+
+/*
+ * Return zero iff tracing doesn't care to examine this fatal signal,
+ * so it can short-circuit normal delivery directly to a group exit.
+ * Called with tsk->sighand->siglock held.
+ */
+static inline int tracehook_consider_fatal_signal(struct task_struct *tsk,
+                                                 int sig)
+{
+#ifdef CONFIG_UTRACE
+       return (tsk->utrace_flags & (UTRACE_EVENT(SIGNAL_TERM)
+                                    | UTRACE_EVENT(SIGNAL_CORE)));
+#endif
+       return 0;
+}
+
+/*
+ * Return zero iff tracing doesn't care to examine this ignored signal,
+ * so it can short-circuit normal delivery and never even get queued.
+ * Either the handler is SIG_DFL and sig's default is ignore, or it's SIG_IGN.
+ * Called with tsk->sighand->siglock held.
+ */
+static inline int tracehook_consider_ignored_signal(struct task_struct *tsk,
+                                                   int sig, void *handler)
+{
+#ifdef CONFIG_UTRACE
+       return (tsk->utrace_flags & UTRACE_EVENT(SIGNAL_IGN));
+#endif
+       return 0;
+}
+
+
+/*
+ * Called with the siglock held when computing tsk's signal_pending flag.
+ * Return nonzero to force the signal_pending flag on, so that
+ * tracehook_induce_signal will be called before the next return to user mode.
+ */
+static inline int tracehook_induce_sigpending(struct task_struct *tsk)
+{
+#ifdef CONFIG_UTRACE
+       return unlikely(tsk->utrace_flags & UTRACE_ACTION_QUIESCE);
+#endif
+       return 0;
+}
+
+/*
+ * Called with the siglock held before dequeuing pending signals.
+ * Return zero to check for a real pending signal normally.
+ * Return -1 after releasing the siglock to repeat the check.
+ * Return a signal number to induce an artifical signal delivery,
+ * setting *info and *return_ka to specify its details and behavior.
+ */
+static inline int tracehook_get_signal(struct task_struct *tsk,
+                                      struct pt_regs *regs,
+                                      siginfo_t *info,
+                                      struct k_sigaction *return_ka)
+{
+#ifdef CONFIG_UTRACE
+       if (unlikely(tsk->utrace_flags))
+               return utrace_get_signal(tsk, regs, info, return_ka);
+#endif
+       return 0;
+}
+
+/*
+ * Called with no locks held when about to stop for job control;
+ * we are already in TASK_STOPPED state, about to call schedule.
+ * Return zero if the normal SIGCHLD should be generated, which
+ * will happen if last_one is true meaning this is the last thread
+ * in the thread group to stop.
+ */
+static inline int tracehook_finish_stop(int last_one)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & UTRACE_EVENT(JCTL))
+               return utrace_report_jctl(CLD_STOPPED);
+#endif
+
+       return 0;
+}
+
+/*
+ * Called with tasklist_lock held for reading, for an event notification stop.
+ * We are already in TASK_TRACED.  Return zero to go back to running,
+ * or nonzero to actually stop until resumed.
+ */
+static inline int tracehook_stop_now(void)
+{
+       return 0;
+}
+
+
+/*
+ * Return nonzero if the child's parent (current) should be prevented
+ * from seeing its child in TASK_STOPPED state when it waits with WSTOPPED.
+ * Called with tasklist_lock held for reading.
+ */
+static inline int tracehook_inhibit_wait_stopped(struct task_struct *child)
+{
+#ifdef CONFIG_UTRACE
+       return (child->utrace_flags & UTRACE_ACTION_NOREAP);
+#endif
+       return 0;
+}
+
+/*
+ * Return nonzero if the child's parent (current) should be prevented
+ * from seeing its child in TASK_ZOMBIE state when it waits with WEXITED.
+ * Called with tasklist_lock held for reading.
+ */
+static inline int tracehook_inhibit_wait_zombie(struct task_struct *child)
+{
+#ifdef CONFIG_UTRACE
+       return (child->utrace_flags & UTRACE_ACTION_NOREAP);
+#endif
+       return 0;
+}
+
+/*
+ * Return nonzero if the child's parent (current) should be prevented
+ * from seeing its child resuming after job stop when it waits with WCONTINUED.
+ * Called with tasklist_lock held for reading.
+ */
+static inline int tracehook_inhibit_wait_continued(struct task_struct *child)
+{
+#ifdef CONFIG_UTRACE
+       return (child->utrace_flags & UTRACE_ACTION_NOREAP);
+#endif
+       return 0;
+}
+
+
+/*
+ * Return LSM_UNSAFE_* bits applied to an exec because of tracing.
+ * Called with task_lock(tsk) held.
+ */
+static inline int tracehook_unsafe_exec(struct task_struct *tsk)
+{
+#ifdef CONFIG_UTRACE
+       if (tsk->utrace_flags)
+               return utrace_unsafe_exec(tsk);
+#endif
+       return 0;
+}
+
+/*
+ * Return the task_struct for the task using ptrace on this one, or NULL.
+ * Must be called with rcu_read_lock held to keep the returned struct alive.
+ *
+ * At exec time, this may be called with task_lock(p) still held from when
+ * tracehook_unsafe_exec was just called.
+ *
+ * The value is also used to display after "TracerPid:" in /proc/PID/status,
+ * where it is called with only rcu_read_lock held.
+ */
+static inline struct task_struct *tracehook_tracer_task(struct task_struct *p)
+{
+#ifdef CONFIG_UTRACE
+       if (p->utrace_flags)
+               return utrace_tracer_task(p);
+#endif
+       return NULL;
+}
+
+/*
+ * Return nonzero if the current task should be allowed to use
+ * access_process_vm on the given task.
+ */
+static inline int tracehook_allow_access_process_vm(struct task_struct *tsk)
+{
+       if (tsk == current)
+               return 1;
+#ifdef CONFIG_UTRACE
+       if (tsk->utrace_flags)
+               return utrace_allow_access_process_vm(tsk);
+#endif
+       return 0;
+}
+
+
+/***
+ ***
+ *** Following decelarations are hook stubs where core code reports
+ *** events.  These are called without locks, from the thread having the
+ *** event.  In all tracehook_report_* calls, no locks are held and the thread
+ *** is in a state close to returning to user mode with little baggage to
+ *** unwind, except as noted below for tracehook_report_clone.  It is generally
+ *** OK to block in these places if you want the user thread to be suspended.
+ ***
+ ***/
+
+/*
+ * Thread has just become a zombie (exit_state==TASK_ZOMBIE) or is about to
+ * self-reap (exit_state==EXIT_DEAD).  If normal reaping is not inhibited,
+ * tsk->exit_state might be changing in parallel.  The death_cookie was
+ * passed back by tracehook_notify_death (above).
+ */
+static inline void tracehook_report_death(struct task_struct *tsk,
+                                         int exit_state, void *death_cookie)
+{
+#ifdef CONFIG_UTRACE
+       smp_mb();
+       if (tsk->utrace_flags & (UTRACE_EVENT(DEATH) | UTRACE_ACTION_QUIESCE))
+               utrace_report_death(tsk, death_cookie);
+#endif
+}
+
+/*
+ * exec completed, we are shortly going to return to user mode.
+ * The freshly initialized register state can be seen and changed here.
+ */
+static inline void tracehook_report_exec(struct linux_binprm *bprm,
+                                   struct pt_regs *regs)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & UTRACE_EVENT(EXEC))
+               utrace_report_exec(bprm, regs);
+#endif
+}
+
+/*
+ * Called from do_exit, we are about to exit.  The code returned to the
+ * parent for wait can be changed here.
+ */
+static inline void tracehook_report_exit(long *exit_code)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & UTRACE_EVENT(EXIT))
+               utrace_report_exit(exit_code);
+#endif
+}
+
+/*
+ * Called after a child is set up, but before it has been started or
+ * been given its CLONE_STOPPED initial stop.  (See also tracehook_init_task.)
+ * This is not a good place to block, because the child has not started yet.
+ * Suspend the child here if desired, and block in clone_complete (below).
+ * This must prevent the child from self-reaping if clone_complete uses
+ * the task_struct pointer; otherwise it might have died and been released
+ * by the time tracehook_report_clone_complete is called.
+ */
+static inline void tracehook_report_clone(unsigned long clone_flags,
+                                         struct task_struct *child)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & UTRACE_EVENT(CLONE))
+               utrace_report_clone(clone_flags, child);
+#endif
+}
+
+/*
+ * Called after the child has started running, shortly after
+ * tracehook_report_clone.  This is just before the clone/fork syscall
+ * returns, or blocks for vfork child completion if (clone_flags &
+ * CLONE_VFORK).  The child pointer may be invalid if a self-reaping
+ * child died and tracehook_report_clone took no action to prevent it
+ * from self-reaping.
+ */
+static inline void tracehook_report_clone_complete(unsigned long clone_flags,
+                                                  pid_t pid,
+                                                  struct task_struct *child)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & UTRACE_ACTION_QUIESCE)
+               utrace_quiescent(current);
+#endif
+}
+
+/*
+ * Called after a CLONE_VFORK parent has waited for the child to complete.
+ * The clone/vfork system call will return immediately after this.
+ * The child pointer may be invalid if a self-reaping child died and
+ * tracehook_report_clone took no action to prevent it from self-reaping.
+ */
+static inline void tracehook_report_vfork_done(struct task_struct *child,
+                                              pid_t child_pid)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & UTRACE_EVENT(VFORK_DONE))
+               utrace_report_vfork_done(child_pid);
+#endif
+}
+
+/*
+ * Called for system call entry or exit.
+ */
+static inline void tracehook_report_syscall(struct pt_regs *regs, int is_exit)
+{
+#ifdef CONFIG_UTRACE
+       if (current->utrace_flags & (is_exit ? UTRACE_EVENT(SYSCALL_EXIT)
+                                    : UTRACE_EVENT(SYSCALL_ENTRY)))
+               utrace_report_syscall(regs, is_exit);
+#endif
+}
+
+/*
+ * Called after system call exit if single/block-stepped into the syscall.
+ */
+static inline void tracehook_report_syscall_step(struct pt_regs *regs)
+{
+}
+
+/*
+ * Called when a signal handler has been set up.
+ * Register and stack state reflects the user handler about to run.
+ * Signal mask changes have already been made.
+ */
+static inline void tracehook_report_handle_signal(int sig,
+                                                 const struct k_sigaction *ka,
+                                                 const sigset_t *oldset,
+                                                 struct pt_regs *regs)
+{
+#ifdef CONFIG_UTRACE
+       struct task_struct *tsk = current;
+       if ((tsk->utrace_flags & UTRACE_EVENT_SIGNAL_ALL)
+           && (tsk->utrace_flags & (UTRACE_ACTION_SINGLESTEP
+                                    | UTRACE_ACTION_BLOCKSTEP)))
+               utrace_signal_handler_singlestep(tsk, regs);
+#endif
+}
+
+
+#endif /* <linux/tracehook.h> */
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
new file mode 100644 (file)
index 0000000..391e7ed
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __LINUX_UACCESS_H__
+#define __LINUX_UACCESS_H__
+
+#include <asm/uaccess.h>
+
+#ifndef ARCH_HAS_NOCACHE_UACCESS
+
+static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
+                               const void __user *from, unsigned long n)
+{
+       return __copy_from_user_inatomic(to, from, n);
+}
+
+static inline unsigned long __copy_from_user_nocache(void *to,
+                               const void __user *from, unsigned long n)
+{
+       return __copy_from_user(to, from, n);
+}
+
+#endif         /* ARCH_HAS_NOCACHE_UACCESS */
+
+#endif         /* __LINUX_UACCESS_H__ */
diff --git a/include/linux/unwind.h b/include/linux/unwind.h
new file mode 100644 (file)
index 0000000..73e1751
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef _LINUX_UNWIND_H
+#define _LINUX_UNWIND_H
+
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *     Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ *
+ * A simple API for unwinding kernel stacks.  This is used for
+ * debugging and error reporting purposes.  The kernel doesn't need
+ * full-blown stack unwinding with all the bells and whistles, so there
+ * is not much point in implementing the full Dwarf2 unwind API.
+ */
+
+struct module;
+
+#ifdef CONFIG_STACK_UNWIND
+
+#include <asm/unwind.h>
+
+#ifndef ARCH_UNWIND_SECTION_NAME
+#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
+#endif
+
+/*
+ * Initialize unwind support.
+ */
+extern void unwind_init(void);
+
+#ifdef CONFIG_MODULES
+
+extern void *unwind_add_table(struct module *,
+                              const void *table_start,
+                              unsigned long table_size);
+
+extern void unwind_remove_table(void *handle, int init_only);
+
+#endif
+
+extern int unwind_init_frame_info(struct unwind_frame_info *,
+                                  struct task_struct *,
+                                  /*const*/ struct pt_regs *);
+
+/*
+ * Prepare to unwind a blocked task.
+ */
+extern int unwind_init_blocked(struct unwind_frame_info *,
+                               struct task_struct *);
+
+/*
+ * Prepare to unwind the currently running thread.
+ */
+extern int unwind_init_running(struct unwind_frame_info *,
+                               asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                          void *arg),
+                               void *arg);
+
+/*
+ * Unwind to previous to frame.  Returns 0 if successful, negative
+ * number in case of an error.
+ */
+extern int unwind(struct unwind_frame_info *);
+
+/*
+ * Unwind until the return pointer is in user-land (or until an error
+ * occurs).  Returns 0 if successful, negative number in case of
+ * error.
+ */
+extern int unwind_to_user(struct unwind_frame_info *);
+
+#else
+
+struct unwind_frame_info {};
+
+static inline void unwind_init(void) {}
+
+#ifdef CONFIG_MODULES
+
+static inline void *unwind_add_table(struct module *mod,
+                                     const void *table_start,
+                                     unsigned long table_size)
+{
+       return NULL;
+}
+
+#endif
+
+static inline void unwind_remove_table(void *handle, int init_only)
+{
+}
+
+static inline int unwind_init_frame_info(struct unwind_frame_info *info,
+                                         struct task_struct *tsk,
+                                         const struct pt_regs *regs)
+{
+       return -ENOSYS;
+}
+
+static inline int unwind_init_blocked(struct unwind_frame_info *info,
+                                      struct task_struct *tsk)
+{
+       return -ENOSYS;
+}
+
+static inline int unwind_init_running(struct unwind_frame_info *info,
+                                      asmlinkage int (*cb)(struct unwind_frame_info *,
+                                                           void *arg),
+                                      void *arg)
+{
+       return -ENOSYS;
+}
+
+static inline int unwind(struct unwind_frame_info *info)
+{
+       return -ENOSYS;
+}
+
+static inline int unwind_to_user(struct unwind_frame_info *info)
+{
+       return -ENOSYS;
+}
+
+#endif
+
+#endif /* _LINUX_UNWIND_H */
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
new file mode 100644 (file)
index 0000000..ba617c3
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * USB Communications Device Class (CDC) definitions
+ *
+ * CDC says how to talk to lots of different types of network adapters,
+ * notably ethernet adapters and various modems.  It's used mostly with
+ * firmware based USB peripherals.
+ */
+
+#define USB_CDC_SUBCLASS_ACM                   0x02
+#define USB_CDC_SUBCLASS_ETHERNET              0x06
+#define USB_CDC_SUBCLASS_WHCM                  0x08
+#define USB_CDC_SUBCLASS_DMM                   0x09
+#define USB_CDC_SUBCLASS_MDLM                  0x0a
+#define USB_CDC_SUBCLASS_OBEX                  0x0b
+
+#define USB_CDC_PROTO_NONE                     0
+
+#define USB_CDC_ACM_PROTO_AT_V25TER            1
+#define USB_CDC_ACM_PROTO_AT_PCCA101           2
+#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE      3
+#define USB_CDC_ACM_PROTO_AT_GSM               4
+#define USB_CDC_ACM_PROTO_AT_3G                        5
+#define USB_CDC_ACM_PROTO_AT_CDMA              6
+#define USB_CDC_ACM_PROTO_VENDOR               0xff
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific descriptors ... there are a couple dozen of them
+ */
+
+#define USB_CDC_HEADER_TYPE            0x00            /* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE   0x01            /* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE               0x02            /* acm_descriptor */
+#define USB_CDC_UNION_TYPE             0x06            /* union_desc */
+#define USB_CDC_COUNTRY_TYPE           0x07
+#define USB_CDC_NETWORK_TERMINAL_TYPE  0x0a            /* network_terminal_desc */
+#define USB_CDC_ETHERNET_TYPE          0x0f            /* ether_desc */
+#define USB_CDC_WHCM_TYPE              0x11
+#define USB_CDC_MDLM_TYPE              0x12            /* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE       0x13            /* mdlm_detail_desc */
+#define USB_CDC_DMM_TYPE               0x14
+#define USB_CDC_OBEX_TYPE              0x15
+
+/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
+struct usb_cdc_header_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdCDC;
+} __attribute__ ((packed));
+
+/* "Call Management Descriptor" from CDC spec  5.2.3.2 */
+struct usb_cdc_call_mgmt_descriptor {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bmCapabilities;
+#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT                0x01
+#define USB_CDC_CALL_MGMT_CAP_DATA_INTF                0x02
+
+       __u8    bDataInterface;
+} __attribute__ ((packed));
+
+/* "Abstract Control Management Descriptor" from CDC spec  5.2.3.3 */
+struct usb_cdc_acm_descriptor {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bmCapabilities;
+} __attribute__ ((packed));
+
+/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
+struct usb_cdc_union_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bMasterInterface0;
+       __u8    bSlaveInterface0;
+       /* ... and there could be other slave interfaces */
+} __attribute__ ((packed));
+
+/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */
+struct usb_cdc_network_terminal_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bEntityId;
+       __u8    iName;
+       __u8    bChannelIndex;
+       __u8    bPhysicalInterface;
+} __attribute__ ((packed));
+
+/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
+struct usb_cdc_ether_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    iMACAddress;
+       __le32  bmEthernetStatistics;
+       __le16  wMaxSegmentSize;
+       __le16  wNumberMCFilters;
+       __u8    bNumberPowerFilters;
+} __attribute__ ((packed));
+
+/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
+struct usb_cdc_mdlm_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdVersion;
+       __u8    bGUID[16];
+} __attribute__ ((packed));
+
+/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
+struct usb_cdc_mdlm_detail_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       /* type is associated with mdlm_desc.bGUID */
+       __u8    bGuidDescriptorType;
+       __u8    bDetailData[0];
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Control Requests (6.2)
+ *
+ * section 3.6.2.1 table 4 has the ACM profile, for modems.
+ * section 3.8.2 table 10 has the ethernet profile.
+ *
+ * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
+ * heavily dependent on the encapsulated (proprietary) command mechanism.
+ */
+
+#define USB_CDC_SEND_ENCAPSULATED_COMMAND      0x00
+#define USB_CDC_GET_ENCAPSULATED_RESPONSE      0x01
+#define USB_CDC_REQ_SET_LINE_CODING            0x20
+#define USB_CDC_REQ_GET_LINE_CODING            0x21
+#define USB_CDC_REQ_SET_CONTROL_LINE_STATE     0x22
+#define USB_CDC_REQ_SEND_BREAK                 0x23
+#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
+#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
+#define USB_CDC_SET_ETHERNET_PACKET_FILTER     0x43
+#define USB_CDC_GET_ETHERNET_STATISTIC         0x44
+
+/* Line Coding Structure from CDC spec 6.2.13 */
+struct usb_cdc_line_coding {
+       __le32  dwDTERate;
+       __u8    bCharFormat;
+#define USB_CDC_1_STOP_BITS                    0
+#define USB_CDC_1_5_STOP_BITS                  1
+#define USB_CDC_2_STOP_BITS                    2
+
+       __u8    bParityType;
+#define USB_CDC_NO_PARITY                      0
+#define USB_CDC_ODD_PARITY                     1
+#define USB_CDC_EVEN_PARITY                    2
+#define USB_CDC_MARK_PARITY                    3
+#define USB_CDC_SPACE_PARITY                   4
+
+       __u8    bDataBits;
+} __attribute__ ((packed));
+
+/* table 62; bits in multicast filter */
+#define        USB_CDC_PACKET_TYPE_PROMISCUOUS         (1 << 0)
+#define        USB_CDC_PACKET_TYPE_ALL_MULTICAST       (1 << 1) /* no filter */
+#define        USB_CDC_PACKET_TYPE_DIRECTED            (1 << 2)
+#define        USB_CDC_PACKET_TYPE_BROADCAST           (1 << 3)
+#define        USB_CDC_PACKET_TYPE_MULTICAST           (1 << 4) /* filtered */
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Notifications (6.3) sent by interrupt transfers
+ *
+ * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
+ * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
+ * RNDIS also defines its own bit-incompatible notifications
+ */
+
+#define USB_CDC_NOTIFY_NETWORK_CONNECTION      0x00
+#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE      0x01
+#define USB_CDC_NOTIFY_SERIAL_STATE            0x20
+#define USB_CDC_NOTIFY_SPEED_CHANGE            0x2a
+
+struct usb_cdc_notification {
+       __u8    bmRequestType;
+       __u8    bNotificationType;
+       __le16  wValue;
+       __le16  wIndex;
+       __le16  wLength;
+} __attribute__ ((packed));
+
diff --git a/include/linux/usb/input.h b/include/linux/usb/input.h
new file mode 100644 (file)
index 0000000..716e0cc
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __USB_INPUT_H
+#define __USB_INPUT_H
+
+/*
+ * Copyright (C) 2005 Dmitry Torokhov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <asm/byteorder.h>
+
+static inline void
+usb_to_input_id(const struct usb_device *dev, struct input_id *id)
+{
+       id->bustype = BUS_USB;
+       id->vendor = le16_to_cpu(dev->descriptor.idVendor);
+       id->product = le16_to_cpu(dev->descriptor.idProduct);
+       id->version = le16_to_cpu(dev->descriptor.bcdDevice);
+}
+
+#endif
diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h
new file mode 100644 (file)
index 0000000..436dd8a
--- /dev/null
@@ -0,0 +1,29 @@
+
+/*
+ * Board initialization code should put one of these into dev->platform_data
+ * and place the isp116x onto platform_bus.
+ */
+
+struct isp116x_platform_data {
+       /* Enable internal resistors on downstream ports */
+       unsigned sel15Kres:1;
+       /* On-chip overcurrent detection */
+       unsigned oc_enable:1;
+       /* INT output polarity */
+       unsigned int_act_high:1;
+       /* INT edge or level triggered */
+       unsigned int_edge_triggered:1;
+       /* Enable wakeup by devices on usb bus (e.g. wakeup
+          by attachment/detachment or by device activity
+          such as moving a mouse). When chosen, this option
+          prevents stopping internal clock, increasing
+          thereby power consumption in suspended state. */
+       unsigned remote_wakeup_enable:1;
+       /* Inter-io delay (ns). The chip is picky about access timings; it
+          expects at least:
+          150ns delay between consecutive accesses to DATA_REG,
+          300ns delay between access to ADDR_REG and DATA_REG
+          OE, WE MUST NOT be changed during these intervals
+        */
+       void (*delay) (struct device * dev, int delay);
+};
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
new file mode 100644 (file)
index 0000000..91c983e
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * USB Serial Converter stuff
+ *
+ *     Copyright (C) 1999 - 2005
+ *         Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; version 2 of the License.
+ *
+ */
+
+
+#ifndef __LINUX_USB_SERIAL_H
+#define __LINUX_USB_SERIAL_H
+
+#include <linux/kref.h>
+#include <linux/mutex.h>
+
+#define SERIAL_TTY_MAJOR       188     /* Nice legal number now */
+#define SERIAL_TTY_MINORS      255     /* loads of devices :) */
+
+#define MAX_NUM_PORTS          8       /* The maximum number of ports one device can grab at once */
+
+/* parity check flag */
+#define RELEVANT_IFLAG(iflag)  (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/**
+ * usb_serial_port: structure for the specific ports of a device.
+ * @serial: pointer back to the struct usb_serial owner of this port.
+ * @tty: pointer to the corresponding tty for this port.
+ * @lock: spinlock to grab when updating portions of this structure.
+ * @mutex: mutex used to synchronize serial_open() and serial_close()
+ *     access for this port.
+ * @number: the number of the port (the minor number).
+ * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
+ * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
+ * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe
+ *     for this port.
+ * @interrupt_out_buffer: pointer to the interrupt out buffer for this port.
+ * @interrupt_out_size: the size of the interrupt_out_buffer, in bytes.
+ * @interrupt_out_urb: pointer to the interrupt out struct urb for this port.
+ * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe
+ *     for this port.
+ * @bulk_in_buffer: pointer to the bulk in buffer for this port.
+ * @read_urb: pointer to the bulk in struct urb for this port.
+ * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this
+ *     port.
+ * @bulk_out_buffer: pointer to the bulk out buffer for this port.
+ * @bulk_out_size: the size of the bulk_out_buffer, in bytes.
+ * @write_urb: pointer to the bulk out struct urb for this port.
+ * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
+ *     port.
+ * @write_wait: a wait_queue_head_t used by the port.
+ * @work: work queue entry for the line discipline waking up.
+ * @open_count: number of times this port has been opened.
+ *
+ * This structure is used by the usb-serial core and drivers for the specific
+ * ports of a device.
+ */
+struct usb_serial_port {
+       struct usb_serial *     serial;
+       struct tty_struct *     tty;
+       spinlock_t              lock;
+       struct mutex            mutex;
+       unsigned char           number;
+
+       unsigned char *         interrupt_in_buffer;
+       struct urb *            interrupt_in_urb;
+       __u8                    interrupt_in_endpointAddress;
+
+       unsigned char *         interrupt_out_buffer;
+       int                     interrupt_out_size;
+       struct urb *            interrupt_out_urb;
+       __u8                    interrupt_out_endpointAddress;
+
+       unsigned char *         bulk_in_buffer;
+       int                     bulk_in_size;
+       struct urb *            read_urb;
+       __u8                    bulk_in_endpointAddress;
+
+       unsigned char *         bulk_out_buffer;
+       int                     bulk_out_size;
+       struct urb *            write_urb;
+       int                     write_urb_busy;
+       __u8                    bulk_out_endpointAddress;
+
+       wait_queue_head_t       write_wait;
+       struct work_struct      work;
+       int                     open_count;
+       struct device           dev;
+};
+#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
+
+/* get and set the port private data pointer helper functions */
+static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
+{
+       return dev_get_drvdata(&port->dev);
+}
+
+static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
+{
+       dev_set_drvdata(&port->dev, data);
+}
+
+/**
+ * usb_serial - structure used by the usb-serial core for a device
+ * @dev: pointer to the struct usb_device for this device
+ * @type: pointer to the struct usb_serial_driver for this device
+ * @interface: pointer to the struct usb_interface for this device
+ * @minor: the starting minor number for this device
+ * @num_ports: the number of ports this device has
+ * @num_interrupt_in: number of interrupt in endpoints we have
+ * @num_interrupt_out: number of interrupt out endpoints we have
+ * @num_bulk_in: number of bulk in endpoints we have
+ * @num_bulk_out: number of bulk out endpoints we have
+ * @port: array of struct usb_serial_port structures for the different ports.
+ * @private: place to put any driver specific information that is needed.  The
+ *     usb-serial driver is required to manage this data, the usb-serial core
+ *     will not touch this.  Use usb_get_serial_data() and
+ *     usb_set_serial_data() to access this.
+ */
+struct usb_serial {
+       struct usb_device *             dev;
+       struct usb_serial_driver *      type;
+       struct usb_interface *          interface;
+       unsigned char                   minor;
+       unsigned char                   num_ports;
+       unsigned char                   num_port_pointers;
+       char                            num_interrupt_in;
+       char                            num_interrupt_out;
+       char                            num_bulk_in;
+       char                            num_bulk_out;
+       struct usb_serial_port *        port[MAX_NUM_PORTS];
+       struct kref                     kref;
+       void *                          private;
+};
+#define to_usb_serial(d) container_of(d, struct usb_serial, kref)
+
+#define NUM_DONT_CARE  (-1)
+
+/* get and set the serial private data pointer helper functions */
+static inline void *usb_get_serial_data (struct usb_serial *serial)
+{
+       return serial->private;
+}
+
+static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+{
+       serial->private = data;
+}
+
+/**
+ * usb_serial_driver - describes a usb serial driver
+ * @description: pointer to a string that describes this driver.  This string used
+ *     in the syslog messages when a device is inserted or removed.
+ * @id_table: pointer to a list of usb_device_id structures that define all
+ *     of the devices this structure can support.
+ * @num_interrupt_in: the number of interrupt in endpoints this device will
+ *     have.
+ * @num_interrupt_out: the number of interrupt out endpoints this device will
+ *     have.
+ * @num_bulk_in: the number of bulk in endpoints this device will have.
+ * @num_bulk_out: the number of bulk out endpoints this device will have.
+ * @num_ports: the number of different ports this device will have.
+ * @calc_num_ports: pointer to a function to determine how many ports this
+ *     device has dynamically.  It will be called after the probe()
+ *     callback is called, but before attach()
+ * @probe: pointer to the driver's probe function.
+ *     This will be called when the device is inserted into the system,
+ *     but before the device has been fully initialized by the usb_serial
+ *     subsystem.  Use this function to download any firmware to the device,
+ *     or any other early initialization that might be needed.
+ *     Return 0 to continue on with the initialization sequence.  Anything
+ *     else will abort it.
+ * @attach: pointer to the driver's attach function.
+ *     This will be called when the struct usb_serial structure is fully set
+ *     set up.  Do any local initialization of the device, or any private
+ *     memory structure allocation at this point in time.
+ * @shutdown: pointer to the driver's shutdown function.  This will be
+ *     called when the device is removed from the system.
+ *
+ * This structure is defines a USB Serial driver.  It provides all of
+ * the information that the USB serial core code needs.  If the function
+ * pointers are defined, then the USB serial core code will call them when
+ * the corresponding tty port functions are called.  If they are not
+ * called, the generic serial function will be used instead.
+ *
+ * The driver.owner field should be set to the module owner of this driver.
+ * The driver.name field should be set to the name of this driver (remember
+ * it will show up in sysfs, so it needs to be short and to the point.
+ * Useing the module name is a good idea.)
+ */
+struct usb_serial_driver {
+       const char *description;
+       const struct usb_device_id *id_table;
+       char    num_interrupt_in;
+       char    num_interrupt_out;
+       char    num_bulk_in;
+       char    num_bulk_out;
+       char    num_ports;
+
+       struct list_head        driver_list;
+       struct device_driver    driver;
+
+       int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
+       int (*attach) (struct usb_serial *serial);
+       int (*calc_num_ports) (struct usb_serial *serial);
+
+       void (*shutdown) (struct usb_serial *serial);
+
+       int (*port_probe) (struct usb_serial_port *port);
+       int (*port_remove) (struct usb_serial_port *port);
+
+       /* serial function calls */
+       int  (*open)            (struct usb_serial_port *port, struct file * filp);
+       void (*close)           (struct usb_serial_port *port, struct file * filp);
+       int  (*write)           (struct usb_serial_port *port, const unsigned char *buf, int count);
+       int  (*write_room)      (struct usb_serial_port *port);
+       int  (*ioctl)           (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+       void (*set_termios)     (struct usb_serial_port *port, struct termios * old);
+       void (*break_ctl)       (struct usb_serial_port *port, int break_state);
+       int  (*chars_in_buffer) (struct usb_serial_port *port);
+       void (*throttle)        (struct usb_serial_port *port);
+       void (*unthrottle)      (struct usb_serial_port *port);
+       int  (*tiocmget)        (struct usb_serial_port *port, struct file *file);
+       int  (*tiocmset)        (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
+
+       void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
+       void (*write_int_callback)(struct urb *urb, struct pt_regs *regs);
+       void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
+       void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
+};
+#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
+
+extern int  usb_serial_register(struct usb_serial_driver *driver);
+extern void usb_serial_deregister(struct usb_serial_driver *driver);
+extern void usb_serial_port_softint(struct usb_serial_port *port);
+
+extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
+extern void usb_serial_disconnect(struct usb_interface *iface);
+
+extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
+extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
+
+/* USB Serial console functions */
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+extern void usb_serial_console_init (int debug, int minor);
+extern void usb_serial_console_exit (void);
+extern void usb_serial_console_disconnect(struct usb_serial *serial);
+#else
+static inline void usb_serial_console_init (int debug, int minor) { }
+static inline void usb_serial_console_exit (void) { }
+static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
+#endif
+
+/* Functions needed by other parts of the usbserial core */
+extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
+extern void usb_serial_put(struct usb_serial *serial);
+extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
+extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_write_room (struct usb_serial_port *port);
+extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
+extern void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
+extern void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
+extern void usb_serial_generic_shutdown (struct usb_serial *serial);
+extern int usb_serial_generic_register (int debug);
+extern void usb_serial_generic_deregister (void);
+
+extern int usb_serial_bus_register (struct usb_serial_driver *device);
+extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
+
+extern struct usb_serial_driver usb_serial_generic_device;
+extern struct bus_type usb_serial_bus_type;
+extern struct tty_driver *usb_serial_tty_driver;
+
+static inline void usb_serial_debug_data(int debug,
+                                        struct device *dev,
+                                        const char *function, int size,
+                                        const unsigned char *data)
+{
+       int i;
+
+       if (debug) {
+               dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", function, size);
+               for (i = 0; i < size; ++i)
+                       printk ("%.2x ", data[i]);
+               printk ("\n");
+       }
+}
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
+
+
+
+#endif /* ifdef __LINUX_USB_SERIAL_H */
+
diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h
new file mode 100644 (file)
index 0000000..397ee3b
--- /dev/null
@@ -0,0 +1,26 @@
+
+/*
+ * board initialization should put one of these into dev->platform_data
+ * and place the sl811hs onto platform_bus named "sl811-hcd".
+ */
+
+struct sl811_platform_data {
+       unsigned        can_wakeup:1;
+
+       /* given port_power, msec/2 after power on till power good */
+       u8              potpg;
+
+       /* mA/2 power supplied on this port (max = default = 250) */
+       u8              power;
+
+       /* sl811 relies on an external source of VBUS current */
+       void            (*port_power)(struct device *dev, int is_on);
+
+       /* pulse sl811 nRST (probably with a GPIO) */
+       void            (*reset)(struct device *dev);
+
+       // some boards need something like these:
+       // int          (*check_overcurrent)(struct device *dev);
+       // void         (*clock_enable)(struct device *dev, int is_on);
+};
+
diff --git a/include/linux/utrace.h b/include/linux/utrace.h
new file mode 100644 (file)
index 0000000..e0f8ae1
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * User Debugging Data & Event Rendezvous
+ *
+ * This interface allows for notification of interesting events in a thread.
+ * It also mediates access to thread state such as registers.
+ * Multiple unrelated users can be associated with a single thread.
+ * We call each of these a tracing engine.
+ *
+ * A tracing engine starts by calling utrace_attach on the chosen thread,
+ * passing in a set of hooks (struct utrace_engine_ops), and some associated
+ * data.  This produces a struct utrace_attached_engine, which is the handle
+ * used for all other operations.  An attached engine has its ops vector,
+ * its data, and a flags word controlled by utrace_set_flags.
+ *
+ * Each engine's flags word contains two kinds of flags: events of
+ * interest, and action state flags.
+ *
+ * For each event flag that is set, that engine will get the
+ * appropriate ops->report_* callback when the event occurs.  The
+ * struct utrace_engine_ops need not provide callbacks for an event
+ * unless the engine sets one of the associated event flags.
+ *
+ * Action state flags change the normal behavior of the thread.
+ * These bits are in UTRACE_ACTION_STATE_MASK; these can be OR'd into
+ * flags set with utrace_set_flags.  Also, every callback that return
+ * an action value can reset these bits for the engine (see below).
+ *
+ * The bits UTRACE_ACTION_STATE_MASK of all attached engines are OR'd
+ * together, so each action is in force as long as any engine requests it.
+ * As long as some engine sets the UTRACE_ACTION_QUIESCE flag, the thread
+ * will block and not resume running user code.  When the last engine
+ * clears its UTRACE_ACTION_QUIESCE flag, the thread will resume running.
+ */
+
+#ifndef _LINUX_UTRACE_H
+#define _LINUX_UTRACE_H        1
+
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+#include <linux/signal.h>
+
+struct linux_binprm;
+struct pt_regs;
+struct utrace_regset;
+struct utrace_regset_view;
+
+
+/*
+ * Flags in task_struct.utrace_flags and utrace_attached_engine.flags.
+ * Low four bits are UTRACE_ACTION_STATE_MASK bits (below).
+ * Higher bits are events of interest.
+ */
+
+#define UTRACE_FIRST_EVENT     4
+#define UTRACE_EVENT_BITS      (BITS_PER_LONG - UTRACE_FIRST_EVENT)
+#define UTRACE_EVENT_MASK      (-1UL &~ UTRACE_ACTION_STATE_MASK)
+
+enum utrace_events {
+       _UTRACE_EVENT_QUIESCE,  /* Tracing requests stop.  */
+       _UTRACE_EVENT_REAP,     /* Zombie reaped, no more tracing possible.  */
+       _UTRACE_EVENT_CLONE,    /* Successful clone/fork/vfork just done.  */
+       _UTRACE_EVENT_VFORK_DONE, /* vfork woke from waiting for child.  */
+       _UTRACE_EVENT_EXEC,     /* Successful execve just completed.  */
+       _UTRACE_EVENT_EXIT,     /* Thread exit in progress.  */
+       _UTRACE_EVENT_DEATH,    /* Thread has died.  */
+       _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */
+       _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call.  */
+       _UTRACE_EVENT_SIGNAL,   /* Signal delivery will run a user handler.  */
+       _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered.  */
+       _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend.  */
+       _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate.  */
+       _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core.  */
+       _UTRACE_EVENT_JCTL,     /* Job control stop or continue completed.  */
+       _UTRACE_NEVENTS
+};
+#define UTRACE_EVENT_BIT(type) (UTRACE_FIRST_EVENT + _UTRACE_EVENT_##type)
+#define UTRACE_EVENT(type)     (1UL << UTRACE_EVENT_BIT(type))
+
+/*
+ * All the kinds of signal events.  These all use the report_signal callback.
+ */
+#define UTRACE_EVENT_SIGNAL_ALL        (UTRACE_EVENT(SIGNAL) \
+                                | UTRACE_EVENT(SIGNAL_IGN) \
+                                | UTRACE_EVENT(SIGNAL_STOP) \
+                                | UTRACE_EVENT(SIGNAL_TERM) \
+                                | UTRACE_EVENT(SIGNAL_CORE))
+/*
+ * Both kinds of syscall events; these call the report_syscall_entry and
+ * report_syscall_exit callbacks, respectively.
+ */
+#define UTRACE_EVENT_SYSCALL   \
+       (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT))
+
+
+/*
+ * Action flags, in return value of callbacks.
+ *
+ * UTRACE_ACTION_RESUME (zero) is the return value to do nothing special.
+ * For each particular callback, some bits in UTRACE_ACTION_OP_MASK can
+ * be set in the return value to change the thread's behavior (see below).
+ *
+ * If UTRACE_ACTION_NEWSTATE is set, then the UTRACE_ACTION_STATE_MASK
+ * bits in the return value replace the engine's flags as in utrace_set_flags
+ * (but the event flags remained unchanged).
+ *
+ * If UTRACE_ACTION_HIDE is set, then the callbacks to other engines
+ * should be suppressed for this event.  This is appropriate only when
+ * the event was artificially provoked by something this engine did,
+ * such as setting a breakpoint.
+ *
+ * If UTRACE_ACTION_DETACH is set, this engine is detached as by utrace_detach.
+ * The action bits in UTRACE_ACTION_OP_MASK work as normal, but the engine's
+ * UTRACE_ACTION_STATE_MASK bits will no longer affect the thread.
+ */
+#define UTRACE_ACTION_RESUME   0x0000 /* Continue normally after event.  */
+#define UTRACE_ACTION_HIDE     0x0010 /* Hide event from other tracing.  */
+#define UTRACE_ACTION_DETACH   0x0020 /* Detach me, state flags ignored.  */
+#define UTRACE_ACTION_NEWSTATE 0x0040 /* Replace state bits.  */
+
+/*
+ * These flags affect the state of the thread until they are changed via
+ * utrace_set_flags or by the next callback to the same engine that uses
+ * UTRACE_ACTION_NEWSTATE.
+ */
+#define UTRACE_ACTION_QUIESCE  0x0001 /* Stay quiescent after callbacks.  */
+#define UTRACE_ACTION_SINGLESTEP 0x0002 /* Resume for one instruction.  */
+#define UTRACE_ACTION_BLOCKSTEP 0x0004 /* Resume until next branch.  */
+#define UTRACE_ACTION_NOREAP   0x0008 /* Inhibit parent SIGCHLD and wait.  */
+#define UTRACE_ACTION_STATE_MASK 0x000f /* Lasting state bits.  */
+
+/* These flags have meanings specific to the particular event report hook.  */
+#define UTRACE_ACTION_OP_MASK  0xff00
+
+/*
+ * Action flags in return value and argument of report_signal callback.
+ */
+#define UTRACE_SIGNAL_DELIVER  0x0100 /* Deliver according to sigaction.  */
+#define UTRACE_SIGNAL_IGN      0x0200 /* Ignore the signal.  */
+#define UTRACE_SIGNAL_TERM     0x0300 /* Terminate the process.  */
+#define UTRACE_SIGNAL_CORE     0x0400 /* Terminate with core dump.  */
+#define UTRACE_SIGNAL_STOP     0x0500 /* Deliver as absolute stop.  */
+#define UTRACE_SIGNAL_TSTP     0x0600 /* Deliver as job control stop.  */
+#define UTRACE_SIGNAL_HOLD     0x1000 /* Flag, push signal back on queue.  */
+/*
+ * This value is passed to a report_signal callback after a signal
+ * handler is entered while UTRACE_ACTION_SINGLESTEP is in force.
+ * For this callback, no signal will never actually be delivered regardless
+ * of the return value, and the other callback parameters are null.
+ */
+#define UTRACE_SIGNAL_HANDLER  0x0700
+
+/* Action flag in return value of report_jctl.  */
+#define UTRACE_JCTL_NOSIGCHLD  0x0100 /* Do not notify the parent.  */
+
+
+/*
+ * Flags for utrace_attach.  If UTRACE_ATTACH_CREATE is not specified,
+ * you only look up an existing engine already attached to the
+ * thread.  If UTRACE_ATTACH_MATCH_* bits are set, only consider
+ * matching engines.  If UTRACE_ATTACH_EXCLUSIVE is set, attempting to
+ * attach a second (matching) engine fails with -EEXIST.
+ */
+#define UTRACE_ATTACH_CREATE           0x0010 /* Attach a new engine.  */
+#define UTRACE_ATTACH_EXCLUSIVE                0x0020 /* Refuse if existing match.  */
+#define UTRACE_ATTACH_MATCH_OPS                0x0001 /* Match engines on ops.  */
+#define UTRACE_ATTACH_MATCH_DATA       0x0002 /* Match engines on data.  */
+#define UTRACE_ATTACH_MATCH_MASK       0x000f
+
+
+/*
+ * Per-thread structure task_struct.utrace points to.
+ *
+ * The task itself never has to worry about this going away after
+ * some event is found set in task_struct.utrace_flags.
+ * Once created, this pointer is changed only when the task is quiescent
+ * (TASK_TRACED or TASK_STOPPED with the siglock held, or dead).
+ *
+ * For other parties, the pointer to this is protected by RCU and
+ * task_lock.  Since call_rcu is never used while the thread is alive and
+ * using this struct utrace, we can overlay the RCU data structure used
+ * only for a dead struct with some local state used only for a live utrace
+ * on an active thread.
+ */
+struct utrace
+{
+       union {
+               struct rcu_head dead;
+               struct {
+                       struct task_struct *cloning;
+                       struct utrace_signal *signal;
+               } live;
+               struct {
+                       int notified;
+                       int reap;
+               } exit;
+       } u;
+
+       struct list_head engines;
+       spinlock_t lock;
+};
+#define utrace_lock(utrace)    spin_lock(&(utrace)->lock)
+#define utrace_unlock(utrace)  spin_unlock(&(utrace)->lock)
+
+
+/*
+ * Per-engine per-thread structure.
+ *
+ * The task itself never has to worry about engines detaching while
+ * it's doing event callbacks.  These structures are freed only when
+ * the task is quiescent.  For other parties, the list is protected
+ * by RCU and utrace_lock.
+ */
+struct utrace_attached_engine
+{
+       struct list_head entry; /* Entry on thread's utrace.engines list.  */
+       struct rcu_head rhead;
+
+       const struct utrace_engine_ops *ops;
+       unsigned long data;
+
+       unsigned long flags;
+};
+
+
+struct utrace_engine_ops
+{
+       /*
+        * Event reporting hooks.
+        *
+        * Return values contain UTRACE_ACTION_* flag bits.
+        * The UTRACE_ACTION_OP_MASK bits are specific to each kind of event.
+        *
+        * All report_* hooks are called with no locks held, in a generally
+        * safe environment when we will be returning to user mode soon.
+        * It is fine to block for memory allocation and the like, but all
+        * hooks are *asynchronous* and must not block on external events.
+        * If you want the thread to block, request UTRACE_ACTION_QUIESCE in
+        * your hook; then later wake it up with utrace_set_flags.
+        *
+        */
+
+       /*
+        * Event reported for parent, before child might run.
+        * The PF_STARTING flag prevents other engines from attaching
+        * before this one has its chance.
+        */
+       u32 (*report_clone)(struct utrace_attached_engine *engine,
+                           struct task_struct *parent,
+                           unsigned long clone_flags,
+                           struct task_struct *child);
+
+       /*
+        * Event reported for parent using CLONE_VFORK or vfork system call.
+        * The child has died or exec'd, so the vfork parent has unblocked
+        * and is about to return child_pid.
+        */
+       u32 (*report_vfork_done)(struct utrace_attached_engine *engine,
+                                struct task_struct *parent, pid_t child_pid);
+
+       /*
+        * Event reported after UTRACE_ACTION_QUIESCE is set, when the target
+        * thread is quiescent.  Either it's the current thread, or it's in
+        * TASK_TRACED or TASK_STOPPED and will not resume running until the
+        * UTRACE_ACTION_QUIESCE flag is no longer asserted by any engine.
+        */
+       u32 (*report_quiesce)(struct utrace_attached_engine *engine,
+                             struct task_struct *tsk);
+
+       /*
+        * Thread dequeuing a signal to be delivered.
+        * The action and *return_ka values say what UTRACE_ACTION_RESUME
+        * will do (possibly already influenced by another tracing engine).
+        * An UTRACE_SIGNAL_* return value overrides the signal disposition.
+        * The *info data (including info->si_signo) can be changed at will.
+        * Changing *return_ka affects the sigaction that be used.
+        * The *orig_ka value is the one in force before other tracing
+        * engines intervened.
+        */
+       u32 (*report_signal)(struct utrace_attached_engine *engine,
+                            struct task_struct *tsk,
+                            struct pt_regs *regs,
+                            u32 action, siginfo_t *info,
+                            const struct k_sigaction *orig_ka,
+                            struct k_sigaction *return_ka);
+
+       /*
+        * Job control event completing, about to send SIGCHLD to parent
+        * with CLD_STOPPED or CLD_CONTINUED as given in type.
+        * UTRACE_JOBSTOP_NOSIGCHLD in the return value inhibits that.
+        */
+       u32 (*report_jctl)(struct utrace_attached_engine *engine,
+                          struct task_struct *tsk,
+                          int type);
+
+       /*
+        * Thread has just completed an exec.
+        * The initial user register state is handy to be tweaked directly.
+        */
+       u32 (*report_exec)(struct utrace_attached_engine *engine,
+                          struct task_struct *tsk,
+                          const struct linux_binprm *bprm,
+                          struct pt_regs *regs);
+
+       /*
+        * Thread has entered the kernel to request a system call.
+        * The user register state is handy to be tweaked directly.
+        */
+       u32 (*report_syscall_entry)(struct utrace_attached_engine *engine,
+                                   struct task_struct *tsk,
+                                   struct pt_regs *regs);
+
+       /*
+        * Thread is about to leave the kernel after a system call request.
+        * The user register state is handy to be tweaked directly.
+        */
+       u32 (*report_syscall_exit)(struct utrace_attached_engine *engine,
+                                  struct task_struct *tsk,
+                                  struct pt_regs *regs);
+
+       /*
+        * Thread is exiting and cannot be prevented from doing so,
+        * but all its state is still live.  The *code value will be
+        * the wait result seen by the parent, and can be changed by
+        * this engine or others.  The orig_code value is the real
+        * status, not changed by any tracing engine.
+        */
+       u32 (*report_exit)(struct utrace_attached_engine *engine,
+                          struct task_struct *tsk,
+                          long orig_code, long *code);
+
+       /*
+        * Thread is really dead now.  If UTRACE_ACTION_NOREAP is in force,
+        * it remains an unreported zombie.  Otherwise, it might be reaped
+        * by its parent, or self-reap immediately.  Though the actual
+        * reaping may happen in parallel, a report_reap callback will
+        * always be ordered after a report_death callback.
+        */
+       u32 (*report_death)(struct utrace_attached_engine *engine,
+                           struct task_struct *tsk);
+
+       /*
+        * Called when someone reaps the dead task (parent, init, or self).
+        * No more callbacks are made after this one.
+        * The engine is always detached.
+        * There is nothing more a tracing engine can do about this thread.
+        */
+       void (*report_reap)(struct utrace_attached_engine *engine,
+                           struct task_struct *tsk);
+
+       /*
+        * Miscellaneous hooks.  These are not associated with event reports.
+        * Any of these may be null if the engine has nothing to say.
+        * These hooks are called in more constrained environments and should
+        * not block or do very much.
+        */
+
+       /*
+        * Return nonzero iff the caller task should be allowed to access
+        * the memory of the target task via /proc/PID/mem and so forth,
+        * by dint of this engine's attachment to the target.
+        */
+       int (*allow_access_process_vm)(struct utrace_attached_engine *engine,
+                                      struct task_struct *target,
+                                      struct task_struct *caller);
+
+       /*
+        * Return LSM_UNSAFE_* bits that apply to the exec in progress
+        * due to tracing done by this engine.  These bits indicate that
+        * someone is able to examine the process and so a set-UID or similar
+        * privilege escalation may not be safe to permit.
+        *
+        * Called with task_lock held.
+        */
+       int (*unsafe_exec)(struct utrace_attached_engine *engine,
+                          struct task_struct *target);
+
+       /*
+        * Return the task_struct for the task using ptrace on this one, or
+        * NULL.  Always called with rcu_read_lock held to keep the
+        * returned struct alive.
+        *
+        * At exec time, this may be called with task_lock(target) still
+        * held from when unsafe_exec was just called.  In that case it
+        * must give results consistent with those unsafe_exec results,
+        * i.e. non-NULL if any LSM_UNSAFE_PTRACE_* bits were set.
+        *
+        * The value is also used to display after "TracerPid:" in
+        * /proc/PID/status, where it is called with only rcu_read_lock held.
+        *
+        * If this engine returns NULL, another engine may supply the result.
+        */
+       struct task_struct *(*tracer_task)(struct utrace_attached_engine *,
+                                          struct task_struct *target);
+};
+
+
+/***
+ *** These are the exported entry points for tracing engines to use.
+ ***/
+
+/*
+ * Attach a new tracing engine to a thread, or look up attached engines.
+ * See UTRACE_ATTACH_* flags, above.  The caller must ensure that the
+ * target thread does not get freed, i.e. hold a ref or be its parent.
+ */
+struct utrace_attached_engine *utrace_attach(struct task_struct *target,
+                                            int flags,
+                                            const struct utrace_engine_ops *,
+                                            unsigned long data);
+
+/*
+ * Detach a tracing engine from a thread.  After this, the engine
+ * data structure is no longer accessible, and the thread might be reaped.
+ * The thread will start running again if it was being kept quiescent
+ * and no longer has any attached engines asserting UTRACE_ACTION_QUIESCE.
+ *
+ * If the target thread is not already quiescent, then a callback to this
+ * engine might be in progress or about to start on another CPU.  If it's
+ * quiescent when utrace_detach is called, then after return it's guaranteed
+ * that no more callbacks to the ops vector will be done.
+ */
+void utrace_detach(struct task_struct *target,
+                  struct utrace_attached_engine *engine);
+
+/*
+ * Change the flags for a tracing engine.
+ * This resets the event flags and the action state flags.
+ * If UTRACE_ACTION_QUIESCE and UTRACE_EVENT(QUIESCE) are set,
+ * this will cause a report_quiesce callback soon, maybe immediately.
+ * If UTRACE_ACTION_QUIESCE was set before and is no longer set by
+ * any engine, this will wake the thread up.
+ */
+void utrace_set_flags(struct task_struct *target,
+                     struct utrace_attached_engine *engine,
+                     unsigned long flags);
+
+/*
+ * Cause a specified signal delivery in the target thread, which must be
+ * quiescent (or the current thread).  The action has UTRACE_SIGNAL_* bits
+ * as returned from a report_signal callback.  If ka is non-null, it gives
+ * the sigaction to follow for UTRACE_SIGNAL_DELIVER; otherwise, the
+ * installed sigaction at the time of delivery is used.
+ */
+int utrace_inject_signal(struct task_struct *target,
+                        struct utrace_attached_engine *engine,
+                        u32 action, siginfo_t *info,
+                        const struct k_sigaction *ka);
+
+/*
+ * Prepare to access thread's machine state, see <linux/tracehook.h>.
+ * The given thread must be quiescent (or the current thread).
+ * When this returns, the struct utrace_regset calls may be used to
+ * interrogate or change the thread's state.  Do not cache the returned
+ * pointer when the thread can resume.  You must call utrace_regset to
+ * ensure that context switching has completed and consistent state is
+ * available.
+ */
+const struct utrace_regset *utrace_regset(struct task_struct *target,
+                                         struct utrace_attached_engine *,
+                                         const struct utrace_regset_view *,
+                                         int which);
+
+
+/*
+ * Hooks in <linux/tracehook.h> call these entry points to the utrace dispatch.
+ */
+void utrace_quiescent(struct task_struct *);
+void utrace_release_task(struct task_struct *);
+int utrace_get_signal(struct task_struct *, struct pt_regs *,
+                     siginfo_t *, struct k_sigaction *);
+void utrace_report_clone(unsigned long clone_flags, struct task_struct *child);
+void utrace_report_vfork_done(pid_t child_pid);
+void utrace_report_exit(long *exit_code);
+void utrace_report_death(struct task_struct *, struct utrace *);
+int utrace_report_jctl(int type);
+void utrace_report_exec(struct linux_binprm *bprm, struct pt_regs *regs);
+void utrace_report_syscall(struct pt_regs *regs, int is_exit);
+struct task_struct *utrace_tracer_task(struct task_struct *);
+int utrace_allow_access_process_vm(struct task_struct *);
+int utrace_unsafe_exec(struct task_struct *);
+void utrace_signal_handler_singlestep(struct task_struct *, struct pt_regs *);
+
+
+#endif /* linux/utrace.h */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
new file mode 100644 (file)
index 0000000..1983726
--- /dev/null
@@ -0,0 +1,219 @@
+#ifndef _LINUX_VMSTAT_H
+#define _LINUX_VMSTAT_H
+
+#include <linux/types.h>
+#include <linux/percpu.h>
+#include <linux/mmzone.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+/*
+ * Light weight per cpu counter implementation.
+ *
+ * Counters should only be incremented and no critical kernel component
+ * should rely on the counter values.
+ *
+ * Counters are handled completely inline. On many platforms the code
+ * generated will simply be the increment of a global address.
+ */
+
+#define FOR_ALL_ZONES(x) x##_DMA, x##_DMA32, x##_NORMAL, x##_HIGH
+
+enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
+               FOR_ALL_ZONES(PGALLOC),
+               PGFREE, PGACTIVATE, PGDEACTIVATE,
+               PGFAULT, PGMAJFAULT,
+               FOR_ALL_ZONES(PGREFILL),
+               FOR_ALL_ZONES(PGSTEAL),
+               FOR_ALL_ZONES(PGSCAN_KSWAPD),
+               FOR_ALL_ZONES(PGSCAN_DIRECT),
+               PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL,
+               PAGEOUTRUN, ALLOCSTALL, PGROTATED,
+               NR_VM_EVENT_ITEMS
+};
+
+struct vm_event_state {
+       unsigned long event[NR_VM_EVENT_ITEMS];
+};
+
+DECLARE_PER_CPU(struct vm_event_state, vm_event_states);
+
+static inline void __count_vm_event(enum vm_event_item item)
+{
+       __get_cpu_var(vm_event_states).event[item]++;
+}
+
+static inline void count_vm_event(enum vm_event_item item)
+{
+       get_cpu_var(vm_event_states).event[item]++;
+       put_cpu();
+}
+
+static inline void __count_vm_events(enum vm_event_item item, long delta)
+{
+       __get_cpu_var(vm_event_states).event[item] += delta;
+}
+
+static inline void count_vm_events(enum vm_event_item item, long delta)
+{
+       get_cpu_var(vm_event_states).event[item] += delta;
+       put_cpu();
+}
+
+extern void all_vm_events(unsigned long *);
+extern void vm_events_fold_cpu(int cpu);
+
+#else
+
+/* Disable counters */
+#define get_cpu_vm_events(e)   0L
+#define count_vm_event(e)      do { } while (0)
+#define count_vm_events(e,d)   do { } while (0)
+#define __count_vm_event(e)    do { } while (0)
+#define __count_vm_events(e,d) do { } while (0)
+#define vm_events_fold_cpu(x)  do { } while (0)
+
+#endif /* CONFIG_VM_EVENT_COUNTERS */
+
+#define __count_zone_vm_events(item, zone, delta) \
+                       __count_vm_events(item##_DMA + zone_idx(zone), delta)
+
+/*
+ * Zone based page accounting with per cpu differentials.
+ */
+extern atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+
+static inline void zone_page_state_add(long x, struct zone *zone,
+                                enum zone_stat_item item)
+{
+       atomic_long_add(x, &zone->vm_stat[item]);
+       atomic_long_add(x, &vm_stat[item]);
+}
+
+static inline unsigned long global_page_state(enum zone_stat_item item)
+{
+       long x = atomic_long_read(&vm_stat[item]);
+#ifdef CONFIG_SMP
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
+}
+
+static inline unsigned long zone_page_state(struct zone *zone,
+                                       enum zone_stat_item item)
+{
+       long x = atomic_long_read(&zone->vm_stat[item]);
+#ifdef CONFIG_SMP
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
+}
+
+#ifdef CONFIG_NUMA
+/*
+ * Determine the per node value of a stat item. This function
+ * is called frequently in a NUMA machine, so try to be as
+ * frugal as possible.
+ */
+static inline unsigned long node_page_state(int node,
+                                enum zone_stat_item item)
+{
+       struct zone *zones = NODE_DATA(node)->node_zones;
+
+       return
+#ifndef CONFIG_DMA_IS_NORMAL
+#if !defined(CONFIG_DMA_IS_DMA32) && BITS_PER_LONG >= 64
+               zone_page_state(&zones[ZONE_DMA32], item) +
+#endif
+               zone_page_state(&zones[ZONE_NORMAL], item) +
+#endif
+#ifdef CONFIG_HIGHMEM
+               zone_page_state(&zones[ZONE_HIGHMEM], item) +
+#endif
+               zone_page_state(&zones[ZONE_DMA], item);
+}
+
+extern void zone_statistics(struct zonelist *, struct zone *);
+
+#else
+
+#define node_page_state(node, item) global_page_state(item)
+#define zone_statistics(_zl,_z) do { } while (0)
+
+#endif /* CONFIG_NUMA */
+
+#define __add_zone_page_state(__z, __i, __d)   \
+               __mod_zone_page_state(__z, __i, __d)
+#define __sub_zone_page_state(__z, __i, __d)   \
+               __mod_zone_page_state(__z, __i,-(__d))
+
+#define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d)
+#define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d))
+
+static inline void zap_zone_vm_stats(struct zone *zone)
+{
+       memset(zone->vm_stat, 0, sizeof(zone->vm_stat));
+}
+
+extern void inc_zone_state(struct zone *, enum zone_stat_item);
+
+#ifdef CONFIG_SMP
+void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int);
+void __inc_zone_page_state(struct page *, enum zone_stat_item);
+void __dec_zone_page_state(struct page *, enum zone_stat_item);
+
+void mod_zone_page_state(struct zone *, enum zone_stat_item, int);
+void inc_zone_page_state(struct page *, enum zone_stat_item);
+void dec_zone_page_state(struct page *, enum zone_stat_item);
+
+extern void inc_zone_state(struct zone *, enum zone_stat_item);
+
+void refresh_cpu_vm_stats(int);
+void refresh_vm_stats(void);
+
+#else /* CONFIG_SMP */
+
+/*
+ * We do not maintain differentials in a single processor configuration.
+ * The functions directly modify the zone and global counters.
+ */
+static inline void __mod_zone_page_state(struct zone *zone,
+                       enum zone_stat_item item, int delta)
+{
+       zone_page_state_add(delta, zone, item);
+}
+
+static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
+{
+       atomic_long_inc(&zone->vm_stat[item]);
+       atomic_long_inc(&vm_stat[item]);
+}
+
+static inline void __inc_zone_page_state(struct page *page,
+                       enum zone_stat_item item)
+{
+       __inc_zone_state(page_zone(page), item);
+}
+
+static inline void __dec_zone_page_state(struct page *page,
+                       enum zone_stat_item item)
+{
+       atomic_long_dec(&page_zone(page)->vm_stat[item]);
+       atomic_long_dec(&vm_stat[item]);
+}
+
+/*
+ * We only use atomic operations to update counters. So there is no need to
+ * disable interrupts.
+ */
+#define inc_zone_page_state __inc_zone_page_state
+#define dec_zone_page_state __dec_zone_page_state
+#define mod_zone_page_state __mod_zone_page_state
+
+static inline void refresh_cpu_vm_stats(int cpu) { }
+static inline void refresh_vm_stats(void) { }
+#endif
+
+#endif /* _LINUX_VMSTAT_H */
diff --git a/include/linux/vs_cvirt.h.orig b/include/linux/vs_cvirt.h.orig
new file mode 100644 (file)
index 0000000..c6aa9d3
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef _VX_VS_CVIRT_H
+#define _VX_VS_CVIRT_H
+
+#include "vserver/cvirt.h"
+#include "vserver/debug.h"
+
+
+/* utsname virtualization */
+
+static inline struct new_utsname *vx_new_utsname(void)
+{
+       if (current->vx_info)
+               return &current->vx_info->cvirt.utsname;
+       return &system_utsname;
+}
+
+#define vx_new_uts(x)          ((vx_new_utsname())->x)
+
+
+/* pid faking stuff */
+
+
+#define vx_info_map_pid(v,p) \
+       __vx_info_map_pid((v), (p), __FUNC__, __FILE__, __LINE__)
+#define vx_info_map_tgid(v,p)  vx_info_map_pid(v,p)
+#define vx_map_pid(p)  vx_info_map_pid(current->vx_info, p)
+#define vx_map_tgid(p) vx_map_pid(p)
+
+static inline int __vx_info_map_pid(struct vx_info *vxi, int pid,
+       const char *func, const char *file, int line)
+{
+       if (vx_info_flags(vxi, VXF_INFO_INIT, 0)) {
+               vxfprintk(VXD_CBIT(cvirt, 2),
+                       "vx_map_tgid: %p/%llx: %d -> %d",
+                       vxi, (long long)vxi->vx_flags, pid,
+                       (pid && pid == vxi->vx_initpid)?1:pid,
+                       func, file, line);
+               if (pid == 0)
+                       return 0;
+               if (pid == vxi->vx_initpid)
+                       return 1;
+       }
+       return pid;
+}
+
+#define vx_info_rmap_pid(v,p) \
+       __vx_info_rmap_pid((v), (p), __FUNC__, __FILE__, __LINE__)
+#define vx_rmap_pid(p) vx_info_rmap_pid(current->vx_info, p)
+#define vx_rmap_tgid(p) vx_rmap_pid(p)
+
+static inline int __vx_info_rmap_pid(struct vx_info *vxi, int pid,
+       const char *func, const char *file, int line)
+{
+       if (vx_info_flags(vxi, VXF_INFO_INIT, 0)) {
+               vxfprintk(VXD_CBIT(cvirt, 2),
+                       "vx_rmap_tgid: %p/%llx: %d -> %d",
+                       vxi, (long long)vxi->vx_flags, pid,
+                       (pid == 1)?vxi->vx_initpid:pid,
+                       func, file, line);
+               if ((pid == 1) && vxi->vx_initpid)
+                       return vxi->vx_initpid;
+               if (pid == vxi->vx_initpid)
+                       return ~0U;
+       }
+       return pid;
+}
+
+
+static inline void vx_activate_task(struct task_struct *p)
+{
+       struct vx_info *vxi;
+
+       if ((vxi = p->vx_info)) {
+               vx_update_load(vxi);
+               atomic_inc(&vxi->cvirt.nr_running);
+       }
+}
+
+static inline void vx_deactivate_task(struct task_struct *p)
+{
+       struct vx_info *vxi;
+
+       if ((vxi = p->vx_info)) {
+               vx_update_load(vxi);
+               atomic_dec(&vxi->cvirt.nr_running);
+       }
+}
+
+static inline void vx_uninterruptible_inc(struct task_struct *p)
+{
+       struct vx_info *vxi;
+
+       if ((vxi = p->vx_info))
+               atomic_inc(&vxi->cvirt.nr_uninterruptible);
+}
+
+static inline void vx_uninterruptible_dec(struct task_struct *p)
+{
+       struct vx_info *vxi;
+
+       if ((vxi = p->vx_info))
+               atomic_dec(&vxi->cvirt.nr_uninterruptible);
+}
+
+
+struct inode;
+
+#define VXF_FAKE_INIT  (VXF_INFO_INIT|VXF_STATE_INIT)
+
+static inline
+int proc_pid_visible(struct task_struct *task, int pid)
+{
+       if ((pid == 1) &&
+               !vx_flags(VXF_FAKE_INIT, VXF_FAKE_INIT))
+               /* show a blend through init */
+               goto visible;
+       if (vx_check(vx_task_xid(task), VX_WATCH|VX_IDENT))
+               goto visible;
+       return 0;
+visible:
+       return 1;
+}
+
+static inline
+struct task_struct *find_proc_task_by_pid(int pid)
+{
+       struct task_struct *task = find_task_by_pid(pid);
+
+       if (task && !proc_pid_visible(task, pid)) {
+               vxdprintk(VXD_CBIT(misc, 6),
+                       "dropping task %p[#%u,%u] for %p[#%u,%u]",
+                       task, task->xid, task->pid,
+                       current, current->xid, current->pid);
+               task = NULL;
+       }
+       return task;
+}
+
+static inline
+struct task_struct *vx_get_proc_task(struct inode *inode, struct pid *pid)
+{
+       struct task_struct *task = get_pid_task(pid, PIDTYPE_PID);
+
+       if (task && !proc_pid_visible(task, pid->nr)) {
+               vxdprintk(VXD_CBIT(misc, 6),
+                       "dropping task %p[#%u,%u] for %p[#%u,%u]",
+                       task, task->xid, task->pid,
+                       current, current->xid, current->pid);
+               put_task_struct(task);
+               task = NULL;
+       }
+       return task;
+}
+
+#else
+#warning duplicate inclusion
+#endif
diff --git a/include/linux/xenfb.h b/include/linux/xenfb.h
new file mode 100644 (file)
index 0000000..3653c57
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * linux/include/linux/xenfb.h -- Xen virtual frame buffer device
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef _LINUX_XENFB_H
+#define _LINUX_XENFB_H
+
+#include <asm/types.h>
+
+/* out events */
+
+#define XENFB_OUT_EVENT_SIZE 40
+
+#define XENFB_TYPE_MOTION 1
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_motion        /* currently unused */
+{
+       __u8 type;          /* XENFB_TYPE_MOTION */
+       __u16 x;            /* The new x coordinate */
+       __u16 y;            /* The new y coordinate */
+};
+
+struct xenfb_update
+{
+       __u8 type;          /* XENFB_TYPE_UPDATE */
+       __u16 x;            /* source x */
+       __u16 y;            /* source y */
+       __u16 width;        /* rect width */
+       __u16 height;       /* rect height */
+};
+
+union xenfb_out_event
+{
+       __u8 type;
+       struct xenfb_motion motion;
+       struct xenfb_update update;
+       char _[XENFB_OUT_EVENT_SIZE];
+};
+
+/* in events */
+
+#define XENFB_IN_EVENT_SIZE 40
+
+#define XENFB_TYPE_SET_EVENTS 1
+
+#define XENFB_FLAG_MOTION 1
+#define XENFB_FLAG_UPDATE 2
+#define XENFB_FLAG_COPY 4
+#define XENFB_FLAG_FILL 8
+
+struct xenfb_set_events
+{
+       __u8 type;          /* XENFB_TYPE_SET_EVENTS */
+       __u32 flags;        /* combination of XENFB_FLAG_* */
+};
+
+union xenfb_in_event
+{
+       __u8 type;
+       struct xenfb_set_events set_events;
+       char _[XENFB_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE 1024
+#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+#define XENFB_IN_RING_OFFS 1024
+#define XENFB_IN_RING(page) \
+    ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+#define XENFB_IN_RING_REF(page, idx) \
+    (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+
+#define XENFB_OUT_RING_SIZE 2048
+#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+#define XENFB_OUT_RING(page) \
+    ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+#define XENFB_OUT_RING_REF(page, idx) \
+    (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+
+struct xenfb_page
+{
+       __u16 width;         /* the width of the framebuffer (in pixels) */
+       __u16 height;        /* the height of the framebuffer (in pixels) */
+       __u32 line_length;   /* the length of a row of pixels (in bytes) */
+       __u32 mem_length;    /* the length of the framebuffer (in bytes) */
+       __u8 depth;          /* the depth of a pixel (in bits) */
+
+       unsigned long pd[2];    /* FIXME rename to pgdir? */
+       /* FIXME pd[1] unused at this time, shrink? */
+
+       __u32 in_cons, in_prod;
+       __u32 out_cons, out_prod;
+};
+
+void xenfb_resume(void);
+
+#endif
diff --git a/include/linux/xenkbd.h b/include/linux/xenkbd.h
new file mode 100644 (file)
index 0000000..c023c12
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * linux/include/linux/xenkbd.h -- Xen virtual keyboard/mouse
+ *
+ * Copyright (C) 2005
+ *
+ *      Anthony Liguori <aliguori@us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef _LINUX_XENKBD_H
+#define _LINUX_XENKBD_H
+
+#include <asm/types.h>
+
+/* in events */
+
+#define XENKBD_IN_EVENT_SIZE 40
+
+#define XENKBD_TYPE_MOTION  1     /* mouse movement event */
+#define XENKBD_TYPE_BUTTON  2     /* mouse button event */
+#define XENKBD_TYPE_KEY     3     /* keyboard event */
+
+struct xenkbd_motion
+{
+       __u8 type;         /* XENKBD_TYPE_MOTION */
+       __s16 rel_x;       /* relative X motion */
+       __s16 rel_y;       /* relative Y motion */
+};
+
+struct xenkbd_button
+{
+       __u8 type;         /* XENKBD_TYPE_BUTTON */
+       __u8 pressed;      /* 1 if pressed; 0 otherwise */
+       __u8 button;       /* the button (0, 1, 2 is right, middle, left) */
+};
+
+struct xenkbd_key
+{
+       __u8 type;         /* XENKBD_TYPE_KEY */
+       __u8 pressed;      /* 1 if pressed; 0 otherwise */
+       __u16 keycode;     /* KEY_* from linux/input.h */
+};
+
+union xenkbd_in_event
+{
+       __u8 type;
+       struct xenkbd_motion motion;
+       struct xenkbd_button button;
+       struct xenkbd_key key;
+       char _[XENKBD_IN_EVENT_SIZE];
+};
+
+/* out events */
+
+#define XENKBD_OUT_EVENT_SIZE 40
+
+union xenkbd_out_event
+{
+       __u8 type;
+       char _[XENKBD_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENKBD_IN_RING_SIZE 2048
+#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+#define XENKBD_IN_RING_OFFS 1024
+#define XENKBD_IN_RING(page) \
+    ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+#define XENKBD_IN_RING_REF(page, idx) \
+    (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+
+#define XENKBD_OUT_RING_SIZE 1024
+#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+#define XENKBD_OUT_RING(page) \
+    ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+#define XENKBD_OUT_RING_REF(page, idx) \
+    (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+
+struct xenkbd_info
+{
+       __u32 in_cons, in_prod;
+       __u32 out_cons, out_prod;
+};
+
+void xenkbd_resume(void);
+
+#endif
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
new file mode 100644 (file)
index 0000000..d91d88f
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+    cx23415/6 header containing common defines.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU 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 CX2341X_H
+#define CX2341X_H
+
+enum cx2341x_port {
+       CX2341X_PORT_MEMORY    = 0,
+       CX2341X_PORT_STREAMING = 1,
+       CX2341X_PORT_SERIAL    = 2
+};
+
+enum cx2341x_cap {
+       CX2341X_CAP_HAS_SLICED_VBI = 1 << 0,
+};
+
+struct cx2341x_mpeg_params {
+       /* misc */
+       u32 capabilities;
+       enum cx2341x_port port;
+       u16 width;
+       u16 height;
+       u16 is_50hz;
+
+       /* stream */
+       enum v4l2_mpeg_stream_type stream_type;
+       enum v4l2_mpeg_stream_vbi_fmt stream_vbi_fmt;
+
+       /* audio */
+       enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq;
+       enum v4l2_mpeg_audio_encoding audio_encoding;
+       enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate;
+       enum v4l2_mpeg_audio_mode audio_mode;
+       enum v4l2_mpeg_audio_mode_extension audio_mode_extension;
+       enum v4l2_mpeg_audio_emphasis audio_emphasis;
+       enum v4l2_mpeg_audio_crc audio_crc;
+       u8 audio_properties;
+
+       /* video */
+       enum v4l2_mpeg_video_encoding video_encoding;
+       enum v4l2_mpeg_video_aspect video_aspect;
+       u16 video_b_frames;
+       u16 video_gop_size;
+       u16 video_gop_closure;
+       u16 video_pulldown;
+       enum v4l2_mpeg_video_bitrate_mode video_bitrate_mode;
+       u32 video_bitrate;
+       u32 video_bitrate_peak;
+       u16 video_temporal_decimation;
+
+       /* encoding filters */
+       enum v4l2_mpeg_cx2341x_video_spatial_filter_mode video_spatial_filter_mode;
+       u16 video_spatial_filter;
+       enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type video_luma_spatial_filter_type;
+       enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type video_chroma_spatial_filter_type;
+       enum v4l2_mpeg_cx2341x_video_temporal_filter_mode video_temporal_filter_mode;
+       u16 video_temporal_filter;
+       enum v4l2_mpeg_cx2341x_video_median_filter_type video_median_filter_type;
+       u16 video_luma_median_filter_top;
+       u16 video_luma_median_filter_bottom;
+       u16 video_chroma_median_filter_top;
+       u16 video_chroma_median_filter_bottom;
+};
+
+#define CX2341X_MBOX_MAX_DATA 16
+
+extern const u32 cx2341x_mpeg_ctrls[];
+typedef int (*cx2341x_mbox_func)(void *priv, int cmd, int in, int out,
+               u32 data[CX2341X_MBOX_MAX_DATA]);
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+               const struct cx2341x_mpeg_params *old,
+               const struct cx2341x_mpeg_params *new);
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
+               struct v4l2_queryctrl *qctrl);
+const char **cx2341x_ctrl_get_menu(u32 id);
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+               struct v4l2_ext_controls *ctrls, unsigned int cmd);
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p);
+void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix);
+
+/* Firmware names */
+#define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw"
+/* Decoder firmware for the cx23415 only */
+#define CX2341X_FIRM_DEC_FILENAME "v4l-cx2341x-dec.fw"
+
+/* Firmware API commands */
+
+/* MPEG decoder API, specific to the cx23415 */
+#define CX2341X_DEC_PING_FW                    0x00
+#define CX2341X_DEC_START_PLAYBACK             0x01
+#define CX2341X_DEC_STOP_PLAYBACK              0x02
+#define CX2341X_DEC_SET_PLAYBACK_SPEED                 0x03
+#define CX2341X_DEC_STEP_VIDEO                         0x05
+#define CX2341X_DEC_SET_DMA_BLOCK_SIZE                 0x08
+#define CX2341X_DEC_GET_XFER_INFO              0x09
+#define CX2341X_DEC_GET_DMA_STATUS             0x0a
+#define CX2341X_DEC_SCHED_DMA_FROM_HOST                0x0b
+#define CX2341X_DEC_PAUSE_PLAYBACK             0x0d
+#define CX2341X_DEC_HALT_FW                    0x0e
+#define CX2341X_DEC_SET_STANDARD               0x10
+#define CX2341X_DEC_GET_VERSION                        0x11
+#define CX2341X_DEC_SET_STREAM_INPUT           0x14
+#define CX2341X_DEC_GET_TIMING_INFO            0x15
+#define CX2341X_DEC_SET_AUDIO_MODE             0x16
+#define CX2341X_DEC_SET_EVENT_NOTIFICATION     0x17
+#define CX2341X_DEC_SET_DISPLAY_BUFFERS                0x18
+#define CX2341X_DEC_EXTRACT_VBI                0x19
+#define CX2341X_DEC_SET_DECODER_SOURCE                 0x1a
+#define CX2341X_DEC_SET_AUDIO_OUTPUT           0x1b
+#define CX2341X_DEC_SET_AV_DELAY               0x1c
+#define CX2341X_DEC_SET_PREBUFFERING           0x1e
+
+/* MPEG encoder API */
+#define CX2341X_ENC_PING_FW                    0x80
+#define CX2341X_ENC_START_CAPTURE              0x81
+#define CX2341X_ENC_STOP_CAPTURE               0x82
+#define CX2341X_ENC_SET_AUDIO_ID               0x89
+#define CX2341X_ENC_SET_VIDEO_ID               0x8b
+#define CX2341X_ENC_SET_PCR_ID                         0x8d
+#define CX2341X_ENC_SET_FRAME_RATE             0x8f
+#define CX2341X_ENC_SET_FRAME_SIZE             0x91
+#define CX2341X_ENC_SET_BIT_RATE               0x95
+#define CX2341X_ENC_SET_GOP_PROPERTIES                 0x97
+#define CX2341X_ENC_SET_ASPECT_RATIO           0x99
+#define CX2341X_ENC_SET_DNR_FILTER_MODE        0x9b
+#define CX2341X_ENC_SET_DNR_FILTER_PROPS       0x9d
+#define CX2341X_ENC_SET_CORING_LEVELS          0x9f
+#define CX2341X_ENC_SET_SPATIAL_FILTER_TYPE    0xa1
+#define CX2341X_ENC_SET_3_2_PULLDOWN           0xb1
+#define CX2341X_ENC_SET_VBI_LINE               0xb7
+#define CX2341X_ENC_SET_STREAM_TYPE            0xb9
+#define CX2341X_ENC_SET_OUTPUT_PORT            0xbb
+#define CX2341X_ENC_SET_AUDIO_PROPERTIES       0xbd
+#define CX2341X_ENC_HALT_FW                    0xc3
+#define CX2341X_ENC_GET_VERSION                        0xc4
+#define CX2341X_ENC_SET_GOP_CLOSURE            0xc5
+#define CX2341X_ENC_GET_SEQ_END                0xc6
+#define CX2341X_ENC_SET_PGM_INDEX_INFO                 0xc7
+#define CX2341X_ENC_SET_VBI_CONFIG             0xc8
+#define CX2341X_ENC_SET_DMA_BLOCK_SIZE                 0xc9
+#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_10    0xca
+#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_9     0xcb
+#define CX2341X_ENC_SCHED_DMA_TO_HOST          0xcc
+#define CX2341X_ENC_INITIALIZE_INPUT           0xcd
+#define CX2341X_ENC_SET_FRAME_DROP_RATE        0xd0
+#define CX2341X_ENC_PAUSE_ENCODER              0xd2
+#define CX2341X_ENC_REFRESH_INPUT              0xd3
+#define CX2341X_ENC_SET_COPYRIGHT              0xd4
+#define CX2341X_ENC_SET_EVENT_NOTIFICATION     0xd5
+#define CX2341X_ENC_SET_NUM_VSYNC_LINES        0xd6
+#define CX2341X_ENC_SET_PLACEHOLDER            0xd7
+#define CX2341X_ENC_MUTE_VIDEO                         0xd9
+#define CX2341X_ENC_MUTE_AUDIO                         0xda
+#define CX2341X_ENC_UNKNOWN                    0xdb
+#define CX2341X_ENC_MISC                       0xdc
+
+/* OSD API, specific to the cx23415 */
+#define CX2341X_OSD_GET_FRAMEBUFFER            0x41
+#define CX2341X_OSD_GET_PIXEL_FORMAT           0x42
+#define CX2341X_OSD_SET_PIXEL_FORMAT           0x43
+#define CX2341X_OSD_GET_STATE                  0x44
+#define CX2341X_OSD_SET_STATE                  0x45
+#define CX2341X_OSD_GET_OSD_COORDS             0x46
+#define CX2341X_OSD_SET_OSD_COORDS             0x47
+#define CX2341X_OSD_GET_SCREEN_COORDS          0x48
+#define CX2341X_OSD_SET_SCREEN_COORDS          0x49
+#define CX2341X_OSD_GET_GLOBAL_ALPHA           0x4a
+#define CX2341X_OSD_SET_GLOBAL_ALPHA           0x4b
+#define CX2341X_OSD_SET_BLEND_COORDS           0x4c
+#define CX2341X_OSD_GET_FLICKER_STATE          0x4f
+#define CX2341X_OSD_SET_FLICKER_STATE          0x50
+#define CX2341X_OSD_BLT_COPY                   0x52
+#define CX2341X_OSD_BLT_FILL                   0x53
+#define CX2341X_OSD_BLT_TEXT                   0x54
+#define CX2341X_OSD_SET_FRAMEBUFFER_WINDOW     0x56
+#define CX2341X_OSD_SET_CHROMA_KEY             0x60
+#define CX2341X_OSD_GET_ALPHA_CONTENT_INDEX    0x61
+#define CX2341X_OSD_SET_ALPHA_CONTENT_INDEX    0x62
+
+#endif /* CX2341X_H */
diff --git a/include/media/pwc-ioctl.h b/include/media/pwc-ioctl.h
new file mode 100644 (file)
index 0000000..adc1254
--- /dev/null
@@ -0,0 +1,325 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 10.0.10
+   It contains structures and defines to communicate from user space
+   directly to the driver.
+ */
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for
+                         changing white balance and red/blue gains
+   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
+              PWCX easier
+   2006/01/01  Luc Saillard Add raw format definition
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API.
+
+   The #define names are built up like follows:
+   VIDIOC              VIDeo IOCtl prefix
+        PWC            Philps WebCam
+           G           optional: Get
+           S           optional: Set
+            ...        the function
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF      0x00
+#define PSZ_QSIF       0x01
+#define PSZ_QCIF       0x02
+#define PSZ_SIF                0x03
+#define PSZ_CIF                0x04
+#define PSZ_VGA                0x05
+#define PSZ_MAX                6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   This value can also be passing using the private flag when using v4l2 and
+   VIDIOC_S_FMT ioctl.
+
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour
+   balance controls.
+ */
+#define PWC_FPS_SHIFT          16
+#define PWC_FPS_MASK           0x00FF0000
+#define PWC_FPS_FRMASK         0x003F0000
+#define PWC_FPS_SNAPSHOT       0x00400000
+#define PWC_QLT_MASK           0x03000000
+#define PWC_QLT_SHIFT          24
+
+
+/* structure for transferring x & y coordinates */
+struct pwc_coord
+{
+       int x, y;               /* guess what */
+       int size;               /* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+       char name[32];
+       int type;
+};
+
+struct pwc_serial
+{
+       char serial[30];        /* String with serial number. Contains terminating 0 */
+};
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR          0
+#define PWC_WB_OUTDOOR         1
+#define PWC_WB_FL              2
+#define PWC_WB_MANUAL          3
+#define PWC_WB_AUTO            4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside
+   the camera; range 0..65535
+   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+   otherwise undefined.
+   'read_red' and 'read_blue' are read-only.
+*/
+struct pwc_whitebalance
+{
+       int mode;
+       int manual_red, manual_blue;    /* R/W */
+       int read_red, read_blue;        /* R/O */
+};
+
+/*
+   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+   and tell the camera how fast it should react to changes in lighting, and
+   with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+       int control_speed;
+       int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+       int led_on;                     /* Led on-time; range = 0..25000 */
+       int led_off;                    /* Led off-time; range = 0..25000  */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+       int width;
+       int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN            0x01
+#define PWC_MPT_TILT           0x02
+#define PWC_MPT_TIMEOUT                0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */
+struct pwc_mpt_angles
+{
+       int absolute;           /* write-only */
+       int pan;                /* degrees * 100 */
+       int tilt;               /* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+       int pan_min, pan_max;           /* degrees * 100 */
+       int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+       int status;
+       int time_pan;
+       int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+   all the necessary information to initialize and use the decompressor
+   routines in standalone applications.
+ */
+struct pwc_video_command
+{
+       int type;               /* camera type (645, 675, 730, etc.) */
+       int release;            /* release number */
+
+       int size;               /* one of PSZ_* */
+       int alternate;
+       int command_len;        /* length of USB video command */
+       unsigned char command_buf[13];  /* Actual USB video command */
+       int bandlength;         /* >0 = compressed */
+       int frame_size;         /* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR       0x0001
+#define PWCX_FLAG_BAYER                0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER         _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER         _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY       _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL                _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL                _IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL       _IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+    becomes difficult to include all the names in programs that want to
+    check for the enhanced Philips stuff. So in stead, try this PROBE;
+    it returns a structure with the original name, and the corresponding
+    Philips type.
+    To use, fill the structure with zeroes, call PROBE and if that succeeds,
+    compare the name with that returned from VIDIOCGCAP; they should be the
+    same. If so, you can be assured it is a Philips (OEM) cam and the type
+    is valid.
+ */
+#define VIDIOCPWCPROBE         _IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC          _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC          _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER      _IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED     _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED     _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR      _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR      _IOR('v', 206, int)
+
+  /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT    _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT    _IOR('v', 207, int)
+
+  /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER      _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER      _IOR('v', 208, int)
+
+  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE     _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE     _IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE     _IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */
+#define VIDIOCPWCMPTRESET      _IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE     _IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE     _IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE     _IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS     _IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD       _IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+   int len;
+   char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE     _IOR('v', 216, struct pwc_table_init_buffer)
+
+/*
+ * This is private command used when communicating with v4l2.
+ * In the future all private ioctl will be remove/replace to
+ * use interface offer by v4l2.
+ */
+
+#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
+
+struct pwc_raw_frame {
+   __le16 type;                /* type of the webcam */
+   __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
+   __u8   cmd[4];      /* the four byte of the command (in case of nala,
+                          only the first 3 bytes is filled) */
+   __u8   rawframe[0]; /* frame_size = H/4*vbandlength */
+} __attribute__ ((packed));
+
+
+#endif
diff --git a/include/media/tvp5150.h b/include/media/tvp5150.h
new file mode 100644 (file)
index 0000000..72bd2a2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+    tvp5150.h - definition for tvp5150 inputs
+
+    Copyright (C) 2006 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 as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU 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 _TVP5150_H_
+#define _TVP5150_H_
+
+/* TVP5150 HW inputs */
+#define TVP5150_COMPOSITE0 0
+#define TVP5150_COMPOSITE1 1
+#define TVP5150_SVIDEO     2
+
+/* TVP5150 HW outputs */
+#define TVP5150_NORMAL       0
+#define TVP5150_BLACK_SCREEN 1
+
+#endif
+
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
new file mode 100644 (file)
index 0000000..810462f
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ *
+ *     V 4 L 2   D R I V E R   H E L P E R   A P I
+ *
+ * Moved from videodev2.h
+ *
+ *     Some commonly needed functions for drivers (v4l2-common.o module)
+ */
+#ifndef _V4L2_DEV_H
+#define _V4L2_DEV_H
+
+#define OBSOLETE_OWNER 1 /* to be removed soon */
+
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/compiler.h> /* need __user */
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+#include <linux/videodev.h>
+#else
+#include <linux/videodev2.h>
+#endif
+
+#include <linux/fs.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
+
+/*  Video standard functions  */
+extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
+extern int v4l2_video_std_construct(struct v4l2_standard *vs,
+                                   int id, char *name);
+
+/* prority handling */
+struct v4l2_prio_state {
+       atomic_t prios[4];
+};
+int v4l2_prio_init(struct v4l2_prio_state *global);
+int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
+                    enum v4l2_priority new);
+int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
+int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
+enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
+int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
+
+/* names for fancy debug output */
+extern char *v4l2_field_names[];
+extern char *v4l2_type_names[];
+
+/*  Compatibility layer interface  --  v4l1-compat module */
+typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
+                          unsigned int cmd, void *arg);
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
+                              int cmd, void *arg, v4l2_kioctl driver_ioctl);
+#else
+#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
+#endif
+
+/* 32 Bits compatibility layer for 64 bits processors */
+extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
+                               unsigned long arg);
+
+/*
+ * Newer version of video_device, handled by videodev2.c
+ *     This version moves redundant code from video device code to
+ *     the common handler
+ */
+struct v4l2_tvnorm {
+       char          *name;
+       v4l2_std_id   id;
+
+       void          *priv_data;
+};
+
+struct video_device
+{
+       /* device ops */
+       const struct file_operations *fops;
+
+       /* device info */
+       struct device *dev;
+       char name[32];
+       int type;       /* v4l1 */
+       int type2;      /* v4l2 */
+       int hardware;
+       int minor;
+
+       int debug;      /* Activates debug level*/
+
+       /* Video standard vars */
+       int tvnormsize; /* Size of tvnorm array */
+       v4l2_std_id current_norm; /* Current tvnorm */
+       struct v4l2_tvnorm *tvnorms;
+
+       /* callbacks */
+       void (*release)(struct video_device *vfd);
+
+       /* ioctl callbacks */
+
+       /* VIDIOC_QUERYCAP handler */
+       int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
+
+       /* Priority handling */
+       int (*vidioc_g_priority)   (struct file *file, void *fh,
+                                   enum v4l2_priority *p);
+       int (*vidioc_s_priority)   (struct file *file, void *fh,
+                                   enum v4l2_priority p);
+
+       /* VIDIOC_ENUM_FMT handlers */
+       int (*vidioc_enum_fmt_cap)         (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_overlay)     (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vbi)         (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vbi_capture) (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_video_output)(struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vbi_output)  (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+
+       /* VIDIOC_G_FMT handlers */
+       int (*vidioc_g_fmt_cap)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_overlay)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi_output) (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi_capture)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_video_output)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       /* VIDIOC_S_FMT handlers */
+       int (*vidioc_s_fmt_cap)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       int (*vidioc_s_fmt_overlay)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi_output) (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi_capture)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_video_output)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       /* VIDIOC_TRY_FMT handlers */
+       int (*vidioc_try_fmt_cap)        (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_overlay)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi)        (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi_output) (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi_capture)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_video_output)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+
+       /* Buffer handlers */
+       int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
+       int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
+
+
+       int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+                       /* buffer type is struct vidio_mbuf * */
+       int (*vidiocgmbuf)  (struct file *file, void *fh, struct video_mbuf *p);
+#endif
+       int (*vidioc_g_fbuf)   (struct file *file, void *fh,
+                               struct v4l2_framebuffer *a);
+       int (*vidioc_s_fbuf)   (struct file *file, void *fh,
+                               struct v4l2_framebuffer *a);
+
+               /* Stream on/off */
+       int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
+       int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
+
+               /* Standard handling
+                       G_STD and ENUMSTD are handled by videodev.c
+                */
+       int (*vidioc_s_std)    (struct file *file, void *fh, v4l2_std_id a);
+       int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
+
+               /* Input handling */
+       int (*vidioc_enum_input)(struct file *file, void *fh,
+                                struct v4l2_input *inp);
+       int (*vidioc_g_input)   (struct file *file, void *fh, unsigned int *i);
+       int (*vidioc_s_input)   (struct file *file, void *fh, unsigned int i);
+
+               /* Output handling */
+       int (*vidioc_enumoutput) (struct file *file, void *fh,
+                                 struct v4l2_output *a);
+       int (*vidioc_g_output)   (struct file *file, void *fh, unsigned int *i);
+       int (*vidioc_s_output)   (struct file *file, void *fh, unsigned int i);
+
+               /* Control handling */
+       int (*vidioc_queryctrl)        (struct file *file, void *fh,
+                                       struct v4l2_queryctrl *a);
+       int (*vidioc_g_ctrl)           (struct file *file, void *fh,
+                                       struct v4l2_control *a);
+       int (*vidioc_s_ctrl)           (struct file *file, void *fh,
+                                       struct v4l2_control *a);
+       int (*vidioc_g_ext_ctrls)      (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_s_ext_ctrls)      (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_try_ext_ctrls)    (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_querymenu)        (struct file *file, void *fh,
+                                       struct v4l2_querymenu *a);
+
+       /* Audio ioctls */
+       int (*vidioc_enumaudio)        (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+       int (*vidioc_g_audio)          (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+       int (*vidioc_s_audio)          (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+
+       /* Audio out ioctls */
+       int (*vidioc_enumaudout)       (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_g_audout)         (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_s_audout)         (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_g_modulator)      (struct file *file, void *fh,
+                                       struct v4l2_modulator *a);
+       int (*vidioc_s_modulator)      (struct file *file, void *fh,
+                                       struct v4l2_modulator *a);
+       /* Crop ioctls */
+       int (*vidioc_cropcap)          (struct file *file, void *fh,
+                                       struct v4l2_cropcap *a);
+       int (*vidioc_g_crop)           (struct file *file, void *fh,
+                                       struct v4l2_crop *a);
+       int (*vidioc_s_crop)           (struct file *file, void *fh,
+                                       struct v4l2_crop *a);
+       /* Compression ioctls */
+       int (*vidioc_g_mpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_mpeg_compression *a);
+       int (*vidioc_s_mpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_mpeg_compression *a);
+       int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_jpegcompression *a);
+       int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_jpegcompression *a);
+
+       /* Stream type-dependent parameter ioctls */
+       int (*vidioc_g_parm)           (struct file *file, void *fh,
+                                       struct v4l2_streamparm *a);
+       int (*vidioc_s_parm)           (struct file *file, void *fh,
+                                       struct v4l2_streamparm *a);
+
+       /* Tuner ioctls */
+       int (*vidioc_g_tuner)          (struct file *file, void *fh,
+                                       struct v4l2_tuner *a);
+       int (*vidioc_s_tuner)          (struct file *file, void *fh,
+                                       struct v4l2_tuner *a);
+       int (*vidioc_g_frequency)      (struct file *file, void *fh,
+                                       struct v4l2_frequency *a);
+       int (*vidioc_s_frequency)      (struct file *file, void *fh,
+                                       struct v4l2_frequency *a);
+
+       /* Sliced VBI cap */
+       int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
+                                       struct v4l2_sliced_vbi_cap *a);
+
+       /* Log status ioctl */
+       int (*vidioc_log_status)       (struct file *file, void *fh);
+
+
+#ifdef OBSOLETE_OWNER /* to be removed soon */
+/* obsolete -- fops->owner is used instead */
+struct module *owner;
+/* 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 intenal usage -- please don't touch */
+       int users;                     /* video_exclusive_{open|close} ... */
+       struct mutex lock;             /* ... helper function uses these   */
+       struct class_device class_dev; /* sysfs */
+};
+
+/* Version 2 functions */
+extern int video_register_device(struct video_device *vfd, int type, int nr);
+void video_unregister_device(struct video_device *);
+extern int video_ioctl2(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg);
+
+/* helper functions to alloc / release struct video_device, the
+   later can be used for video_device->release() */
+struct video_device *video_device_alloc(void);
+void video_device_release(struct video_device *vfd);
+
+/* Include support for obsoleted stuff */
+extern int video_usercopy(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg,
+                         int (*func)(struct inode *inode, struct file *file,
+                                     unsigned int cmd, void *arg));
+
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+#include <linux/mm.h>
+
+extern struct video_device* video_devdata(struct file*);
+
+#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
+static inline int
+video_device_create_file(struct video_device *vfd,
+                        struct class_device_attribute *attr)
+{
+       int ret = class_device_create_file(&vfd->class_dev, attr);
+       if (ret < 0)
+               printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret);
+       return ret;
+}
+static inline void
+video_device_remove_file(struct video_device *vfd,
+                        struct class_device_attribute *attr)
+{
+       class_device_remove_file(&vfd->class_dev, attr);
+}
+
+#endif /* CONFIG_VIDEO_V4L1_COMPAT */
+
+#ifdef OBSOLETE_OWNER /* to be removed soon */
+/* helper functions to access driver private data. */
+static inline void *video_get_drvdata(struct video_device *dev)
+{
+       return dev->priv;
+}
+
+static inline void video_set_drvdata(struct video_device *dev, void *data)
+{
+       dev->priv = data;
+}
+#endif
+
+extern int video_exclusive_open(struct inode *inode, struct file *file);
+extern int video_exclusive_release(struct inode *inode, struct file *file);
+
+#endif /* _V4L2_DEV_H */
diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild
new file mode 100644 (file)
index 0000000..13e7a3c
--- /dev/null
@@ -0,0 +1,6 @@
+header-y += inftl-user.h
+header-y += jffs2-user.h
+header-y += mtd-user.h
+header-y += nftl-user.h
+
+unifdef-y += mtd-abi.h
diff --git a/include/net/netdma.h b/include/net/netdma.h
new file mode 100644 (file)
index 0000000..f28c6e0
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef NETDMA_H
+#define NETDMA_H
+#ifdef CONFIG_NET_DMA
+#include <linux/dmaengine.h>
+#include <linux/skbuff.h>
+
+static inline struct dma_chan *get_softnet_dma(void)
+{
+       struct dma_chan *chan;
+       rcu_read_lock();
+       chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma);
+       if (chan)
+               dma_chan_get(chan);
+       rcu_read_unlock();
+       return chan;
+}
+
+int dma_skb_copy_datagram_iovec(struct dma_chan* chan,
+               struct sk_buff *skb, int offset, struct iovec *to,
+               size_t len, struct dma_pinned_list *pinned_list);
+
+#endif /* CONFIG_NET_DMA */
+#endif /* NETDMA_H */
diff --git a/include/net/netevent.h b/include/net/netevent.h
new file mode 100644 (file)
index 0000000..e5d2162
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _NET_EVENT_H
+#define _NET_EVENT_H
+
+/*
+ *     Generic netevent notifiers
+ *
+ *     Authors:
+ *      Tom Tucker              <tom@opengridcomputing.com>
+ *      Steve Wise              <swise@opengridcomputing.com>
+ *
+ *     Changes:
+ */
+#ifdef __KERNEL__
+
+#include <net/dst.h>
+
+struct netevent_redirect {
+       struct dst_entry *old;
+       struct dst_entry *new;
+};
+
+enum netevent_notif_type {
+       NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */
+       NETEVENT_PMTU_UPDATE,      /* arg is struct dst_entry ptr */
+       NETEVENT_REDIRECT,         /* arg is struct netevent_redirect ptr */
+};
+
+extern int register_netevent_notifier(struct notifier_block *nb);
+extern int unregister_netevent_notifier(struct notifier_block *nb);
+extern int call_netevent_notifiers(unsigned long val, void *v);
+
+#endif
+#endif
diff --git a/include/rdma/Kbuild b/include/rdma/Kbuild
new file mode 100644 (file)
index 0000000..e7c0432
--- /dev/null
@@ -0,0 +1 @@
+header-y += ib_user_mad.h
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
new file mode 100644 (file)
index 0000000..0ff6739
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(IB_ADDR_H)
+#define IB_ADDR_H
+
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/netdevice.h>
+#include <linux/socket.h>
+#include <rdma/ib_verbs.h>
+
+struct rdma_dev_addr {
+       unsigned char src_dev_addr[MAX_ADDR_LEN];
+       unsigned char dst_dev_addr[MAX_ADDR_LEN];
+       unsigned char broadcast[MAX_ADDR_LEN];
+       enum ib_node_type dev_type;
+};
+
+/**
+ * rdma_translate_ip - Translate a local IP address to an RDMA hardware
+ *   address.
+ */
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr);
+
+/**
+ * rdma_resolve_ip - Resolve source and destination IP addresses to
+ *   RDMA hardware addresses.
+ * @src_addr: An optional source address to use in the resolution.  If a
+ *   source address is not provided, a usable address will be returned via
+ *   the callback.
+ * @dst_addr: The destination address to resolve.
+ * @addr: A reference to a data location that will receive the resolved
+ *   addresses.  The data location must remain valid until the callback has
+ *   been invoked.
+ * @timeout_ms: Amount of time to wait for the address resolution to complete.
+ * @callback: Call invoked once address resolution has completed, timed out,
+ *   or been canceled.  A status of 0 indicates success.
+ * @context: User-specified context associated with the call.
+ */
+int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+                   struct rdma_dev_addr *addr, int timeout_ms,
+                   void (*callback)(int status, struct sockaddr *src_addr,
+                                    struct rdma_dev_addr *addr, void *context),
+                   void *context);
+
+void rdma_addr_cancel(struct rdma_dev_addr *addr);
+
+static inline int ip_addr_size(struct sockaddr *addr)
+{
+       return addr->sa_family == AF_INET6 ?
+              sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+}
+
+static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)
+{
+       return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];
+}
+
+static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey)
+{
+       dev_addr->broadcast[8] = pkey >> 8;
+       dev_addr->broadcast[9] = (unsigned char) pkey;
+}
+
+static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(gid, dev_addr->src_dev_addr + 4, sizeof *gid);
+}
+
+static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid);
+}
+
+static inline void ib_addr_get_dgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(gid, dev_addr->dst_dev_addr + 4, sizeof *gid);
+}
+
+static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid);
+}
+
+#endif /* IB_ADDR_H */
diff --git a/include/rdma/ib_marshall.h b/include/rdma/ib_marshall.h
new file mode 100644 (file)
index 0000000..66bf4d7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(IB_USER_MARSHALL_H)
+#define IB_USER_MARSHALL_H
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_user_sa.h>
+
+void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+                            struct ib_qp_attr *src);
+
+void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+                             struct ib_sa_path_rec *src);
+
+void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
+                               struct ib_user_path_rec *src);
+
+#endif /* IB_USER_MARSHALL_H */
diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h
new file mode 100644 (file)
index 0000000..6591201
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  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
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_SA_H
+#define IB_USER_SA_H
+
+#include <linux/types.h>
+
+struct ib_user_path_rec {
+       __u8    dgid[16];
+       __u8    sgid[16];
+       __be16  dlid;
+       __be16  slid;
+       __u32   raw_traffic;
+       __be32  flow_label;
+       __u32   reversible;
+       __u32   mtu;
+       __be16  pkey;
+       __u8    hop_limit;
+       __u8    traffic_class;
+       __u8    numb_path;
+       __u8    sl;
+       __u8    mtu_selector;
+       __u8    rate_selector;
+       __u8    rate;
+       __u8    packet_life_time_selector;
+       __u8    packet_life_time;
+       __u8    preference;
+};
+
+#endif /* IB_USER_SA_H */
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
new file mode 100644 (file)
index 0000000..402c63d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(RDMA_CM_H)
+#define RDMA_CM_H
+
+#include <linux/socket.h>
+#include <linux/in6.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_sa.h>
+
+/*
+ * Upon receiving a device removal event, users must destroy the associated
+ * RDMA identifier and release all resources allocated with the device.
+ */
+enum rdma_cm_event_type {
+       RDMA_CM_EVENT_ADDR_RESOLVED,
+       RDMA_CM_EVENT_ADDR_ERROR,
+       RDMA_CM_EVENT_ROUTE_RESOLVED,
+       RDMA_CM_EVENT_ROUTE_ERROR,
+       RDMA_CM_EVENT_CONNECT_REQUEST,
+       RDMA_CM_EVENT_CONNECT_RESPONSE,
+       RDMA_CM_EVENT_CONNECT_ERROR,
+       RDMA_CM_EVENT_UNREACHABLE,
+       RDMA_CM_EVENT_REJECTED,
+       RDMA_CM_EVENT_ESTABLISHED,
+       RDMA_CM_EVENT_DISCONNECTED,
+       RDMA_CM_EVENT_DEVICE_REMOVAL,
+};
+
+enum rdma_port_space {
+       RDMA_PS_SDP  = 0x0001,
+       RDMA_PS_TCP  = 0x0106,
+       RDMA_PS_UDP  = 0x0111,
+       RDMA_PS_SCTP = 0x0183
+};
+
+struct rdma_addr {
+       struct sockaddr src_addr;
+       u8              src_pad[sizeof(struct sockaddr_in6) -
+                               sizeof(struct sockaddr)];
+       struct sockaddr dst_addr;
+       u8              dst_pad[sizeof(struct sockaddr_in6) -
+                               sizeof(struct sockaddr)];
+       struct rdma_dev_addr dev_addr;
+};
+
+struct rdma_route {
+       struct rdma_addr addr;
+       struct ib_sa_path_rec *path_rec;
+       int num_paths;
+};
+
+struct rdma_cm_event {
+       enum rdma_cm_event_type  event;
+       int                      status;
+       void                    *private_data;
+       u8                       private_data_len;
+};
+
+struct rdma_cm_id;
+
+/**
+ * rdma_cm_event_handler - Callback used to report user events.
+ *
+ * Notes: Users may not call rdma_destroy_id from this callback to destroy
+ *   the passed in id, or a corresponding listen id.  Returning a
+ *   non-zero value from the callback will destroy the passed in id.
+ */
+typedef int (*rdma_cm_event_handler)(struct rdma_cm_id *id,
+                                    struct rdma_cm_event *event);
+
+struct rdma_cm_id {
+       struct ib_device        *device;
+       void                    *context;
+       struct ib_qp            *qp;
+       rdma_cm_event_handler    event_handler;
+       struct rdma_route        route;
+       enum rdma_port_space     ps;
+       u8                       port_num;
+};
+
+/**
+ * rdma_create_id - Create an RDMA identifier.
+ *
+ * @event_handler: User callback invoked to report events associated with the
+ *   returned rdma_id.
+ * @context: User specified context associated with the id.
+ * @ps: RDMA port space.
+ */
+struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+                                 void *context, enum rdma_port_space ps);
+
+void rdma_destroy_id(struct rdma_cm_id *id);
+
+/**
+ * rdma_bind_addr - Bind an RDMA identifier to a source address and
+ *   associated RDMA device, if needed.
+ *
+ * @id: RDMA identifier.
+ * @addr: Local address information.  Wildcard values are permitted.
+ *
+ * This associates a source address with the RDMA identifier before calling
+ * rdma_listen.  If a specific local address is given, the RDMA identifier will
+ * be bound to a local RDMA device.
+ */
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);
+
+/**
+ * rdma_resolve_addr - Resolve destination and optional source addresses
+ *   from IP addresses to an RDMA address.  If successful, the specified
+ *   rdma_cm_id will be bound to a local device.
+ *
+ * @id: RDMA identifier.
+ * @src_addr: Source address information.  This parameter may be NULL.
+ * @dst_addr: Destination address information.
+ * @timeout_ms: Time to wait for resolution to complete.
+ */
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+                     struct sockaddr *dst_addr, int timeout_ms);
+
+/**
+ * rdma_resolve_route - Resolve the RDMA address bound to the RDMA identifier
+ *   into route information needed to establish a connection.
+ *
+ * This is called on the client side of a connection.
+ * Users must have first called rdma_resolve_addr to resolve a dst_addr
+ * into an RDMA address before calling this routine.
+ */
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms);
+
+/**
+ * rdma_create_qp - Allocate a QP and associate it with the specified RDMA
+ * identifier.
+ *
+ * QPs allocated to an rdma_cm_id will automatically be transitioned by the CMA
+ * through their states.
+ */
+int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
+                  struct ib_qp_init_attr *qp_init_attr);
+
+/**
+ * rdma_destroy_qp - Deallocate the QP associated with the specified RDMA
+ * identifier.
+ *
+ * Users must destroy any QP associated with an RDMA identifier before
+ * destroying the RDMA ID.
+ */
+void rdma_destroy_qp(struct rdma_cm_id *id);
+
+/**
+ * rdma_init_qp_attr - Initializes the QP attributes for use in transitioning
+ *   to a specified QP state.
+ * @id: Communication identifier associated with the QP attributes to
+ *   initialize.
+ * @qp_attr: On input, specifies the desired QP state.  On output, the
+ *   mandatory and desired optional attributes will be set in order to
+ *   modify the QP to the specified state.
+ * @qp_attr_mask: The QP attribute mask that may be used to transition the
+ *   QP to the specified state.
+ *
+ * Users must set the @qp_attr->qp_state to the desired QP state.  This call
+ * will set all required attributes for the given transition, along with
+ * known optional attributes.  Users may override the attributes returned from
+ * this call before calling ib_modify_qp.
+ *
+ * Users that wish to have their QP automatically transitioned through its
+ * states can associate a QP with the rdma_cm_id by calling rdma_create_qp().
+ */
+int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
+                      int *qp_attr_mask);
+
+struct rdma_conn_param {
+       const void *private_data;
+       u8 private_data_len;
+       u8 responder_resources;
+       u8 initiator_depth;
+       u8 flow_control;
+       u8 retry_count;         /* ignored when accepting */
+       u8 rnr_retry_count;
+       /* Fields below ignored if a QP is created on the rdma_cm_id. */
+       u8 srq;
+       u32 qp_num;
+       enum ib_qp_type qp_type;
+};
+
+/**
+ * rdma_connect - Initiate an active connection request.
+ *
+ * Users must have resolved a route for the rdma_cm_id to connect with
+ * by having called rdma_resolve_route before calling this routine.
+ */
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_listen - This function is called by the passive side to
+ *   listen for incoming connection requests.
+ *
+ * Users must have bound the rdma_cm_id to a local address by calling
+ * rdma_bind_addr before calling this routine.
+ */
+int rdma_listen(struct rdma_cm_id *id, int backlog);
+
+/**
+ * rdma_accept - Called to accept a connection request or response.
+ * @id: Connection identifier associated with the request.
+ * @conn_param: Information needed to establish the connection.  This must be
+ *   provided if accepting a connection request.  If accepting a connection
+ *   response, this parameter must be NULL.
+ *
+ * Typically, this routine is only called by the listener to accept a connection
+ * request.  It must also be called on the active side of a connection if the
+ * user is performing their own QP transitions.
+ */
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_reject - Called to reject a connection request or response.
+ */
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+               u8 private_data_len);
+
+/**
+ * rdma_disconnect - This function disconnects the associated QP and
+ *   transitions it into the error state.
+ */
+int rdma_disconnect(struct rdma_cm_id *id);
+
+#endif /* RDMA_CM_H */
+
diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h
new file mode 100644 (file)
index 0000000..e8c3af1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(RDMA_CM_IB_H)
+#define RDMA_CM_IB_H
+
+#include <rdma/rdma_cm.h>
+
+/**
+ * rdma_set_ib_paths - Manually sets the path records used to establish a
+ *   connection.
+ * @id: Connection identifier associated with the request.
+ * @path_rec: Reference to the path record
+ *
+ * This call permits a user to specify routing information for rdma_cm_id's
+ * bound to Infiniband devices.  It is called on the client side of a
+ * connection and replaces the call to rdma_resolve_route.
+ */
+int rdma_set_ib_paths(struct rdma_cm_id *id,
+                     struct ib_sa_path_rec *path_rec, int num_paths);
+
+#endif /* RDMA_CM_IB_H */
diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild
new file mode 100644 (file)
index 0000000..744f850
--- /dev/null
@@ -0,0 +1,4 @@
+header-y += scsi.h
+
+unifdef-y += scsi_ioctl.h
+unifdef-y += sg.h
diff --git a/include/sound/Kbuild b/include/sound/Kbuild
new file mode 100644 (file)
index 0000000..fd054a3
--- /dev/null
@@ -0,0 +1,10 @@
+header-y += asound_fm.h
+header-y += hdsp.h
+header-y += hdspm.h
+header-y += sfnt_info.h
+header-y += sscape_ioctl.h
+
+unifdef-y += asequencer.h
+unifdef-y += asound.h
+unifdef-y += emu10k1.h
+unifdef-y += sb16_csp.h
diff --git a/include/video/Kbuild b/include/video/Kbuild
new file mode 100644 (file)
index 0000000..a14f9c0
--- /dev/null
@@ -0,0 +1 @@
+unifdef-y += sisfb.h
diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h
new file mode 100644 (file)
index 0000000..3bde0f5
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __MBX_FB_H
+#define __MBX_FB_H
+
+struct mbxfb_val {
+       unsigned int    defval;
+       unsigned int    min;
+       unsigned int    max;
+};
+
+struct fb_info;
+
+struct mbxfb_platform_data {
+               /* Screen info */
+               struct mbxfb_val xres;
+               struct mbxfb_val yres;
+               struct mbxfb_val bpp;
+
+               /* Memory info */
+               unsigned long memsize; /* if 0 use ODFB? */
+               unsigned long timings1;
+               unsigned long timings2;
+               unsigned long timings3;
+
+               int (*probe)(struct fb_info *fb);
+               int (*remove)(struct fb_info *fb);
+};
+
+#endif /* __MBX_FB_H */
diff --git a/include/xen/hvm.h b/include/xen/hvm.h
new file mode 100644 (file)
index 0000000..97bb68a
--- /dev/null
@@ -0,0 +1,24 @@
+/* Simple wrappers around HVM functions */
+#ifndef XEN_HVM_H__
+#define XEN_HVM_H__
+
+#include <xen/interface/hvm/params.h>
+#include <asm/hypercall.h>
+
+static inline unsigned long hvm_get_parameter(int idx)
+{
+       struct xen_hvm_param xhv;
+       int r;
+
+       xhv.domid = DOMID_SELF;
+       xhv.index = idx;
+       r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+       if (r < 0) {
+               printk(KERN_ERR "cannot get hvm parameter %d: %d.\n",
+                      idx, r);
+               return 0;
+       }
+       return xhv.value;
+}
+
+#endif /* XEN_HVM_H__ */
diff --git a/include/xen/interface/arch-ia64.h b/include/xen/interface/arch-ia64.h
new file mode 100644 (file)
index 0000000..98bda1d
--- /dev/null
@@ -0,0 +1,448 @@
+/******************************************************************************
+ * arch-ia64/hypervisor-if.h
+ * 
+ * Guest OS interface to IA64 Xen.
+ */
+
+#ifndef __HYPERVISOR_IF_IA64_H__
+#define __HYPERVISOR_IF_IA64_H__
+
+/* Structural guest handles introduced in 0x00030201. */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+    typedef struct { type *p; } __guest_handle_ ## name
+#else
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+    typedef type * __guest_handle_ ## name
+#endif
+
+#define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define XEN_GUEST_HANDLE(name)          __guest_handle_ ## name
+#define set_xen_guest_handle(hnd, val)  do { (hnd).p = val; } while (0)
+#ifdef __XEN_TOOLS__
+#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
+__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
+__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
+DEFINE_XEN_GUEST_HANDLE(char);
+DEFINE_XEN_GUEST_HANDLE(int);
+DEFINE_XEN_GUEST_HANDLE(long);
+DEFINE_XEN_GUEST_HANDLE(void);
+
+typedef unsigned long xen_pfn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+#endif
+
+/* Arch specific VIRQs definition */
+#define VIRQ_ITC        VIRQ_ARCH_0 /* V. Virtual itc timer */
+
+/* Maximum number of virtual CPUs in multi-processor guests. */
+/* WARNING: before changing this, check that shared_info fits on a page */
+#define MAX_VIRT_CPUS 64
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long xen_ulong_t;
+
+#define GPFN_MEM          (0UL << 56) /* Guest pfn is normal mem */
+#define GPFN_FRAME_BUFFER (1UL << 56) /* VGA framebuffer */
+#define GPFN_LOW_MMIO     (2UL << 56) /* Low MMIO range */
+#define GPFN_PIB          (3UL << 56) /* PIB base */
+#define GPFN_IOSAPIC      (4UL << 56) /* IOSAPIC base */
+#define GPFN_LEGACY_IO    (5UL << 56) /* Legacy I/O base */
+#define GPFN_GFW          (6UL << 56) /* Guest Firmware */
+#define GPFN_HIGH_MMIO    (7UL << 56) /* High MMIO range */
+
+#define GPFN_IO_MASK     (7UL << 56)  /* Guest pfn is I/O type */
+#define GPFN_INV_MASK    (31UL << 59) /* Guest pfn is invalid */
+
+#define INVALID_MFN       (~0UL)
+
+#define MEM_G   (1UL << 30)
+#define MEM_M   (1UL << 20)
+
+#define MMIO_START       (3 * MEM_G)
+#define MMIO_SIZE        (512 * MEM_M)
+
+#define VGA_IO_START     0xA0000UL
+#define VGA_IO_SIZE      0x20000
+
+#define LEGACY_IO_START  (MMIO_START + MMIO_SIZE)
+#define LEGACY_IO_SIZE   (64*MEM_M)
+
+#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
+#define IO_PAGE_SIZE  PAGE_SIZE
+
+#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
+#define STORE_PAGE_SIZE         PAGE_SIZE
+
+#define IO_SAPIC_START   0xfec00000UL
+#define IO_SAPIC_SIZE    0x100000
+
+#define PIB_START 0xfee00000UL
+#define PIB_SIZE 0x200000
+
+#define GFW_START        (4*MEM_G -16*MEM_M)
+#define GFW_SIZE         (16*MEM_M)
+
+struct pt_fpreg {
+    union {
+        unsigned long bits[2];
+        long double __dummy;    /* force 16-byte alignment */
+    } u;
+};
+
+struct cpu_user_regs {
+    /* The following registers are saved by SAVE_MIN: */
+    unsigned long b6;  /* scratch */
+    unsigned long b7;  /* scratch */
+
+    unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
+    unsigned long ar_ssd; /* reserved for future use (scratch) */
+
+    unsigned long r8;  /* scratch (return value register 0) */
+    unsigned long r9;  /* scratch (return value register 1) */
+    unsigned long r10; /* scratch (return value register 2) */
+    unsigned long r11; /* scratch (return value register 3) */
+
+    unsigned long cr_ipsr; /* interrupted task's psr */
+    unsigned long cr_iip;  /* interrupted task's instruction pointer */
+    unsigned long cr_ifs;  /* interrupted task's function state */
+
+    unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
+    unsigned long ar_pfs;  /* prev function state  */
+    unsigned long ar_rsc;  /* RSE configuration */
+    /* The following two are valid only if cr_ipsr.cpl > 0: */
+    unsigned long ar_rnat;  /* RSE NaT */
+    unsigned long ar_bspstore; /* RSE bspstore */
+
+    unsigned long pr;  /* 64 predicate registers (1 bit each) */
+    unsigned long b0;  /* return pointer (bp) */
+    unsigned long loadrs;  /* size of dirty partition << 16 */
+
+    unsigned long r1;  /* the gp pointer */
+    unsigned long r12; /* interrupted task's memory stack pointer */
+    unsigned long r13; /* thread pointer */
+
+    unsigned long ar_fpsr;  /* floating point status (preserved) */
+    unsigned long r15;  /* scratch */
+
+ /* The remaining registers are NOT saved for system calls.  */
+
+    unsigned long r14;  /* scratch */
+    unsigned long r2;  /* scratch */
+    unsigned long r3;  /* scratch */
+    unsigned long r16;  /* scratch */
+    unsigned long r17;  /* scratch */
+    unsigned long r18;  /* scratch */
+    unsigned long r19;  /* scratch */
+    unsigned long r20;  /* scratch */
+    unsigned long r21;  /* scratch */
+    unsigned long r22;  /* scratch */
+    unsigned long r23;  /* scratch */
+    unsigned long r24;  /* scratch */
+    unsigned long r25;  /* scratch */
+    unsigned long r26;  /* scratch */
+    unsigned long r27;  /* scratch */
+    unsigned long r28;  /* scratch */
+    unsigned long r29;  /* scratch */
+    unsigned long r30;  /* scratch */
+    unsigned long r31;  /* scratch */
+    unsigned long ar_ccv;  /* compare/exchange value (scratch) */
+
+    /*
+     * Floating point registers that the kernel considers scratch:
+     */
+    struct pt_fpreg f6;  /* scratch */
+    struct pt_fpreg f7;  /* scratch */
+    struct pt_fpreg f8;  /* scratch */
+    struct pt_fpreg f9;  /* scratch */
+    struct pt_fpreg f10;  /* scratch */
+    struct pt_fpreg f11;  /* scratch */
+    unsigned long r4;  /* preserved */
+    unsigned long r5;  /* preserved */
+    unsigned long r6;  /* preserved */
+    unsigned long r7;  /* preserved */
+    unsigned long eml_unat;    /* used for emulating instruction */
+    unsigned long pad0;     /* alignment pad */
+
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+
+union vac {
+    unsigned long value;
+    struct {
+        int a_int:1;
+        int a_from_int_cr:1;
+        int a_to_int_cr:1;
+        int a_from_psr:1;
+        int a_from_cpuid:1;
+        int a_cover:1;
+        int a_bsw:1;
+        long reserved:57;
+    };
+};
+typedef union vac vac_t;
+
+union vdc {
+    unsigned long value;
+    struct {
+        int d_vmsw:1;
+        int d_extint:1;
+        int d_ibr_dbr:1;
+        int d_pmc:1;
+        int d_to_pmd:1;
+        int d_itm:1;
+        long reserved:58;
+    };
+};
+typedef union vdc vdc_t;
+
+struct mapped_regs {
+    union vac   vac;
+    union vdc   vdc;
+    unsigned long  virt_env_vaddr;
+    unsigned long  reserved1[29];
+    unsigned long  vhpi;
+    unsigned long  reserved2[95];
+    union {
+        unsigned long  vgr[16];
+        unsigned long bank1_regs[16]; // bank1 regs (r16-r31) when bank0 active
+    };
+    union {
+        unsigned long  vbgr[16];
+        unsigned long bank0_regs[16]; // bank0 regs (r16-r31) when bank1 active
+    };
+    unsigned long  vnat;
+    unsigned long  vbnat;
+    unsigned long  vcpuid[5];
+    unsigned long  reserved3[11];
+    unsigned long  vpsr;
+    unsigned long  vpr;
+    unsigned long  reserved4[76];
+    union {
+        unsigned long  vcr[128];
+        struct {
+            unsigned long dcr;  // CR0
+            unsigned long itm;
+            unsigned long iva;
+            unsigned long rsv1[5];
+            unsigned long pta;  // CR8
+            unsigned long rsv2[7];
+            unsigned long ipsr;  // CR16
+            unsigned long isr;
+            unsigned long rsv3;
+            unsigned long iip;
+            unsigned long ifa;
+            unsigned long itir;
+            unsigned long iipa;
+            unsigned long ifs;
+            unsigned long iim;  // CR24
+            unsigned long iha;
+            unsigned long rsv4[38];
+            unsigned long lid;  // CR64
+            unsigned long ivr;
+            unsigned long tpr;
+            unsigned long eoi;
+            unsigned long irr[4];
+            unsigned long itv;  // CR72
+            unsigned long pmv;
+            unsigned long cmcv;
+            unsigned long rsv5[5];
+            unsigned long lrr0;  // CR80
+            unsigned long lrr1;
+            unsigned long rsv6[46];
+        };
+    };
+    union {
+        unsigned long  reserved5[128];
+        struct {
+            unsigned long precover_ifs;
+            unsigned long unat;  // not sure if this is needed until NaT arch is done
+            int interrupt_collection_enabled; // virtual psr.ic
+            /* virtual interrupt deliverable flag is evtchn_upcall_mask in
+             * shared info area now. interrupt_mask_addr is the address
+             * of evtchn_upcall_mask for current vcpu
+             */
+            unsigned char *interrupt_mask_addr;
+            int pending_interruption;
+            int incomplete_regframe; // see SDM vol2 6.8
+            unsigned char vpsr_pp;
+            unsigned char reserved5_2[7];
+            unsigned long reserved5_1[3];
+            int metaphysical_mode; // 1 = use metaphys mapping, 0 = use virtual
+            int banknum; // 0 or 1, which virtual register bank is active
+            unsigned long rrs[8]; // region registers
+            unsigned long krs[8]; // kernel registers
+            unsigned long pkrs[8]; // protection key registers
+            unsigned long tmp[8]; // temp registers (e.g. for hyperprivops)
+        };
+    };
+};
+typedef struct mapped_regs mapped_regs_t;
+
+struct vpd {
+    struct mapped_regs vpd_low;
+    unsigned long  reserved6[3456];
+    unsigned long  vmm_avail[128];
+    unsigned long  reserved7[4096];
+};
+typedef struct vpd vpd_t;
+
+struct arch_vcpu_info {
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct arch_shared_info {
+    /* PFN of the start_info page.  */
+    unsigned long start_info_pfn;
+
+    /* Interrupt vector for event channel.  */
+    int evtchn_vector;
+
+    uint64_t pad[32];
+};
+typedef struct arch_shared_info arch_shared_info_t;
+
+typedef unsigned long xen_callback_t;
+
+struct ia64_tr_entry {
+    unsigned long pte;
+    unsigned long itir;
+    unsigned long vadr;
+    unsigned long rid;
+};
+
+struct vcpu_extra_regs {
+    struct ia64_tr_entry itrs[8];
+    struct ia64_tr_entry dtrs[8];
+    unsigned long iva;
+    unsigned long dcr;
+    unsigned long event_callback_ip;
+};
+
+struct vcpu_guest_context {
+#define VGCF_EXTRA_REGS (1<<1) /* Get/Set extra regs.  */
+    unsigned long flags;       /* VGCF_* flags */
+
+    struct cpu_user_regs user_regs;
+    struct vcpu_extra_regs extra_regs;
+    unsigned long privregs_pfn;
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+
+// dom0 vp op
+#define __HYPERVISOR_ia64_dom0vp_op     __HYPERVISOR_arch_0
+#define IA64_DOM0VP_ioremap             0       // map io space in machine
+                                                // address to dom0 physical
+                                                // address space.
+                                                // currently physical
+                                                // assignedg address equals to
+                                                // machine address
+#define IA64_DOM0VP_phystomach          1       // convert a pseudo physical
+                                                // page frame number
+                                                // to the corresponding
+                                                // machine page frame number.
+                                                // if no page is assigned,
+                                                // INVALID_MFN or GPFN_INV_MASK
+                                                // is returned depending on
+                                                // domain's non-vti/vti mode.
+#define IA64_DOM0VP_machtophys          3       // convert a machine page
+                                                // frame number
+                                                // to the corresponding
+                                                // pseudo physical page frame
+                                                // number of the caller domain
+#define IA64_DOM0VP_zap_physmap         17      // unmap and free pages
+                                                // contained in the specified
+                                                // pseudo physical region
+#define IA64_DOM0VP_add_physmap         18      // assigne machine page frane
+                                                // to dom0's pseudo physical
+                                                // address space.
+// flags for page assignement to pseudo physical address space
+#define _ASSIGN_readonly                0
+#define ASSIGN_readonly                 (1UL << _ASSIGN_readonly)
+#define ASSIGN_writable                 (0UL << _ASSIGN_readonly) // dummy flag
+/* Internal only: memory attribute must be WC/UC/UCE.  */
+#define _ASSIGN_nocache                 1
+#define ASSIGN_nocache                  (1UL << _ASSIGN_nocache)
+
+/* This structure has the same layout of struct ia64_boot_param, defined in
+   <asm/system.h>.  It is redefined here to ease use.  */
+struct xen_ia64_boot_param {
+       unsigned long command_line;     /* physical address of cmd line args */
+       unsigned long efi_systab;       /* physical address of EFI system table */
+       unsigned long efi_memmap;       /* physical address of EFI memory map */
+       unsigned long efi_memmap_size;  /* size of EFI memory map */
+       unsigned long efi_memdesc_size; /* size of an EFI memory map descriptor */
+       unsigned int  efi_memdesc_version;      /* memory descriptor version */
+       struct {
+               unsigned short num_cols;        /* number of columns on console.  */
+               unsigned short num_rows;        /* number of rows on console.  */
+               unsigned short orig_x;  /* cursor's x position */
+               unsigned short orig_y;  /* cursor's y position */
+       } console_info;
+       unsigned long fpswa;            /* physical address of the fpswa interface */
+       unsigned long initrd_start;
+       unsigned long initrd_size;
+       unsigned long domain_start;     /* va where the boot time domain begins */
+       unsigned long domain_size;      /* how big is the boot domain */
+};
+
+#endif /* !__ASSEMBLY__ */
+
+/* Address of shared_info in domain virtual space.
+   This is the default address, for compatibility only.  */
+#define XSI_BASE                       0xf100000000000000
+
+/* Size of the shared_info area (this is not related to page size).  */
+#define XSI_SHIFT                      14
+#define XSI_SIZE                       (1 << XSI_SHIFT)
+/* Log size of mapped_regs area (64 KB - only 4KB is used).  */
+#define XMAPPEDREGS_SHIFT              12
+/* Offset of XASI (Xen arch shared info) wrt XSI_BASE.  */
+#define XMAPPEDREGS_OFS                        XSI_SIZE
+
+/* Hyperprivops.  */
+#define HYPERPRIVOP_RFI                        0x1
+#define HYPERPRIVOP_RSM_DT             0x2
+#define HYPERPRIVOP_SSM_DT             0x3
+#define HYPERPRIVOP_COVER              0x4
+#define HYPERPRIVOP_ITC_D              0x5
+#define HYPERPRIVOP_ITC_I              0x6
+#define HYPERPRIVOP_SSM_I              0x7
+#define HYPERPRIVOP_GET_IVR            0x8
+#define HYPERPRIVOP_GET_TPR            0x9
+#define HYPERPRIVOP_SET_TPR            0xa
+#define HYPERPRIVOP_EOI                        0xb
+#define HYPERPRIVOP_SET_ITM            0xc
+#define HYPERPRIVOP_THASH              0xd
+#define HYPERPRIVOP_PTC_GA             0xe
+#define HYPERPRIVOP_ITR_D              0xf
+#define HYPERPRIVOP_GET_RR             0x10
+#define HYPERPRIVOP_SET_RR             0x11
+#define HYPERPRIVOP_SET_KR             0x12
+#define HYPERPRIVOP_FC                 0x13
+#define HYPERPRIVOP_GET_CPUID          0x14
+#define HYPERPRIVOP_GET_PMD            0x15
+#define HYPERPRIVOP_GET_EFLAG          0x16
+#define HYPERPRIVOP_SET_EFLAG          0x17
+#define HYPERPRIVOP_RSM_BE             0x18
+#define HYPERPRIVOP_GET_PSR            0x19
+#define HYPERPRIVOP_MAX                        0x19
+
+#endif /* __HYPERVISOR_IF_IA64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/xen/interface/domctl.h b/include/xen/interface/domctl.h
new file mode 100644 (file)
index 0000000..6ad8918
--- /dev/null
@@ -0,0 +1,392 @@
+/******************************************************************************
+ * domctl.h
+ * 
+ * Domain management operations. For use by node control stack.
+ * 
+ * Copyright (c) 2002-2003, B Dragovic
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_DOMCTL_H__
+#define __XEN_PUBLIC_DOMCTL_H__
+
+#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
+#error "domctl operations are intended for use by node control tools only"
+#endif
+
+#include "xen.h"
+
+#define XEN_DOMCTL_INTERFACE_VERSION 0x00000003
+
+struct xenctl_cpumap {
+    XEN_GUEST_HANDLE(uint8_t) bitmap;
+    uint32_t nr_cpus;
+};
+
+/*
+ * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
+ * If it is specified as zero, an id is auto-allocated and returned.
+ */
+#define XEN_DOMCTL_createdomain       1
+struct xen_domctl_createdomain {
+    /* IN parameters */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+};
+typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
+
+#define XEN_DOMCTL_destroydomain      2
+#define XEN_DOMCTL_pausedomain        3
+#define XEN_DOMCTL_unpausedomain      4
+
+#define XEN_DOMCTL_getdomaininfo      5
+struct xen_domctl_getdomaininfo {
+    /* OUT variables. */
+    domid_t  domain;              /* Also echoed in domctl.domain */
+#define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
+#define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
+#define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
+#define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
+#define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
+#define DOMFLAGS_CPUMASK      255 /* CPU to which this domain is bound.      */
+#define DOMFLAGS_CPUSHIFT       8
+#define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code.  */
+#define DOMFLAGS_SHUTDOWNSHIFT 16
+    uint32_t flags;
+    uint64_t tot_pages;
+    uint64_t max_pages;
+    uint64_t shared_info_frame;  /* MFN of shared_info struct */
+    uint64_t cpu_time;
+    uint32_t nr_online_vcpus;     /* Number of VCPUs currently online. */
+    uint32_t max_vcpu_id;         /* Maximum VCPUID in use by this domain. */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+};
+typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t);
+
+
+#define XEN_DOMCTL_getmemlist         6
+struct xen_domctl_getmemlist {
+    /* IN variables. */
+    /* Max entries to write to output buffer. */
+    uint64_t max_pfns;
+    /* Start index in guest's page list. */
+    uint64_t start_pfn;
+    XEN_GUEST_HANDLE(xen_pfn_t) buffer;
+    /* OUT variables. */
+    uint64_t num_pfns;
+};
+typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t);
+
+
+#define XEN_DOMCTL_getpageframeinfo   7
+
+#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28
+#define XEN_DOMCTL_PFINFO_NOTAB   (0x0<<28)
+#define XEN_DOMCTL_PFINFO_L1TAB   (0x1<<28)
+#define XEN_DOMCTL_PFINFO_L2TAB   (0x2<<28)
+#define XEN_DOMCTL_PFINFO_L3TAB   (0x3<<28)
+#define XEN_DOMCTL_PFINFO_L4TAB   (0x4<<28)
+#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7<<28)
+#define XEN_DOMCTL_PFINFO_LPINTAB (0x1<<31)
+#define XEN_DOMCTL_PFINFO_XTAB    (0xf<<28) /* invalid page */
+#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xf<<28)
+
+struct xen_domctl_getpageframeinfo {
+    /* IN variables. */
+    uint64_t gmfn;        /* GMFN to query */
+    /* OUT variables. */
+    /* Is the page PINNED to a type? */
+    uint32_t type;         /* see above type defs */
+};
+typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t);
+
+
+#define XEN_DOMCTL_getpageframeinfo2  8
+struct xen_domctl_getpageframeinfo2 {
+    /* IN variables. */
+    uint64_t num;
+    /* IN/OUT variables. */
+    XEN_GUEST_HANDLE(ulong) array;
+};
+typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t);
+
+
+/*
+ * Control shadow pagetables operation
+ */
+#define XEN_DOMCTL_shadow_op         10
+
+/* Disable shadow mode. */
+#define XEN_DOMCTL_SHADOW_OP_OFF         0
+
+/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE      32
+
+/* Log-dirty bitmap operations. */
+ /* Return the bitmap and clean internal copy for next round. */
+#define XEN_DOMCTL_SHADOW_OP_CLEAN       11
+ /* Return the bitmap but do not modify internal copy. */
+#define XEN_DOMCTL_SHADOW_OP_PEEK        12
+
+/* Memory allocation accessors. */
+#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION   30
+#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION   31
+
+/* Legacy enable operations. */
+ /* Equiv. to ENABLE with no mode flags. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST       1
+ /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY   2
+ /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE  3
+
+/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */
+ /*
+  * Shadow pagetables are refcounted: guest does not use explicit mmu
+  * operations nor write-protect its pagetables.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT  (1 << 1)
+ /*
+  * Log pages in a bitmap as they are dirtied.
+  * Used for live relocation to determine which pages must be re-sent.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2)
+ /*
+  * Automatically translate GPFNs into MFNs.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3)
+ /*
+  * Xen does not steal virtual address space from the guest.
+  * Requires HVM support.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL  (1 << 4)
+
+struct xen_domctl_shadow_op_stats {
+    uint32_t fault_count;
+    uint32_t dirty_count;
+};
+typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t);
+
+struct xen_domctl_shadow_op {
+    /* IN variables. */
+    uint32_t       op;       /* XEN_DOMCTL_SHADOW_OP_* */
+
+    /* OP_ENABLE */
+    uint32_t       mode;     /* XEN_DOMCTL_SHADOW_ENABLE_* */
+
+    /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */
+    uint32_t       mb;       /* Shadow memory allocation in MB */
+
+    /* OP_PEEK / OP_CLEAN */
+    XEN_GUEST_HANDLE(ulong) dirty_bitmap;
+    uint64_t       pages;    /* Size of buffer. Updated with actual size. */
+    struct xen_domctl_shadow_op_stats stats;
+};
+typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t);
+
+
+#define XEN_DOMCTL_max_mem           11
+struct xen_domctl_max_mem {
+    /* IN variables. */
+    uint64_t max_memkb;
+};
+typedef struct xen_domctl_max_mem xen_domctl_max_mem_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t);
+
+
+#define XEN_DOMCTL_setvcpucontext    12
+#define XEN_DOMCTL_getvcpucontext    13
+struct xen_domctl_vcpucontext {
+    uint32_t              vcpu;                  /* IN */
+    XEN_GUEST_HANDLE(vcpu_guest_context_t) ctxt; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t);
+
+
+#define XEN_DOMCTL_getvcpuinfo       14
+struct xen_domctl_getvcpuinfo {
+    /* IN variables. */
+    uint32_t vcpu;
+    /* OUT variables. */
+    uint8_t  online;                  /* currently online (not hotplugged)? */
+    uint8_t  blocked;                 /* blocked waiting for an event? */
+    uint8_t  running;                 /* currently scheduled on its CPU? */
+    uint64_t cpu_time;                /* total cpu time consumed (ns) */
+    uint32_t cpu;                     /* current mapping   */
+};
+typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t);
+
+
+/* Get/set which physical cpus a vcpu can execute on. */
+#define XEN_DOMCTL_setvcpuaffinity    9
+#define XEN_DOMCTL_getvcpuaffinity   25
+struct xen_domctl_vcpuaffinity {
+    uint32_t  vcpu;              /* IN */
+    struct xenctl_cpumap cpumap; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t);
+
+
+#define XEN_DOMCTL_max_vcpus         15
+struct xen_domctl_max_vcpus {
+    uint32_t max;           /* maximum number of vcpus */
+};
+typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t);
+
+
+#define XEN_DOMCTL_scheduler_op      16
+/* Scheduler types. */
+#define XEN_SCHEDULER_SEDF     4
+#define XEN_SCHEDULER_CREDIT   5
+/* Set or get info? */
+#define XEN_DOMCTL_SCHEDOP_putinfo 0
+#define XEN_DOMCTL_SCHEDOP_getinfo 1
+struct xen_domctl_scheduler_op {
+    uint32_t sched_id;  /* XEN_SCHEDULER_* */
+    uint32_t cmd;       /* XEN_DOMCTL_SCHEDOP_* */
+    union {
+        struct xen_domctl_sched_sedf {
+            uint64_t period;
+            uint64_t slice;
+            uint64_t latency;
+            uint32_t extratime;
+            uint32_t weight;
+        } sedf;
+        struct xen_domctl_sched_credit {
+            uint16_t weight;
+            uint16_t cap;
+        } credit;
+    } u;
+};
+typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t);
+
+
+#define XEN_DOMCTL_setdomainhandle   17
+struct xen_domctl_setdomainhandle {
+    xen_domain_handle_t handle;
+};
+typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t);
+
+
+#define XEN_DOMCTL_setdebugging      18
+struct xen_domctl_setdebugging {
+    uint8_t enable;
+};
+typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t);
+
+
+#define XEN_DOMCTL_irq_permission    19
+struct xen_domctl_irq_permission {
+    uint8_t pirq;
+    uint8_t allow_access;    /* flag to specify enable/disable of IRQ access */
+};
+typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t);
+
+
+#define XEN_DOMCTL_iomem_permission  20
+struct xen_domctl_iomem_permission {
+    uint64_t first_mfn;       /* first page (physical page number) in range */
+    uint64_t nr_mfns;         /* number of pages in range (>0) */
+    uint8_t  allow_access;    /* allow (!0) or deny (0) access to range? */
+};
+typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t);
+
+
+#define XEN_DOMCTL_ioport_permission 21
+struct xen_domctl_ioport_permission {
+    uint32_t first_port;              /* first port int range */
+    uint32_t nr_ports;                /* size of port range */
+    uint8_t  allow_access;            /* allow or deny access to range? */
+};
+typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t);
+
+#define XEN_DOMCTL_hypercall_init    22
+struct xen_domctl_hypercall_init {
+    uint64_t  gmfn;            /* GMFN to be initialised */
+};
+typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
+
+#define XEN_DOMCTL_arch_setup        23
+#define _XEN_DOMAINSETUP_hvm_guest 0
+#define XEN_DOMAINSETUP_hvm_guest  (1UL<<_XEN_DOMAINSETUP_hvm_guest)
+#define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save)  */
+#define XEN_DOMAINSETUP_query  (1UL<<_XEN_DOMAINSETUP_query)
+typedef struct xen_domctl_arch_setup {
+    uint64_t flags;      /* XEN_DOMAINSETUP_* */
+#ifdef __ia64__
+    uint64_t bp;            /* mpaddr of boot param area */
+    uint64_t maxmem;        /* Highest memory address for MDT.  */
+    uint64_t xsi_va;        /* Xen shared_info area virtual address.  */
+    uint32_t hypercall_imm; /* Break imm for Xen hypercalls.  */
+#endif
+} xen_domctl_arch_setup_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t);
+
+#define XEN_DOMCTL_settimeoffset     24
+struct xen_domctl_settimeoffset {
+    int32_t  time_offset_seconds; /* applied to domain wallclock time */
+};
+typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
+
+struct xen_domctl {
+    uint32_t cmd;
+    uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
+    domid_t  domain;
+    union {
+        struct xen_domctl_createdomain      createdomain;
+        struct xen_domctl_getdomaininfo     getdomaininfo;
+        struct xen_domctl_getmemlist        getmemlist;
+        struct xen_domctl_getpageframeinfo  getpageframeinfo;
+        struct xen_domctl_getpageframeinfo2 getpageframeinfo2;
+        struct xen_domctl_vcpuaffinity      vcpuaffinity;
+        struct xen_domctl_shadow_op         shadow_op;
+        struct xen_domctl_max_mem           max_mem;
+        struct xen_domctl_vcpucontext       vcpucontext;
+        struct xen_domctl_getvcpuinfo       getvcpuinfo;
+        struct xen_domctl_max_vcpus         max_vcpus;
+        struct xen_domctl_scheduler_op      scheduler_op;
+        struct xen_domctl_setdomainhandle   setdomainhandle;
+        struct xen_domctl_setdebugging      setdebugging;
+        struct xen_domctl_irq_permission    irq_permission;
+        struct xen_domctl_iomem_permission  iomem_permission;
+        struct xen_domctl_ioport_permission ioport_permission;
+        struct xen_domctl_hypercall_init    hypercall_init;
+        struct xen_domctl_arch_setup        arch_setup;
+        struct xen_domctl_settimeoffset     settimeoffset;
+        uint8_t                             pad[128];
+    } u;
+};
+typedef struct xen_domctl xen_domctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_t);
+
+#endif /* __XEN_PUBLIC_DOMCTL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/xen/interface/elfnote.h b/include/xen/interface/elfnote.h
new file mode 100644 (file)
index 0000000..a64d3df
--- /dev/null
@@ -0,0 +1,133 @@
+/******************************************************************************
+ * elfnote.h
+ *
+ * Definitions used for the Xen ELF notes.
+ *
+ * Copyright (c) 2006, Ian Campbell, XenSource Ltd.
+ */
+
+#ifndef __XEN_PUBLIC_ELFNOTE_H__
+#define __XEN_PUBLIC_ELFNOTE_H__
+
+/*
+ * The notes should live in a SHT_NOTE segment and have "Xen" in the
+ * name field.
+ *
+ * Numeric types are either 4 or 8 bytes depending on the content of
+ * the desc field.
+ *
+ * LEGACY indicated the fields in the legacy __xen_guest string which
+ * this a note type replaces.
+ */
+
+/*
+ * NAME=VALUE pair (string).
+ *
+ * LEGACY: FEATURES and PAE
+ */
+#define XEN_ELFNOTE_INFO           0
+
+/*
+ * The virtual address of the entry point (numeric).
+ *
+ * LEGACY: VIRT_ENTRY
+ */
+#define XEN_ELFNOTE_ENTRY          1
+
+/* The virtual address of the hypercall transfer page (numeric).
+ *
+ * LEGACY: HYPERCALL_PAGE. (n.b. legacy value is a physical page
+ * number not a virtual address)
+ */
+#define XEN_ELFNOTE_HYPERCALL_PAGE 2
+
+/* The virtual address where the kernel image should be mapped (numeric).
+ *
+ * Defaults to 0.
+ *
+ * LEGACY: VIRT_BASE
+ */
+#define XEN_ELFNOTE_VIRT_BASE      3
+
+/*
+ * The offset of the ELF paddr field from the acutal required
+ * psuedo-physical address (numeric).
+ *
+ * This is used to maintain backwards compatibility with older kernels
+ * which wrote __PAGE_OFFSET into that field. This field defaults to 0
+ * if not present.
+ *
+ * LEGACY: ELF_PADDR_OFFSET. (n.b. legacy default is VIRT_BASE)
+ */
+#define XEN_ELFNOTE_PADDR_OFFSET   4
+
+/*
+ * The version of Xen that we work with (string).
+ *
+ * LEGACY: XEN_VER
+ */
+#define XEN_ELFNOTE_XEN_VERSION    5
+
+/*
+ * The name of the guest operating system (string).
+ *
+ * LEGACY: GUEST_OS
+ */
+#define XEN_ELFNOTE_GUEST_OS       6
+
+/*
+ * The version of the guest operating system (string).
+ *
+ * LEGACY: GUEST_VER
+ */
+#define XEN_ELFNOTE_GUEST_VERSION  7
+
+/*
+ * The loader type (string).
+ *
+ * LEGACY: LOADER
+ */
+#define XEN_ELFNOTE_LOADER         8
+
+/*
+ * The kernel supports PAE (x86/32 only, string = "yes" or "no").
+ *
+ * LEGACY: PAE (n.b. The legacy interface included a provision to
+ * indicate 'extended-cr3' support allowing L3 page tables to be
+ * placed above 4G. It is assumed that any kernel new enough to use
+ * these ELF notes will include this and therefore "yes" here is
+ * equivalent to "yes[entended-cr3]" in the __xen_guest interface.
+ */
+#define XEN_ELFNOTE_PAE_MODE       9
+
+/*
+ * The features supported/required by this kernel (string).
+ *
+ * The string must consist of a list of feature names (as given in
+ * features.h, without the "XENFEAT_" prefix) separated by '|'
+ * characters. If a feature is required for the kernel to function
+ * then the feature name must be preceded by a '!' character.
+ *
+ * LEGACY: FEATURES
+ */
+#define XEN_ELFNOTE_FEATURES      10
+
+/*
+ * The kernel requires the symbol table to be loaded (string = "yes" or "no")
+ * LEGACY: BSD_SYMTAB (n.b. The legacy treated the presence or absence
+ * of this string as a boolean flag rather than requiring "yes" or
+ * "no".
+ */
+#define XEN_ELFNOTE_BSD_SYMTAB    11
+
+#endif /* __XEN_PUBLIC_ELFNOTE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/xen/interface/hvm/e820.h b/include/xen/interface/hvm/e820.h
new file mode 100644 (file)
index 0000000..8190c76
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __XEN_PUBLIC_HVM_E820_H__
+#define __XEN_PUBLIC_HVM_E820_H__
+
+/* PC BIOS standard E820 types. */
+#define E820_RAM          1
+#define E820_RESERVED     2
+#define E820_ACPI         3
+#define E820_NVS          4
+
+/* Xen HVM extended E820 types. */
+#define E820_IO          16
+#define E820_SHARED_PAGE 17
+#define E820_XENSTORE    18
+#define E820_BUFFERED_IO 19
+
+/* E820 location in HVM virtual address space. */
+#define E820_MAP_PAGE        0x00090000
+#define E820_MAP_NR_OFFSET   0x000001E8
+#define E820_MAP_OFFSET      0x000002D0
+
+struct e820entry {
+    uint64_t addr;
+    uint64_t size;
+    uint32_t type;
+} __attribute__((packed));
+
+#define HVM_BELOW_4G_RAM_END        0xF0000000
+
+#define HVM_BELOW_4G_MMIO_START     HVM_BELOW_4G_RAM_END
+#define HVM_BELOW_4G_MMIO_LENGTH    ((1ULL << 32) - HVM_BELOW_4G_MMIO_START)
+
+#endif /* __XEN_PUBLIC_HVM_E820_H__ */
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
new file mode 100644 (file)
index 0000000..46e9160
--- /dev/null
@@ -0,0 +1,125 @@
+/******************************************************************************
+ * platform.h
+ * 
+ * Hardware platform operations. Intended for use by domain-0 kernel.
+ * 
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_PLATFORM_H__
+#define __XEN_PUBLIC_PLATFORM_H__
+
+#include "xen.h"
+
+#define XENPF_INTERFACE_VERSION 0x03000001
+
+/*
+ * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
+ * 1 January, 1970 if the current system time was <system_time>.
+ */
+#define XENPF_settime             17
+struct xenpf_settime {
+    /* IN variables. */
+    uint32_t secs;
+    uint32_t nsecs;
+    uint64_t system_time;
+};
+typedef struct xenpf_settime xenpf_settime_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t);
+
+/*
+ * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type.
+ * On x86, @type is an architecture-defined MTRR memory type.
+ * On success, returns the MTRR that was used (@reg) and a handle that can
+ * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting.
+ * (x86-specific).
+ */
+#define XENPF_add_memtype         31
+struct xenpf_add_memtype {
+    /* IN variables. */
+    xen_pfn_t mfn;
+    uint64_t nr_mfns;
+    uint32_t type;
+    /* OUT variables. */
+    uint32_t handle;
+    uint32_t reg;
+};
+typedef struct xenpf_add_memtype xenpf_add_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t);
+
+/*
+ * Tear down an existing memory-range type. If @handle is remembered then it
+ * should be passed in to accurately tear down the correct setting (in case
+ * of overlapping memory regions with differing types). If it is not known
+ * then @handle should be set to zero. In all cases @reg must be set.
+ * (x86-specific).
+ */
+#define XENPF_del_memtype         32
+struct xenpf_del_memtype {
+    /* IN variables. */
+    uint32_t handle;
+    uint32_t reg;
+};
+typedef struct xenpf_del_memtype xenpf_del_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t);
+
+/* Read current type of an MTRR (x86-specific). */
+#define XENPF_read_memtype        33
+struct xenpf_read_memtype {
+    /* IN variables. */
+    uint32_t reg;
+    /* OUT variables. */
+    xen_pfn_t mfn;
+    uint64_t nr_mfns;
+    uint32_t type;
+};
+typedef struct xenpf_read_memtype xenpf_read_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t);
+
+#define XENPF_microcode_update    35
+struct xenpf_microcode_update {
+    /* IN variables. */
+    XEN_GUEST_HANDLE(void) data;      /* Pointer to microcode data */
+    uint32_t length;                  /* Length of microcode data. */
+};
+typedef struct xenpf_microcode_update xenpf_microcode_update_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t);
+
+#define XENPF_platform_quirk      39
+#define QUIRK_NOIRQBALANCING      1 /* Do not restrict IO-APIC RTE targets */
+#define QUIRK_IOAPIC_BAD_REGSEL   2 /* IO-APIC REGSEL forgets its value    */
+#define QUIRK_IOAPIC_GOOD_REGSEL  3 /* IO-APIC REGSEL behaves properly     */
+struct xenpf_platform_quirk {
+    /* IN variables. */
+    uint32_t quirk_id;
+};
+typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
+
+struct xen_platform_op {
+    uint32_t cmd;
+    uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
+    union {
+        struct xenpf_settime           settime;
+        struct xenpf_add_memtype       add_memtype;
+        struct xenpf_del_memtype       del_memtype;
+        struct xenpf_read_memtype      read_memtype;
+        struct xenpf_microcode_update  microcode;
+        struct xenpf_platform_quirk    platform_quirk;
+        uint8_t                        pad[128];
+    } u;
+};
+typedef struct xen_platform_op xen_platform_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t);
+
+#endif /* __XEN_PUBLIC_PLATFORM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/xen/interface/sysctl.h b/include/xen/interface/sysctl.h
new file mode 100644 (file)
index 0000000..d556270
--- /dev/null
@@ -0,0 +1,151 @@
+/******************************************************************************
+ * sysctl.h
+ * 
+ * System management operations. For use by node control stack.
+ * 
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_SYSCTL_H__
+#define __XEN_PUBLIC_SYSCTL_H__
+
+#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
+#error "sysctl operations are intended for use by node control tools only"
+#endif
+
+#include "xen.h"
+#include "domctl.h"
+
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000002
+
+/*
+ * Read console content from Xen buffer ring.
+ */
+#define XEN_SYSCTL_readconsole       1
+struct xen_sysctl_readconsole {
+    /* IN variables. */
+    uint32_t clear;                /* Non-zero -> clear after reading. */
+    XEN_GUEST_HANDLE(char) buffer; /* Buffer start */
+    /* IN/OUT variables. */
+    uint32_t count;            /* In: Buffer size;  Out: Used buffer size  */
+};
+typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t);
+
+/* Get trace buffers machine base address */
+#define XEN_SYSCTL_tbuf_op           2
+struct xen_sysctl_tbuf_op {
+    /* IN variables */
+#define XEN_SYSCTL_TBUFOP_get_info     0
+#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1
+#define XEN_SYSCTL_TBUFOP_set_evt_mask 2
+#define XEN_SYSCTL_TBUFOP_set_size     3
+#define XEN_SYSCTL_TBUFOP_enable       4
+#define XEN_SYSCTL_TBUFOP_disable      5
+    uint32_t cmd;
+    /* IN/OUT variables */
+    struct xenctl_cpumap cpu_mask;
+    uint32_t             evt_mask;
+    /* OUT variables */
+    uint64_t buffer_mfn;
+    uint32_t size;
+};
+typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t);
+
+/*
+ * Get physical information about the host machine
+ */
+#define XEN_SYSCTL_physinfo          3
+struct xen_sysctl_physinfo {
+    uint32_t threads_per_core;
+    uint32_t cores_per_socket;
+    uint32_t sockets_per_node;
+    uint32_t nr_nodes;
+    uint32_t cpu_khz;
+    uint64_t total_pages;
+    uint64_t free_pages;
+    uint64_t scrub_pages;
+    uint32_t hw_cap[8];
+};
+typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t);
+
+/*
+ * Get the ID of the current scheduler.
+ */
+#define XEN_SYSCTL_sched_id          4
+struct xen_sysctl_sched_id {
+    /* OUT variable */
+    uint32_t sched_id;
+};
+typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t);
+
+/* Interface for controlling Xen software performance counters. */
+#define XEN_SYSCTL_perfc_op          5
+/* Sub-operations: */
+#define XEN_SYSCTL_PERFCOP_reset 1   /* Reset all counters to zero. */
+#define XEN_SYSCTL_PERFCOP_query 2   /* Get perfctr information. */
+struct xen_sysctl_perfc_desc {
+    char         name[80];             /* name of perf counter */
+    uint32_t     nr_vals;              /* number of values for this counter */
+};
+typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t);
+typedef uint32_t xen_sysctl_perfc_val_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t);
+
+struct xen_sysctl_perfc_op {
+    /* IN variables. */
+    uint32_t       cmd;                /*  XEN_SYSCTL_PERFCOP_??? */
+    /* OUT variables. */
+    uint32_t       nr_counters;       /*  number of counters description  */
+    uint32_t       nr_vals;                      /*  number of values  */
+    /* counter information (or NULL) */
+    XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc;
+    /* counter values (or NULL) */
+    XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val;
+};
+typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t);
+
+#define XEN_SYSCTL_getdomaininfolist 6
+struct xen_sysctl_getdomaininfolist {
+    /* IN variables. */
+    domid_t               first_domain;
+    uint32_t              max_domains;
+    XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t) buffer;
+    /* OUT variables. */
+    uint32_t              num_domains;
+};
+typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
+
+struct xen_sysctl {
+    uint32_t cmd;
+    uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
+    union {
+        struct xen_sysctl_readconsole       readconsole;
+        struct xen_sysctl_tbuf_op           tbuf_op;
+        struct xen_sysctl_physinfo          physinfo;
+        struct xen_sysctl_sched_id          sched_id;
+        struct xen_sysctl_perfc_op          perfc_op;
+        struct xen_sysctl_getdomaininfolist getdomaininfolist;
+        uint8_t                             pad[128];
+    } u;
+};
+typedef struct xen_sysctl xen_sysctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t);
+
+#endif /* __XEN_PUBLIC_SYSCTL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
new file mode 100644 (file)
index 0000000..36752f1
--- /dev/null
@@ -0,0 +1,162 @@
+/* delayacct.c - per-task delay accounting
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2006
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/sysctl.h>
+#include <linux/delayacct.h>
+
+int delayacct_on __read_mostly = 1;    /* Delay accounting turned on/off */
+kmem_cache_t *delayacct_cache;
+
+static int __init delayacct_setup_disable(char *str)
+{
+       delayacct_on = 0;
+       return 1;
+}
+__setup("nodelayacct", delayacct_setup_disable);
+
+void delayacct_init(void)
+{
+       delayacct_cache = kmem_cache_create("delayacct_cache",
+                                       sizeof(struct task_delay_info),
+                                       0,
+                                       SLAB_PANIC,
+                                       NULL, NULL);
+       delayacct_tsk_init(&init_task);
+}
+
+void __delayacct_tsk_init(struct task_struct *tsk)
+{
+       tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL);
+       if (tsk->delays)
+               spin_lock_init(&tsk->delays->lock);
+}
+
+/*
+ * Start accounting for a delay statistic using
+ * its starting timestamp (@start)
+ */
+
+static inline void delayacct_start(struct timespec *start)
+{
+       do_posix_clock_monotonic_gettime(start);
+}
+
+/*
+ * Finish delay accounting for a statistic using
+ * its timestamps (@start, @end), accumalator (@total) and @count
+ */
+
+static void delayacct_end(struct timespec *start, struct timespec *end,
+                               u64 *total, u32 *count)
+{
+       struct timespec ts;
+       s64 ns;
+
+       do_posix_clock_monotonic_gettime(end);
+       ts = timespec_sub(*end, *start);
+       ns = timespec_to_ns(&ts);
+       if (ns < 0)
+               return;
+
+       spin_lock(&current->delays->lock);
+       *total += ns;
+       (*count)++;
+       spin_unlock(&current->delays->lock);
+}
+
+void __delayacct_blkio_start(void)
+{
+       delayacct_start(&current->delays->blkio_start);
+}
+
+void __delayacct_blkio_end(void)
+{
+       if (current->delays->flags & DELAYACCT_PF_SWAPIN)
+               /* Swapin block I/O */
+               delayacct_end(&current->delays->blkio_start,
+                       &current->delays->blkio_end,
+                       &current->delays->swapin_delay,
+                       &current->delays->swapin_count);
+       else    /* Other block I/O */
+               delayacct_end(&current->delays->blkio_start,
+                       &current->delays->blkio_end,
+                       &current->delays->blkio_delay,
+                       &current->delays->blkio_count);
+}
+
+int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
+{
+       s64 tmp;
+       struct timespec ts;
+       unsigned long t1,t2,t3;
+
+       /* Though tsk->delays accessed later, early exit avoids
+        * unnecessary returning of other data
+        */
+       if (!tsk->delays)
+               goto done;
+
+       tmp = (s64)d->cpu_run_real_total;
+       cputime_to_timespec(tsk->utime + tsk->stime, &ts);
+       tmp += timespec_to_ns(&ts);
+       d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp;
+
+       /*
+        * No locking available for sched_info (and too expensive to add one)
+        * Mitigate by taking snapshot of values
+        */
+       t1 = tsk->sched_info.pcnt;
+       t2 = tsk->sched_info.run_delay;
+       t3 = tsk->sched_info.cpu_time;
+
+       d->cpu_count += t1;
+
+       jiffies_to_timespec(t2, &ts);
+       tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts);
+       d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp;
+
+       tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000;
+       d->cpu_run_virtual_total =
+               (tmp < (s64)d->cpu_run_virtual_total) ? 0 : tmp;
+
+       /* zero XXX_total, non-zero XXX_count implies XXX stat overflowed */
+
+       spin_lock(&tsk->delays->lock);
+       tmp = d->blkio_delay_total + tsk->delays->blkio_delay;
+       d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp;
+       tmp = d->swapin_delay_total + tsk->delays->swapin_delay;
+       d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp;
+       d->blkio_count += tsk->delays->blkio_count;
+       d->swapin_count += tsk->delays->swapin_count;
+       spin_unlock(&tsk->delays->lock);
+
+done:
+       return 0;
+}
+
+__u64 __delayacct_blkio_ticks(struct task_struct *tsk)
+{
+       __u64 ret;
+
+       spin_lock(&tsk->delays->lock);
+       ret = nsec_to_clock_t(tsk->delays->blkio_delay +
+                               tsk->delays->swapin_delay);
+       spin_unlock(&tsk->delays->lock);
+       return ret;
+}
+
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
new file mode 100644 (file)
index 0000000..ac1f850
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * linux/kernel/irq/chip.c
+ *
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
+ *
+ * This file contains the core interrupt handling code, for irq-chip
+ * based architectures.
+ *
+ * Detailed information is available in Documentation/DocBook/genericirq
+ */
+
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include "internals.h"
+
+/**
+ *     set_irq_chip - set the irq chip for an irq
+ *     @irq:   irq number
+ *     @chip:  pointer to irq chip description structure
+ */
+int set_irq_chip(unsigned int irq, struct irq_chip *chip)
+{
+       struct irq_desc *desc;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS) {
+               printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq);
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       if (!chip)
+               chip = &no_irq_chip;
+
+       desc = irq_desc + irq;
+       spin_lock_irqsave(&desc->lock, flags);
+       irq_chip_set_defaults(chip);
+       desc->chip = chip;
+       /*
+        * For compatibility only:
+        */
+       desc->chip = chip;
+       spin_unlock_irqrestore(&desc->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(set_irq_chip);
+
+/**
+ *     set_irq_type - set the irq type for an irq
+ *     @irq:   irq number
+ *     @type:  interrupt type - see include/linux/interrupt.h
+ */
+int set_irq_type(unsigned int irq, unsigned int type)
+{
+       struct irq_desc *desc;
+       unsigned long flags;
+       int ret = -ENXIO;
+
+       if (irq >= NR_IRQS) {
+               printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
+               return -ENODEV;
+       }
+
+       desc = irq_desc + irq;
+       if (desc->chip->set_type) {
+               spin_lock_irqsave(&desc->lock, flags);
+               ret = desc->chip->set_type(irq, type);
+               spin_unlock_irqrestore(&desc->lock, flags);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(set_irq_type);
+
+/**
+ *     set_irq_data - set irq type data for an irq
+ *     @irq:   Interrupt number
+ *     @data:  Pointer to interrupt specific data
+ *
+ *     Set the hardware irq controller data for an irq
+ */
+int set_irq_data(unsigned int irq, void *data)
+{
+       struct irq_desc *desc;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS) {
+               printk(KERN_ERR
+                      "Trying to install controller data for IRQ%d\n", irq);
+               return -EINVAL;
+       }
+
+       desc = irq_desc + irq;
+       spin_lock_irqsave(&desc->lock, flags);
+       desc->handler_data = data;
+       spin_unlock_irqrestore(&desc->lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(set_irq_data);
+
+/**
+ *     set_irq_chip_data - set irq chip data for an irq
+ *     @irq:   Interrupt number
+ *     @data:  Pointer to chip specific data
+ *
+ *     Set the hardware irq chip data for an irq
+ */
+int set_irq_chip_data(unsigned int irq, void *data)
+{
+       struct irq_desc *desc = irq_desc + irq;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS || !desc->chip) {
+               printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&desc->lock, flags);
+       desc->chip_data = data;
+       spin_unlock_irqrestore(&desc->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(set_irq_chip_data);
+
+/*
+ * default enable function
+ */
+static void default_enable(unsigned int irq)
+{
+       struct irq_desc *desc = irq_desc + irq;
+
+       desc->chip->unmask(irq);
+       desc->status &= ~IRQ_MASKED;
+}
+
+/*
+ * default disable function
+ */
+static void default_disable(unsigned int irq)
+{
+       struct irq_desc *desc = irq_desc + irq;
+
+       if (!(desc->status & IRQ_DELAYED_DISABLE))
+               irq_desc[irq].chip->mask(irq);
+}
+
+/*
+ * default startup function
+ */
+static unsigned int default_startup(unsigned int irq)
+{
+       irq_desc[irq].chip->enable(irq);
+
+       return 0;
+}
+
+/*
+ * Fixup enable/disable function pointers
+ */
+void irq_chip_set_defaults(struct irq_chip *chip)
+{
+       if (!chip->enable)
+               chip->enable = default_enable;
+       if (!chip->disable)
+               chip->disable = default_disable;
+       if (!chip->startup)
+               chip->startup = default_startup;
+       if (!chip->shutdown)
+               chip->shutdown = chip->disable;
+       if (!chip->name)
+               chip->name = chip->typename;
+}
+
+static inline void mask_ack_irq(struct irq_desc *desc, int irq)
+{
+       if (desc->chip->mask_ack)
+               desc->chip->mask_ack(irq);
+       else {
+               desc->chip->mask(irq);
+               desc->chip->ack(irq);
+       }
+}
+
+/**
+ *     handle_simple_irq - Simple and software-decoded IRQs.
+ *     @irq:   the interrupt number
+ *     @desc:  the interrupt description structure for this irq
+ *     @regs:  pointer to a register structure
+ *
+ *     Simple interrupts are either sent from a demultiplexing interrupt
+ *     handler or come from hardware, where no interrupt hardware control
+ *     is necessary.
+ *
+ *     Note: The caller is expected to handle the ack, clear, mask and
+ *     unmask issues if necessary.
+ */
+void fastcall
+handle_simple_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+{
+       struct irqaction *action;
+       irqreturn_t action_ret;
+       const unsigned int cpu = smp_processor_id();
+
+       spin_lock(&desc->lock);
+
+       if (unlikely(desc->status & IRQ_INPROGRESS))
+               goto out_unlock;
+       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+       kstat_cpu(cpu).irqs[irq]++;
+
+       action = desc->action;
+       if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+               goto out_unlock;
+
+       desc->status |= IRQ_INPROGRESS;
+       spin_unlock(&desc->lock);
+
+       action_ret = handle_IRQ_event(irq, regs, action);
+       if (!noirqdebug)
+               note_interrupt(irq, desc, action_ret, regs);
+
+       spin_lock(&desc->lock);
+       desc->status &= ~IRQ_INPROGRESS;
+out_unlock:
+       spin_unlock(&desc->lock);
+}
+
+/**
+ *     handle_level_irq - Level type irq handler
+ *     @irq:   the interrupt number
+ *     @desc:  the interrupt description structure for this irq
+ *     @regs:  pointer to a register structure
+ *
+ *     Level type interrupts are active as long as the hardware line has
+ *     the active level. This may require to mask the interrupt and unmask
+ *     it after the associated handler has acknowledged the device, so the
+ *     interrupt line is back to inactive.
+ */
+void fastcall
+handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+{
+       unsigned int cpu = smp_processor_id();
+       struct irqaction *action;
+       irqreturn_t action_ret;
+
+       spin_lock(&desc->lock);
+       mask_ack_irq(desc, irq);
+
+       if (unlikely(desc->status & IRQ_INPROGRESS))
+               goto out_unlock;
+       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+       kstat_cpu(cpu).irqs[irq]++;
+
+       /*
+        * If its disabled or no action available
+        * keep it masked and get out of here
+        */
+       action = desc->action;
+       if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+               desc->status |= IRQ_PENDING;
+               goto out_unlock;
+       }
+
+       desc->status |= IRQ_INPROGRESS;
+       desc->status &= ~IRQ_PENDING;
+       spin_unlock(&desc->lock);
+
+       action_ret = handle_IRQ_event(irq, regs, action);
+       if (!noirqdebug)
+               note_interrupt(irq, desc, action_ret, regs);
+
+       spin_lock(&desc->lock);
+       desc->status &= ~IRQ_INPROGRESS;
+       if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+               desc->chip->unmask(irq);
+out_unlock:
+       spin_unlock(&desc->lock);
+}
+
+/**
+ *     handle_fasteoi_irq - irq handler for transparent controllers
+ *     @irq:   the interrupt number
+ *     @desc:  the interrupt description structure for this irq
+ *     @regs:  pointer to a register structure
+ *
+ *     Only a single callback will be issued to the chip: an ->eoi()
+ *     call when the interrupt has been serviced. This enables support
+ *     for modern forms of interrupt handlers, which handle the flow
+ *     details in hardware, transparently.
+ */
+void fastcall
+handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc,
+                  struct pt_regs *regs)
+{
+       unsigned int cpu = smp_processor_id();
+       struct irqaction *action;
+       irqreturn_t action_ret;
+
+       spin_lock(&desc->lock);
+
+       if (unlikely(desc->status & IRQ_INPROGRESS))
+               goto out;
+
+       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+       kstat_cpu(cpu).irqs[irq]++;
+
+       /*
+        * If its disabled or no action available
+        * keep it masked and get out of here
+        */
+       action = desc->action;
+       if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+               desc->status |= IRQ_PENDING;
+               goto out;
+       }
+
+       desc->status |= IRQ_INPROGRESS;
+       desc->status &= ~IRQ_PENDING;
+       spin_unlock(&desc->lock);
+
+       action_ret = handle_IRQ_event(irq, regs, action);
+       if (!noirqdebug)
+               note_interrupt(irq, desc, action_ret, regs);
+
+       spin_lock(&desc->lock);
+       desc->status &= ~IRQ_INPROGRESS;
+out:
+       desc->chip->eoi(irq);
+
+       spin_unlock(&desc->lock);
+}
+
+/**
+ *     handle_edge_irq - edge type IRQ handler
+ *     @irq:   the interrupt number
+ *     @desc:  the interrupt description structure for this irq
+ *     @regs:  pointer to a register structure
+ *
+ *     Interrupt occures on the falling and/or rising edge of a hardware
+ *     signal. The occurence is latched into the irq controller hardware
+ *     and must be acked in order to be reenabled. After the ack another
+ *     interrupt can happen on the same source even before the first one
+ *     is handled by the assosiacted event handler. If this happens it
+ *     might be necessary to disable (mask) the interrupt depending on the
+ *     controller hardware. This requires to reenable the interrupt inside
+ *     of the loop which handles the interrupts which have arrived while
+ *     the handler was running. If all pending interrupts are handled, the
+ *     loop is left.
+ */
+void fastcall
+handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+{
+       const unsigned int cpu = smp_processor_id();
+
+       spin_lock(&desc->lock);
+
+       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+
+       /*
+        * If we're currently running this IRQ, or its disabled,
+        * we shouldn't process the IRQ. Mark it pending, handle
+        * the necessary masking and go out
+        */
+       if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
+                   !desc->action)) {
+               desc->status |= (IRQ_PENDING | IRQ_MASKED);
+               mask_ack_irq(desc, irq);
+               goto out_unlock;
+       }
+
+       kstat_cpu(cpu).irqs[irq]++;
+
+       /* Start handling the irq */
+       desc->chip->ack(irq);
+
+       /* Mark the IRQ currently in progress.*/
+       desc->status |= IRQ_INPROGRESS;
+
+       do {
+               struct irqaction *action = desc->action;
+               irqreturn_t action_ret;
+
+               if (unlikely(!action)) {
+                       desc->chip->mask(irq);
+                       goto out_unlock;
+               }
+
+               /*
+                * When another irq arrived while we were handling
+                * one, we could have masked the irq.
+                * Renable it, if it was not disabled in meantime.
+                */
+               if (unlikely((desc->status &
+                              (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
+                             (IRQ_PENDING | IRQ_MASKED))) {
+                       desc->chip->unmask(irq);
+                       desc->status &= ~IRQ_MASKED;
+               }
+
+               desc->status &= ~IRQ_PENDING;
+               spin_unlock(&desc->lock);
+               action_ret = handle_IRQ_event(irq, regs, action);
+               if (!noirqdebug)
+                       note_interrupt(irq, desc, action_ret, regs);
+               spin_lock(&desc->lock);
+
+       } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
+
+       desc->status &= ~IRQ_INPROGRESS;
+out_unlock:
+       spin_unlock(&desc->lock);
+}
+
+#ifdef CONFIG_SMP
+/**
+ *     handle_percpu_IRQ - Per CPU local irq handler
+ *     @irq:   the interrupt number
+ *     @desc:  the interrupt description structure for this irq
+ *     @regs:  pointer to a register structure
+ *
+ *     Per CPU interrupts on SMP machines without locking requirements
+ */
+void fastcall
+handle_percpu_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
+{
+       irqreturn_t action_ret;
+
+       kstat_this_cpu.irqs[irq]++;
+
+       if (desc->chip->ack)
+               desc->chip->ack(irq);
+
+       action_ret = handle_IRQ_event(irq, regs, desc->action);
+       if (!noirqdebug)
+               note_interrupt(irq, desc, action_ret, regs);
+
+       if (desc->chip->eoi)
+               desc->chip->eoi(irq);
+}
+
+#endif /* CONFIG_SMP */
+
+void
+__set_irq_handler(unsigned int irq,
+                 void fastcall (*handle)(unsigned int, irq_desc_t *,
+                                         struct pt_regs *),
+                 int is_chained)
+{
+       struct irq_desc *desc;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS) {
+               printk(KERN_ERR
+                      "Trying to install type control for IRQ%d\n", irq);
+               return;
+       }
+
+       desc = irq_desc + irq;
+
+       if (!handle)
+               handle = handle_bad_irq;
+
+       if (desc->chip == &no_irq_chip) {
+               printk(KERN_WARNING "Trying to install %sinterrupt handler "
+                      "for IRQ%d\n", is_chained ? "chained " : " ", irq);
+               /*
+                * Some ARM implementations install a handler for really dumb
+                * interrupt hardware without setting an irq_chip. This worked
+                * with the ARM no_irq_chip but the check in setup_irq would
+                * prevent us to setup the interrupt at all. Switch it to
+                * dummy_irq_chip for easy transition.
+                */
+               desc->chip = &dummy_irq_chip;
+       }
+
+       spin_lock_irqsave(&desc->lock, flags);
+
+       /* Uninstall? */
+       if (handle == handle_bad_irq) {
+               if (desc->chip != &no_irq_chip) {
+                       desc->chip->mask(irq);
+                       desc->chip->ack(irq);
+               }
+               desc->status |= IRQ_DISABLED;
+               desc->depth = 1;
+       }
+       desc->handle_irq = handle;
+
+       if (handle != handle_bad_irq && is_chained) {
+               desc->status &= ~IRQ_DISABLED;
+               desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
+               desc->depth = 0;
+               desc->chip->unmask(irq);
+       }
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+void
+set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
+                        void fastcall (*handle)(unsigned int,
+                                                struct irq_desc *,
+                                                struct pt_regs *))
+{
+       set_irq_chip(irq, chip);
+       __set_irq_handler(irq, handle, 0);
+}
+
+/*
+ * Get a descriptive string for the highlevel handler, for
+ * /proc/interrupts output:
+ */
+const char *
+handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *,
+                                       struct pt_regs *))
+{
+       if (handle == handle_level_irq)
+               return "level  ";
+       if (handle == handle_fasteoi_irq)
+               return "fasteoi";
+       if (handle == handle_edge_irq)
+               return "edge   ";
+       if (handle == handle_simple_irq)
+               return "simple ";
+#ifdef CONFIG_SMP
+       if (handle == handle_percpu_irq)
+               return "percpu ";
+#endif
+       if (handle == handle_bad_irq)
+               return "bad    ";
+
+       return NULL;
+}
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
new file mode 100644 (file)
index 0000000..35f10f7
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * linux/kernel/irq/resend.c
+ *
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006, Thomas Gleixner
+ *
+ * This file contains the IRQ-resend code
+ *
+ * If the interrupt is waiting to be processed, we try to re-run it.
+ * We can't directly run it from here since the caller might be in an
+ * interrupt-protected region. Not all irq controller chips can
+ * retrigger interrupts at the hardware level, so in those cases
+ * we allow the resending of IRQs via a tasklet.
+ */
+
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/interrupt.h>
+
+#include "internals.h"
+
+#ifdef CONFIG_HARDIRQS_SW_RESEND
+
+/* Bitmap to handle software resend of interrupts: */
+static DECLARE_BITMAP(irqs_resend, NR_IRQS);
+
+/*
+ * Run software resends of IRQ's
+ */
+static void resend_irqs(unsigned long arg)
+{
+       struct irq_desc *desc;
+       int irq;
+
+       while (!bitmap_empty(irqs_resend, NR_IRQS)) {
+               irq = find_first_bit(irqs_resend, NR_IRQS);
+               clear_bit(irq, irqs_resend);
+               desc = irq_desc + irq;
+               local_irq_disable();
+               desc->handle_irq(irq, desc, NULL);
+               local_irq_enable();
+       }
+}
+
+/* Tasklet to handle resend: */
+static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0);
+
+#endif
+
+/*
+ * IRQ resend
+ *
+ * Is called with interrupts disabled and desc->lock held.
+ */
+void check_irq_resend(struct irq_desc *desc, unsigned int irq)
+{
+       unsigned int status = desc->status;
+
+       /*
+        * Make sure the interrupt is enabled, before resending it:
+        */
+       desc->chip->enable(irq);
+
+       if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+               desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY;
+
+               if (!desc->chip || !desc->chip->retrigger ||
+                                       !desc->chip->retrigger(irq)) {
+#ifdef CONFIG_HARDIRQS_SW_RESEND
+                       /* Set it pending and activate the softirq: */
+                       set_bit(irq, irqs_resend);
+                       tasklet_schedule(&resend_tasklet);
+#endif
+               }
+       }
+}
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
new file mode 100644 (file)
index 0000000..3a0c44c
--- /dev/null
@@ -0,0 +1,2727 @@
+/*
+ * kernel/lockdep.c
+ *
+ * Runtime locking correctness validator
+ *
+ * Started by Ingo Molnar:
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * this code maps all the lock dependencies as they occur in a live kernel
+ * and will warn about the following classes of locking bugs:
+ *
+ * - lock inversion scenarios
+ * - circular lock dependencies
+ * - hardirq/softirq safe/unsafe locking bugs
+ *
+ * Bugs are reported even if the current locking scenario does not cause
+ * any deadlock at this point.
+ *
+ * I.e. if anytime in the past two locks were taken in a different order,
+ * even if it happened for another task, even if those were different
+ * locks (but of the same class as this lock), this code will detect it.
+ *
+ * Thanks to Arjan van de Ven for coming up with the initial idea of
+ * mapping lock dependencies runtime.
+ */
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include <linux/interrupt.h>
+#include <linux/stacktrace.h>
+#include <linux/debug_locks.h>
+#include <linux/irqflags.h>
+#include <linux/utsname.h>
+
+#include <asm/sections.h>
+
+#include "lockdep_internals.h"
+
+/*
+ * hash_lock: protects the lockdep hashes and class/list/hash allocators.
+ *
+ * This is one of the rare exceptions where it's justified
+ * to use a raw spinlock - we really dont want the spinlock
+ * code to recurse back into the lockdep code.
+ */
+static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+
+static int lockdep_initialized;
+
+unsigned long nr_list_entries;
+static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
+
+/*
+ * Allocate a lockdep entry. (assumes hash_lock held, returns
+ * with NULL on failure)
+ */
+static struct lock_list *alloc_list_entry(void)
+{
+       if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) {
+               __raw_spin_unlock(&hash_lock);
+               debug_locks_off();
+               printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
+               printk("turning off the locking correctness validator.\n");
+               return NULL;
+       }
+       return list_entries + nr_list_entries++;
+}
+
+/*
+ * All data structures here are protected by the global debug_lock.
+ *
+ * Mutex key structs only get allocated, once during bootup, and never
+ * get freed - this significantly simplifies the debugging code.
+ */
+unsigned long nr_lock_classes;
+static struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
+
+/*
+ * We keep a global list of all lock classes. The list only grows,
+ * never shrinks. The list is only accessed with the lockdep
+ * spinlock lock held.
+ */
+LIST_HEAD(all_lock_classes);
+
+/*
+ * The lockdep classes are in a hash-table as well, for fast lookup:
+ */
+#define CLASSHASH_BITS         (MAX_LOCKDEP_KEYS_BITS - 1)
+#define CLASSHASH_SIZE         (1UL << CLASSHASH_BITS)
+#define CLASSHASH_MASK         (CLASSHASH_SIZE - 1)
+#define __classhashfn(key)     ((((unsigned long)key >> CLASSHASH_BITS) + (unsigned long)key) & CLASSHASH_MASK)
+#define classhashentry(key)    (classhash_table + __classhashfn((key)))
+
+static struct list_head classhash_table[CLASSHASH_SIZE];
+
+unsigned long nr_lock_chains;
+static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS];
+
+/*
+ * We put the lock dependency chains into a hash-table as well, to cache
+ * their existence:
+ */
+#define CHAINHASH_BITS         (MAX_LOCKDEP_CHAINS_BITS-1)
+#define CHAINHASH_SIZE         (1UL << CHAINHASH_BITS)
+#define CHAINHASH_MASK         (CHAINHASH_SIZE - 1)
+#define __chainhashfn(chain) \
+               (((chain >> CHAINHASH_BITS) + chain) & CHAINHASH_MASK)
+#define chainhashentry(chain)  (chainhash_table + __chainhashfn((chain)))
+
+static struct list_head chainhash_table[CHAINHASH_SIZE];
+
+/*
+ * The hash key of the lock dependency chains is a hash itself too:
+ * it's a hash of all locks taken up to that lock, including that lock.
+ * It's a 64-bit hash, because it's important for the keys to be
+ * unique.
+ */
+#define iterate_chain_key(key1, key2) \
+       (((key1) << MAX_LOCKDEP_KEYS_BITS/2) ^ \
+       ((key1) >> (64-MAX_LOCKDEP_KEYS_BITS/2)) ^ \
+       (key2))
+
+void lockdep_off(void)
+{
+       current->lockdep_recursion++;
+}
+
+EXPORT_SYMBOL(lockdep_off);
+
+void lockdep_on(void)
+{
+       current->lockdep_recursion--;
+}
+
+EXPORT_SYMBOL(lockdep_on);
+
+int lockdep_internal(void)
+{
+       return current->lockdep_recursion != 0;
+}
+
+EXPORT_SYMBOL(lockdep_internal);
+
+/*
+ * Debugging switches:
+ */
+
+#define VERBOSE                        0
+#ifdef VERBOSE
+# define VERY_VERBOSE          0
+#endif
+
+#if VERBOSE
+# define HARDIRQ_VERBOSE       1
+# define SOFTIRQ_VERBOSE       1
+#else
+# define HARDIRQ_VERBOSE       0
+# define SOFTIRQ_VERBOSE       0
+#endif
+
+#if VERBOSE || HARDIRQ_VERBOSE || SOFTIRQ_VERBOSE
+/*
+ * Quick filtering for interesting events:
+ */
+static int class_filter(struct lock_class *class)
+{
+#if 0
+       /* Example */
+       if (class->name_version == 1 &&
+                       !strcmp(class->name, "lockname"))
+               return 1;
+       if (class->name_version == 1 &&
+                       !strcmp(class->name, "&struct->lockfield"))
+               return 1;
+#endif
+       /* Allow everything else. 0 would be filter everything else */
+       return 1;
+}
+#endif
+
+static int verbose(struct lock_class *class)
+{
+#if VERBOSE
+       return class_filter(class);
+#endif
+       return 0;
+}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+static int hardirq_verbose(struct lock_class *class)
+{
+#if HARDIRQ_VERBOSE
+       return class_filter(class);
+#endif
+       return 0;
+}
+
+static int softirq_verbose(struct lock_class *class)
+{
+#if SOFTIRQ_VERBOSE
+       return class_filter(class);
+#endif
+       return 0;
+}
+
+#endif
+
+/*
+ * Stack-trace: tightly packed array of stack backtrace
+ * addresses. Protected by the hash_lock.
+ */
+unsigned long nr_stack_trace_entries;
+static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
+
+static int save_trace(struct stack_trace *trace)
+{
+       trace->nr_entries = 0;
+       trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries;
+       trace->entries = stack_trace + nr_stack_trace_entries;
+
+       trace->skip = 3;
+       trace->all_contexts = 0;
+
+       /* Make sure to not recurse in case the the unwinder needs to tak
+e         locks. */
+       lockdep_off();
+       save_stack_trace(trace, NULL);
+       lockdep_on();
+
+       trace->max_entries = trace->nr_entries;
+
+       nr_stack_trace_entries += trace->nr_entries;
+       if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES))
+               return 0;
+
+       if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) {
+               __raw_spin_unlock(&hash_lock);
+               if (debug_locks_off()) {
+                       printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
+                       printk("turning off the locking correctness validator.\n");
+                       dump_stack();
+               }
+               return 0;
+       }
+
+       return 1;
+}
+
+unsigned int nr_hardirq_chains;
+unsigned int nr_softirq_chains;
+unsigned int nr_process_chains;
+unsigned int max_lockdep_depth;
+unsigned int max_recursion_depth;
+
+#ifdef CONFIG_DEBUG_LOCKDEP
+/*
+ * We cannot printk in early bootup code. Not even early_printk()
+ * might work. So we mark any initialization errors and printk
+ * about it later on, in lockdep_info().
+ */
+static int lockdep_init_error;
+
+/*
+ * Various lockdep statistics:
+ */
+atomic_t chain_lookup_hits;
+atomic_t chain_lookup_misses;
+atomic_t hardirqs_on_events;
+atomic_t hardirqs_off_events;
+atomic_t redundant_hardirqs_on;
+atomic_t redundant_hardirqs_off;
+atomic_t softirqs_on_events;
+atomic_t softirqs_off_events;
+atomic_t redundant_softirqs_on;
+atomic_t redundant_softirqs_off;
+atomic_t nr_unused_locks;
+atomic_t nr_cyclic_checks;
+atomic_t nr_cyclic_check_recursions;
+atomic_t nr_find_usage_forwards_checks;
+atomic_t nr_find_usage_forwards_recursions;
+atomic_t nr_find_usage_backwards_checks;
+atomic_t nr_find_usage_backwards_recursions;
+# define debug_atomic_inc(ptr)         atomic_inc(ptr)
+# define debug_atomic_dec(ptr)         atomic_dec(ptr)
+# define debug_atomic_read(ptr)                atomic_read(ptr)
+#else
+# define debug_atomic_inc(ptr)         do { } while (0)
+# define debug_atomic_dec(ptr)         do { } while (0)
+# define debug_atomic_read(ptr)                0
+#endif
+
+/*
+ * Locking printouts:
+ */
+
+static const char *usage_str[] =
+{
+       [LOCK_USED] =                   "initial-use ",
+       [LOCK_USED_IN_HARDIRQ] =        "in-hardirq-W",
+       [LOCK_USED_IN_SOFTIRQ] =        "in-softirq-W",
+       [LOCK_ENABLED_SOFTIRQS] =       "softirq-on-W",
+       [LOCK_ENABLED_HARDIRQS] =       "hardirq-on-W",
+       [LOCK_USED_IN_HARDIRQ_READ] =   "in-hardirq-R",
+       [LOCK_USED_IN_SOFTIRQ_READ] =   "in-softirq-R",
+       [LOCK_ENABLED_SOFTIRQS_READ] =  "softirq-on-R",
+       [LOCK_ENABLED_HARDIRQS_READ] =  "hardirq-on-R",
+};
+
+const char * __get_key_name(struct lockdep_subclass_key *key, char *str)
+{
+       unsigned long offs, size;
+       char *modname;
+
+       return kallsyms_lookup((unsigned long)key, &size, &offs, &modname, str);
+}
+
+void
+get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4)
+{
+       *c1 = '.', *c2 = '.', *c3 = '.', *c4 = '.';
+
+       if (class->usage_mask & LOCKF_USED_IN_HARDIRQ)
+               *c1 = '+';
+       else
+               if (class->usage_mask & LOCKF_ENABLED_HARDIRQS)
+                       *c1 = '-';
+
+       if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ)
+               *c2 = '+';
+       else
+               if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS)
+                       *c2 = '-';
+
+       if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ)
+               *c3 = '-';
+       if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ) {
+               *c3 = '+';
+               if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ)
+                       *c3 = '?';
+       }
+
+       if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ)
+               *c4 = '-';
+       if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ) {
+               *c4 = '+';
+               if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ)
+                       *c4 = '?';
+       }
+}
+
+static void print_lock_name(struct lock_class *class)
+{
+       char str[128], c1, c2, c3, c4;
+       const char *name;
+
+       get_usage_chars(class, &c1, &c2, &c3, &c4);
+
+       name = class->name;
+       if (!name) {
+               name = __get_key_name(class->key, str);
+               printk(" (%s", name);
+       } else {
+               printk(" (%s", name);
+               if (class->name_version > 1)
+                       printk("#%d", class->name_version);
+               if (class->subclass)
+                       printk("/%d", class->subclass);
+       }
+       printk("){%c%c%c%c}", c1, c2, c3, c4);
+}
+
+static void print_lockdep_cache(struct lockdep_map *lock)
+{
+       const char *name;
+       char str[128];
+
+       name = lock->name;
+       if (!name)
+               name = __get_key_name(lock->key->subkeys, str);
+
+       printk("%s", name);
+}
+
+static void print_lock(struct held_lock *hlock)
+{
+       print_lock_name(hlock->class);
+       printk(", at: ");
+       print_ip_sym(hlock->acquire_ip);
+}
+
+static void lockdep_print_held_locks(struct task_struct *curr)
+{
+       int i, depth = curr->lockdep_depth;
+
+       if (!depth) {
+               printk("no locks held by %s/%d.\n", curr->comm, curr->pid);
+               return;
+       }
+       printk("%d lock%s held by %s/%d:\n",
+               depth, depth > 1 ? "s" : "", curr->comm, curr->pid);
+
+       for (i = 0; i < depth; i++) {
+               printk(" #%d: ", i);
+               print_lock(curr->held_locks + i);
+       }
+}
+
+static void print_lock_class_header(struct lock_class *class, int depth)
+{
+       int bit;
+
+       printk("%*s->", depth, "");
+       print_lock_name(class);
+       printk(" ops: %lu", class->ops);
+       printk(" {\n");
+
+       for (bit = 0; bit < LOCK_USAGE_STATES; bit++) {
+               if (class->usage_mask & (1 << bit)) {
+                       int len = depth;
+
+                       len += printk("%*s   %s", depth, "", usage_str[bit]);
+                       len += printk(" at:\n");
+                       print_stack_trace(class->usage_traces + bit, len);
+               }
+       }
+       printk("%*s }\n", depth, "");
+
+       printk("%*s ... key      at: ",depth,"");
+       print_ip_sym((unsigned long)class->key);
+}
+
+/*
+ * printk all lock dependencies starting at <entry>:
+ */
+static void print_lock_dependencies(struct lock_class *class, int depth)
+{
+       struct lock_list *entry;
+
+       if (DEBUG_LOCKS_WARN_ON(depth >= 20))
+               return;
+
+       print_lock_class_header(class, depth);
+
+       list_for_each_entry(entry, &class->locks_after, entry) {
+               DEBUG_LOCKS_WARN_ON(!entry->class);
+               print_lock_dependencies(entry->class, depth + 1);
+
+               printk("%*s ... acquired at:\n",depth,"");
+               print_stack_trace(&entry->trace, 2);
+               printk("\n");
+       }
+}
+
+/*
+ * Add a new dependency to the head of the list:
+ */
+static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
+                           struct list_head *head, unsigned long ip)
+{
+       struct lock_list *entry;
+       /*
+        * Lock not present yet - get a new dependency struct and
+        * add it to the list:
+        */
+       entry = alloc_list_entry();
+       if (!entry)
+               return 0;
+
+       entry->class = this;
+       save_trace(&entry->trace);
+
+       /*
+        * Since we never remove from the dependency list, the list can
+        * be walked lockless by other CPUs, it's only allocation
+        * that must be protected by the spinlock. But this also means
+        * we must make new entries visible only once writes to the
+        * entry become visible - hence the RCU op:
+        */
+       list_add_tail_rcu(&entry->entry, head);
+
+       return 1;
+}
+
+/*
+ * Recursive, forwards-direction lock-dependency checking, used for
+ * both noncyclic checking and for hardirq-unsafe/softirq-unsafe
+ * checking.
+ *
+ * (to keep the stackframe of the recursive functions small we
+ *  use these global variables, and we also mark various helper
+ *  functions as noinline.)
+ */
+static struct held_lock *check_source, *check_target;
+
+/*
+ * Print a dependency chain entry (this is only done when a deadlock
+ * has been detected):
+ */
+static noinline int
+print_circular_bug_entry(struct lock_list *target, unsigned int depth)
+{
+       if (debug_locks_silent)
+               return 0;
+       printk("\n-> #%u", depth);
+       print_lock_name(target->class);
+       printk(":\n");
+       print_stack_trace(&target->trace, 6);
+
+       return 0;
+}
+
+static void print_kernel_version(void)
+{
+       printk("%s %.*s\n", system_utsname.release,
+               (int)strcspn(system_utsname.version, " "),
+               system_utsname.version);
+}
+
+/*
+ * When a circular dependency is detected, print the
+ * header first:
+ */
+static noinline int
+print_circular_bug_header(struct lock_list *entry, unsigned int depth)
+{
+       struct task_struct *curr = current;
+
+       __raw_spin_unlock(&hash_lock);
+       debug_locks_off();
+       if (debug_locks_silent)
+               return 0;
+
+       printk("\n=======================================================\n");
+       printk(  "[ INFO: possible circular locking dependency detected ]\n");
+       print_kernel_version();
+       printk(  "-------------------------------------------------------\n");
+       printk("%s/%d is trying to acquire lock:\n",
+               curr->comm, curr->pid);
+       print_lock(check_source);
+       printk("\nbut task is already holding lock:\n");
+       print_lock(check_target);
+       printk("\nwhich lock already depends on the new lock.\n\n");
+       printk("\nthe existing dependency chain (in reverse order) is:\n");
+
+       print_circular_bug_entry(entry, depth);
+
+       return 0;
+}
+
+static noinline int print_circular_bug_tail(void)
+{
+       struct task_struct *curr = current;
+       struct lock_list this;
+
+       if (debug_locks_silent)
+               return 0;
+
+       this.class = check_source->class;
+       save_trace(&this.trace);
+       print_circular_bug_entry(&this, 0);
+
+       printk("\nother info that might help us debug this:\n\n");
+       lockdep_print_held_locks(curr);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+
+       return 0;
+}
+
+static int noinline print_infinite_recursion_bug(void)
+{
+       __raw_spin_unlock(&hash_lock);
+       DEBUG_LOCKS_WARN_ON(1);
+
+       return 0;
+}
+
+/*
+ * Prove that the dependency graph starting at <entry> can not
+ * lead to <target>. Print an error and return 0 if it does.
+ */
+static noinline int
+check_noncircular(struct lock_class *source, unsigned int depth)
+{
+       struct lock_list *entry;
+
+       debug_atomic_inc(&nr_cyclic_check_recursions);
+       if (depth > max_recursion_depth)
+               max_recursion_depth = depth;
+       if (depth >= 20)
+               return print_infinite_recursion_bug();
+       /*
+        * Check this lock's dependency list:
+        */
+       list_for_each_entry(entry, &source->locks_after, entry) {
+               if (entry->class == check_target->class)
+                       return print_circular_bug_header(entry, depth+1);
+               debug_atomic_inc(&nr_cyclic_checks);
+               if (!check_noncircular(entry->class, depth+1))
+                       return print_circular_bug_entry(entry, depth+1);
+       }
+       return 1;
+}
+
+static int very_verbose(struct lock_class *class)
+{
+#if VERY_VERBOSE
+       return class_filter(class);
+#endif
+       return 0;
+}
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+/*
+ * Forwards and backwards subgraph searching, for the purposes of
+ * proving that two subgraphs can be connected by a new dependency
+ * without creating any illegal irq-safe -> irq-unsafe lock dependency.
+ */
+static enum lock_usage_bit find_usage_bit;
+static struct lock_class *forwards_match, *backwards_match;
+
+/*
+ * Find a node in the forwards-direction dependency sub-graph starting
+ * at <source> that matches <find_usage_bit>.
+ *
+ * Return 2 if such a node exists in the subgraph, and put that node
+ * into <forwards_match>.
+ *
+ * Return 1 otherwise and keep <forwards_match> unchanged.
+ * Return 0 on error.
+ */
+static noinline int
+find_usage_forwards(struct lock_class *source, unsigned int depth)
+{
+       struct lock_list *entry;
+       int ret;
+
+       if (depth > max_recursion_depth)
+               max_recursion_depth = depth;
+       if (depth >= 20)
+               return print_infinite_recursion_bug();
+
+       debug_atomic_inc(&nr_find_usage_forwards_checks);
+       if (source->usage_mask & (1 << find_usage_bit)) {
+               forwards_match = source;
+               return 2;
+       }
+
+       /*
+        * Check this lock's dependency list:
+        */
+       list_for_each_entry(entry, &source->locks_after, entry) {
+               debug_atomic_inc(&nr_find_usage_forwards_recursions);
+               ret = find_usage_forwards(entry->class, depth+1);
+               if (ret == 2 || ret == 0)
+                       return ret;
+       }
+       return 1;
+}
+
+/*
+ * Find a node in the backwards-direction dependency sub-graph starting
+ * at <source> that matches <find_usage_bit>.
+ *
+ * Return 2 if such a node exists in the subgraph, and put that node
+ * into <backwards_match>.
+ *
+ * Return 1 otherwise and keep <backwards_match> unchanged.
+ * Return 0 on error.
+ */
+static noinline int
+find_usage_backwards(struct lock_class *source, unsigned int depth)
+{
+       struct lock_list *entry;
+       int ret;
+
+       if (depth > max_recursion_depth)
+               max_recursion_depth = depth;
+       if (depth >= 20)
+               return print_infinite_recursion_bug();
+
+       debug_atomic_inc(&nr_find_usage_backwards_checks);
+       if (source->usage_mask & (1 << find_usage_bit)) {
+               backwards_match = source;
+               return 2;
+       }
+
+       /*
+        * Check this lock's dependency list:
+        */
+       list_for_each_entry(entry, &source->locks_before, entry) {
+               debug_atomic_inc(&nr_find_usage_backwards_recursions);
+               ret = find_usage_backwards(entry->class, depth+1);
+               if (ret == 2 || ret == 0)
+                       return ret;
+       }
+       return 1;
+}
+
+static int
+print_bad_irq_dependency(struct task_struct *curr,
+                        struct held_lock *prev,
+                        struct held_lock *next,
+                        enum lock_usage_bit bit1,
+                        enum lock_usage_bit bit2,
+                        const char *irqclass)
+{
+       __raw_spin_unlock(&hash_lock);
+       debug_locks_off();
+       if (debug_locks_silent)
+               return 0;
+
+       printk("\n======================================================\n");
+       printk(  "[ INFO: %s-safe -> %s-unsafe lock order detected ]\n",
+               irqclass, irqclass);
+       print_kernel_version();
+       printk(  "------------------------------------------------------\n");
+       printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] is trying to acquire:\n",
+               curr->comm, curr->pid,
+               curr->hardirq_context, hardirq_count() >> HARDIRQ_SHIFT,
+               curr->softirq_context, softirq_count() >> SOFTIRQ_SHIFT,
+               curr->hardirqs_enabled,
+               curr->softirqs_enabled);
+       print_lock(next);
+
+       printk("\nand this task is already holding:\n");
+       print_lock(prev);
+       printk("which would create a new lock dependency:\n");
+       print_lock_name(prev->class);
+       printk(" ->");
+       print_lock_name(next->class);
+       printk("\n");
+
+       printk("\nbut this new dependency connects a %s-irq-safe lock:\n",
+               irqclass);
+       print_lock_name(backwards_match);
+       printk("\n... which became %s-irq-safe at:\n", irqclass);
+
+       print_stack_trace(backwards_match->usage_traces + bit1, 1);
+
+       printk("\nto a %s-irq-unsafe lock:\n", irqclass);
+       print_lock_name(forwards_match);
+       printk("\n... which became %s-irq-unsafe at:\n", irqclass);
+       printk("...");
+
+       print_stack_trace(forwards_match->usage_traces + bit2, 1);
+
+       printk("\nother info that might help us debug this:\n\n");
+       lockdep_print_held_locks(curr);
+
+       printk("\nthe %s-irq-safe lock's dependencies:\n", irqclass);
+       print_lock_dependencies(backwards_match, 0);
+
+       printk("\nthe %s-irq-unsafe lock's dependencies:\n", irqclass);
+       print_lock_dependencies(forwards_match, 0);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+
+       return 0;
+}
+
+static int
+check_usage(struct task_struct *curr, struct held_lock *prev,
+           struct held_lock *next, enum lock_usage_bit bit_backwards,
+           enum lock_usage_bit bit_forwards, const char *irqclass)
+{
+       int ret;
+
+       find_usage_bit = bit_backwards;
+       /* fills in <backwards_match> */
+       ret = find_usage_backwards(prev->class, 0);
+       if (!ret || ret == 1)
+               return ret;
+
+       find_usage_bit = bit_forwards;
+       ret = find_usage_forwards(next->class, 0);
+       if (!ret || ret == 1)
+               return ret;
+       /* ret == 2 */
+       return print_bad_irq_dependency(curr, prev, next,
+                       bit_backwards, bit_forwards, irqclass);
+}
+
+#endif
+
+static int
+print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
+                  struct held_lock *next)
+{
+       debug_locks_off();
+       __raw_spin_unlock(&hash_lock);
+       if (debug_locks_silent)
+               return 0;
+
+       printk("\n=============================================\n");
+       printk(  "[ INFO: possible recursive locking detected ]\n");
+       print_kernel_version();
+       printk(  "---------------------------------------------\n");
+       printk("%s/%d is trying to acquire lock:\n",
+               curr->comm, curr->pid);
+       print_lock(next);
+       printk("\nbut task is already holding lock:\n");
+       print_lock(prev);
+
+       printk("\nother info that might help us debug this:\n");
+       lockdep_print_held_locks(curr);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+
+       return 0;
+}
+
+/*
+ * Check whether we are holding such a class already.
+ *
+ * (Note that this has to be done separately, because the graph cannot
+ * detect such classes of deadlocks.)
+ *
+ * Returns: 0 on deadlock detected, 1 on OK, 2 on recursive read
+ */
+static int
+check_deadlock(struct task_struct *curr, struct held_lock *next,
+              struct lockdep_map *next_instance, int read)
+{
+       struct held_lock *prev;
+       int i;
+
+       for (i = 0; i < curr->lockdep_depth; i++) {
+               prev = curr->held_locks + i;
+               if (prev->class != next->class)
+                       continue;
+               /*
+                * Allow read-after-read recursion of the same
+                * lock class (i.e. read_lock(lock)+read_lock(lock)):
+                */
+               if ((read == 2) && prev->read)
+                       return 2;
+               return print_deadlock_bug(curr, prev, next);
+       }
+       return 1;
+}
+
+/*
+ * There was a chain-cache miss, and we are about to add a new dependency
+ * to a previous lock. We recursively validate the following rules:
+ *
+ *  - would the adding of the <prev> -> <next> dependency create a
+ *    circular dependency in the graph? [== circular deadlock]
+ *
+ *  - does the new prev->next dependency connect any hardirq-safe lock
+ *    (in the full backwards-subgraph starting at <prev>) with any
+ *    hardirq-unsafe lock (in the full forwards-subgraph starting at
+ *    <next>)? [== illegal lock inversion with hardirq contexts]
+ *
+ *  - does the new prev->next dependency connect any softirq-safe lock
+ *    (in the full backwards-subgraph starting at <prev>) with any
+ *    softirq-unsafe lock (in the full forwards-subgraph starting at
+ *    <next>)? [== illegal lock inversion with softirq contexts]
+ *
+ * any of these scenarios could lead to a deadlock.
+ *
+ * Then if all the validations pass, we add the forwards and backwards
+ * dependency.
+ */
+static int
+check_prev_add(struct task_struct *curr, struct held_lock *prev,
+              struct held_lock *next)
+{
+       struct lock_list *entry;
+       int ret;
+
+       /*
+        * Prove that the new <prev> -> <next> dependency would not
+        * create a circular dependency in the graph. (We do this by
+        * forward-recursing into the graph starting at <next>, and
+        * checking whether we can reach <prev>.)
+        *
+        * We are using global variables to control the recursion, to
+        * keep the stackframe size of the recursive functions low:
+        */
+       check_source = next;
+       check_target = prev;
+       if (!(check_noncircular(next->class, 0)))
+               return print_circular_bug_tail();
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /*
+        * Prove that the new dependency does not connect a hardirq-safe
+        * lock with a hardirq-unsafe lock - to achieve this we search
+        * the backwards-subgraph starting at <prev>, and the
+        * forwards-subgraph starting at <next>:
+        */
+       if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ,
+                                       LOCK_ENABLED_HARDIRQS, "hard"))
+               return 0;
+
+       /*
+        * Prove that the new dependency does not connect a hardirq-safe-read
+        * lock with a hardirq-unsafe lock - to achieve this we search
+        * the backwards-subgraph starting at <prev>, and the
+        * forwards-subgraph starting at <next>:
+        */
+       if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ_READ,
+                                       LOCK_ENABLED_HARDIRQS, "hard-read"))
+               return 0;
+
+       /*
+        * Prove that the new dependency does not connect a softirq-safe
+        * lock with a softirq-unsafe lock - to achieve this we search
+        * the backwards-subgraph starting at <prev>, and the
+        * forwards-subgraph starting at <next>:
+        */
+       if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ,
+                                       LOCK_ENABLED_SOFTIRQS, "soft"))
+               return 0;
+       /*
+        * Prove that the new dependency does not connect a softirq-safe-read
+        * lock with a softirq-unsafe lock - to achieve this we search
+        * the backwards-subgraph starting at <prev>, and the
+        * forwards-subgraph starting at <next>:
+        */
+       if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ_READ,
+                                       LOCK_ENABLED_SOFTIRQS, "soft"))
+               return 0;
+#endif
+       /*
+        * For recursive read-locks we do all the dependency checks,
+        * but we dont store read-triggered dependencies (only
+        * write-triggered dependencies). This ensures that only the
+        * write-side dependencies matter, and that if for example a
+        * write-lock never takes any other locks, then the reads are
+        * equivalent to a NOP.
+        */
+       if (next->read == 2 || prev->read == 2)
+               return 1;
+       /*
+        * Is the <prev> -> <next> dependency already present?
+        *
+        * (this may occur even though this is a new chain: consider
+        *  e.g. the L1 -> L2 -> L3 -> L4 and the L5 -> L1 -> L2 -> L3
+        *  chains - the second one will be new, but L1 already has
+        *  L2 added to its dependency list, due to the first chain.)
+        */
+       list_for_each_entry(entry, &prev->class->locks_after, entry) {
+               if (entry->class == next->class)
+                       return 2;
+       }
+
+       /*
+        * Ok, all validations passed, add the new lock
+        * to the previous lock's dependency list:
+        */
+       ret = add_lock_to_list(prev->class, next->class,
+                              &prev->class->locks_after, next->acquire_ip);
+       if (!ret)
+               return 0;
+       /*
+        * Return value of 2 signals 'dependency already added',
+        * in that case we dont have to add the backlink either.
+        */
+       if (ret == 2)
+               return 2;
+       ret = add_lock_to_list(next->class, prev->class,
+                              &next->class->locks_before, next->acquire_ip);
+
+       /*
+        * Debugging printouts:
+        */
+       if (verbose(prev->class) || verbose(next->class)) {
+               __raw_spin_unlock(&hash_lock);
+               printk("\n new dependency: ");
+               print_lock_name(prev->class);
+               printk(" => ");
+               print_lock_name(next->class);
+               printk("\n");
+               dump_stack();
+               __raw_spin_lock(&hash_lock);
+       }
+       return 1;
+}
+
+/*
+ * Add the dependency to all directly-previous locks that are 'relevant'.
+ * The ones that are relevant are (in increasing distance from curr):
+ * all consecutive trylock entries and the final non-trylock entry - or
+ * the end of this context's lock-chain - whichever comes first.
+ */
+static int
+check_prevs_add(struct task_struct *curr, struct held_lock *next)
+{
+       int depth = curr->lockdep_depth;
+       struct held_lock *hlock;
+
+       /*
+        * Debugging checks.
+        *
+        * Depth must not be zero for a non-head lock:
+        */
+       if (!depth)
+               goto out_bug;
+       /*
+        * At least two relevant locks must exist for this
+        * to be a head:
+        */
+       if (curr->held_locks[depth].irq_context !=
+                       curr->held_locks[depth-1].irq_context)
+               goto out_bug;
+
+       for (;;) {
+               hlock = curr->held_locks + depth-1;
+               /*
+                * Only non-recursive-read entries get new dependencies
+                * added:
+                */
+               if (hlock->read != 2) {
+                       check_prev_add(curr, hlock, next);
+                       /*
+                        * Stop after the first non-trylock entry,
+                        * as non-trylock entries have added their
+                        * own direct dependencies already, so this
+                        * lock is connected to them indirectly:
+                        */
+                       if (!hlock->trylock)
+                               break;
+               }
+               depth--;
+               /*
+                * End of lock-stack?
+                */
+               if (!depth)
+                       break;
+               /*
+                * Stop the search if we cross into another context:
+                */
+               if (curr->held_locks[depth].irq_context !=
+                               curr->held_locks[depth-1].irq_context)
+                       break;
+       }
+       return 1;
+out_bug:
+       __raw_spin_unlock(&hash_lock);
+       DEBUG_LOCKS_WARN_ON(1);
+
+       return 0;
+}
+
+
+/*
+ * Is this the address of a static object:
+ */
+static int static_obj(void *obj)
+{
+       unsigned long start = (unsigned long) &_stext,
+                     end   = (unsigned long) &_end,
+                     addr  = (unsigned long) obj;
+#ifdef CONFIG_SMP
+       int i;
+#endif
+
+       /*
+        * static variable?
+        */
+       if ((addr >= start) && (addr < end))
+               return 1;
+
+#ifdef CONFIG_SMP
+       /*
+        * percpu var?
+        */
+       for_each_possible_cpu(i) {
+               start = (unsigned long) &__per_cpu_start + per_cpu_offset(i);
+               end   = (unsigned long) &__per_cpu_end   + per_cpu_offset(i);
+
+               if ((addr >= start) && (addr < end))
+                       return 1;
+       }
+#endif
+
+       /*
+        * module var?
+        */
+       return is_module_address(addr);
+}
+
+/*
+ * To make lock name printouts unique, we calculate a unique
+ * class->name_version generation counter:
+ */
+static int count_matching_names(struct lock_class *new_class)
+{
+       struct lock_class *class;
+       int count = 0;
+
+       if (!new_class->name)
+               return 0;
+
+       list_for_each_entry(class, &all_lock_classes, lock_entry) {
+               if (new_class->key - new_class->subclass == class->key)
+                       return class->name_version;
+               if (class->name && !strcmp(class->name, new_class->name))
+                       count = max(count, class->name_version);
+       }
+
+       return count + 1;
+}
+
+extern void __error_too_big_MAX_LOCKDEP_SUBCLASSES(void);
+
+/*
+ * Register a lock's class in the hash-table, if the class is not present
+ * yet. Otherwise we look it up. We cache the result in the lock object
+ * itself, so actual lookup of the hash should be once per lock object.
+ */
+static inline struct lock_class *
+look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
+{
+       struct lockdep_subclass_key *key;
+       struct list_head *hash_head;
+       struct lock_class *class;
+
+#ifdef CONFIG_DEBUG_LOCKDEP
+       /*
+        * If the architecture calls into lockdep before initializing
+        * the hashes then we'll warn about it later. (we cannot printk
+        * right now)
+        */
+       if (unlikely(!lockdep_initialized)) {
+               lockdep_init();
+               lockdep_init_error = 1;
+       }
+#endif
+
+       /*
+        * Static locks do not have their class-keys yet - for them the key
+        * is the lock object itself:
+        */
+       if (unlikely(!lock->key))
+               lock->key = (void *)lock;
+
+       /*
+        * NOTE: the class-key must be unique. For dynamic locks, a static
+        * lock_class_key variable is passed in through the mutex_init()
+        * (or spin_lock_init()) call - which acts as the key. For static
+        * locks we use the lock object itself as the key.
+        */
+       if (sizeof(struct lock_class_key) > sizeof(struct lock_class))
+               __error_too_big_MAX_LOCKDEP_SUBCLASSES();
+
+       key = lock->key->subkeys + subclass;
+
+       hash_head = classhashentry(key);
+
+       /*
+        * We can walk the hash lockfree, because the hash only
+        * grows, and we are careful when adding entries to the end:
+        */
+       list_for_each_entry(class, hash_head, hash_entry)
+               if (class->key == key)
+                       return class;
+
+       return NULL;
+}
+
+/*
+ * Register a lock's class in the hash-table, if the class is not present
+ * yet. Otherwise we look it up. We cache the result in the lock object
+ * itself, so actual lookup of the hash should be once per lock object.
+ */
+static inline struct lock_class *
+register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force)
+{
+       struct lockdep_subclass_key *key;
+       struct list_head *hash_head;
+       struct lock_class *class;
+
+       class = look_up_lock_class(lock, subclass);
+       if (likely(class))
+               return class;
+
+       /*
+        * Debug-check: all keys must be persistent!
+        */
+       if (!static_obj(lock->key)) {
+               debug_locks_off();
+               printk("INFO: trying to register non-static key.\n");
+               printk("the code is fine but needs lockdep annotation.\n");
+               printk("turning off the locking correctness validator.\n");
+               dump_stack();
+
+               return NULL;
+       }
+
+       key = lock->key->subkeys + subclass;
+       hash_head = classhashentry(key);
+
+       __raw_spin_lock(&hash_lock);
+       /*
+        * We have to do the hash-walk again, to avoid races
+        * with another CPU:
+        */
+       list_for_each_entry(class, hash_head, hash_entry)
+               if (class->key == key)
+                       goto out_unlock_set;
+       /*
+        * Allocate a new key from the static array, and add it to
+        * the hash:
+        */
+       if (nr_lock_classes >= MAX_LOCKDEP_KEYS) {
+               __raw_spin_unlock(&hash_lock);
+               debug_locks_off();
+               printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
+               printk("turning off the locking correctness validator.\n");
+               return NULL;
+       }
+       class = lock_classes + nr_lock_classes++;
+       debug_atomic_inc(&nr_unused_locks);
+       class->key = key;
+       class->name = lock->name;
+       class->subclass = subclass;
+       INIT_LIST_HEAD(&class->lock_entry);
+       INIT_LIST_HEAD(&class->locks_before);
+       INIT_LIST_HEAD(&class->locks_after);
+       class->name_version = count_matching_names(class);
+       /*
+        * We use RCU's safe list-add method to make
+        * parallel walking of the hash-list safe:
+        */
+       list_add_tail_rcu(&class->hash_entry, hash_head);
+
+       if (verbose(class)) {
+               __raw_spin_unlock(&hash_lock);
+               printk("\nnew class %p: %s", class->key, class->name);
+               if (class->name_version > 1)
+                       printk("#%d", class->name_version);
+               printk("\n");
+               dump_stack();
+               __raw_spin_lock(&hash_lock);
+       }
+out_unlock_set:
+       __raw_spin_unlock(&hash_lock);
+
+       if (!subclass || force)
+               lock->class_cache = class;
+
+       DEBUG_LOCKS_WARN_ON(class->subclass != subclass);
+
+       return class;
+}
+
+/*
+ * Look up a dependency chain. If the key is not present yet then
+ * add it and return 0 - in this case the new dependency chain is
+ * validated. If the key is already hashed, return 1.
+ */
+static inline int lookup_chain_cache(u64 chain_key)
+{
+       struct list_head *hash_head = chainhashentry(chain_key);
+       struct lock_chain *chain;
+
+       DEBUG_LOCKS_WARN_ON(!irqs_disabled());
+       /*
+        * We can walk it lock-free, because entries only get added
+        * to the hash:
+        */
+       list_for_each_entry(chain, hash_head, entry) {
+               if (chain->chain_key == chain_key) {
+cache_hit:
+                       debug_atomic_inc(&chain_lookup_hits);
+                       /*
+                        * In the debugging case, force redundant checking
+                        * by returning 1:
+                        */
+#ifdef CONFIG_DEBUG_LOCKDEP
+                       __raw_spin_lock(&hash_lock);
+                       return 1;
+#endif
+                       return 0;
+               }
+       }
+       /*
+        * Allocate a new chain entry from the static array, and add
+        * it to the hash:
+        */
+       __raw_spin_lock(&hash_lock);
+       /*
+        * We have to walk the chain again locked - to avoid duplicates:
+        */
+       list_for_each_entry(chain, hash_head, entry) {
+               if (chain->chain_key == chain_key) {
+                       __raw_spin_unlock(&hash_lock);
+                       goto cache_hit;
+               }
+       }
+       if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) {
+               __raw_spin_unlock(&hash_lock);
+               debug_locks_off();
+               printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
+               printk("turning off the locking correctness validator.\n");
+               return 0;
+       }
+       chain = lock_chains + nr_lock_chains++;
+       chain->chain_key = chain_key;
+       list_add_tail_rcu(&chain->entry, hash_head);
+       debug_atomic_inc(&chain_lookup_misses);
+#ifdef CONFIG_TRACE_IRQFLAGS
+       if (current->hardirq_context)
+               nr_hardirq_chains++;
+       else {
+               if (current->softirq_context)
+                       nr_softirq_chains++;
+               else
+                       nr_process_chains++;
+       }
+#else
+       nr_process_chains++;
+#endif
+
+       return 1;
+}
+
+/*
+ * We are building curr_chain_key incrementally, so double-check
+ * it from scratch, to make sure that it's done correctly:
+ */
+static void check_chain_key(struct task_struct *curr)
+{
+#ifdef CONFIG_DEBUG_LOCKDEP
+       struct held_lock *hlock, *prev_hlock = NULL;
+       unsigned int i, id;
+       u64 chain_key = 0;
+
+       for (i = 0; i < curr->lockdep_depth; i++) {
+               hlock = curr->held_locks + i;
+               if (chain_key != hlock->prev_chain_key) {
+                       debug_locks_off();
+                       printk("hm#1, depth: %u [%u], %016Lx != %016Lx\n",
+                               curr->lockdep_depth, i,
+                               (unsigned long long)chain_key,
+                               (unsigned long long)hlock->prev_chain_key);
+                       WARN_ON(1);
+                       return;
+               }
+               id = hlock->class - lock_classes;
+               DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS);
+               if (prev_hlock && (prev_hlock->irq_context !=
+                                                       hlock->irq_context))
+                       chain_key = 0;
+               chain_key = iterate_chain_key(chain_key, id);
+               prev_hlock = hlock;
+       }
+       if (chain_key != curr->curr_chain_key) {
+               debug_locks_off();
+               printk("hm#2, depth: %u [%u], %016Lx != %016Lx\n",
+                       curr->lockdep_depth, i,
+                       (unsigned long long)chain_key,
+                       (unsigned long long)curr->curr_chain_key);
+               WARN_ON(1);
+       }
+#endif
+}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+/*
+ * print irq inversion bug:
+ */
+static int
+print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other,
+                       struct held_lock *this, int forwards,
+                       const char *irqclass)
+{
+       __raw_spin_unlock(&hash_lock);
+       debug_locks_off();
+       if (debug_locks_silent)
+               return 0;
+
+       printk("\n=========================================================\n");
+       printk(  "[ INFO: possible irq lock inversion dependency detected ]\n");
+       print_kernel_version();
+       printk(  "---------------------------------------------------------\n");
+       printk("%s/%d just changed the state of lock:\n",
+               curr->comm, curr->pid);
+       print_lock(this);
+       if (forwards)
+               printk("but this lock took another, %s-irq-unsafe lock in the past:\n", irqclass);
+       else
+               printk("but this lock was taken by another, %s-irq-safe lock in the past:\n", irqclass);
+       print_lock_name(other);
+       printk("\n\nand interrupts could create inverse lock ordering between them.\n\n");
+
+       printk("\nother info that might help us debug this:\n");
+       lockdep_print_held_locks(curr);
+
+       printk("\nthe first lock's dependencies:\n");
+       print_lock_dependencies(this->class, 0);
+
+       printk("\nthe second lock's dependencies:\n");
+       print_lock_dependencies(other, 0);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+
+       return 0;
+}
+
+/*
+ * Prove that in the forwards-direction subgraph starting at <this>
+ * there is no lock matching <mask>:
+ */
+static int
+check_usage_forwards(struct task_struct *curr, struct held_lock *this,
+                    enum lock_usage_bit bit, const char *irqclass)
+{
+       int ret;
+
+       find_usage_bit = bit;
+       /* fills in <forwards_match> */
+       ret = find_usage_forwards(this->class, 0);
+       if (!ret || ret == 1)
+               return ret;
+
+       return print_irq_inversion_bug(curr, forwards_match, this, 1, irqclass);
+}
+
+/*
+ * Prove that in the backwards-direction subgraph starting at <this>
+ * there is no lock matching <mask>:
+ */
+static int
+check_usage_backwards(struct task_struct *curr, struct held_lock *this,
+                     enum lock_usage_bit bit, const char *irqclass)
+{
+       int ret;
+
+       find_usage_bit = bit;
+       /* fills in <backwards_match> */
+       ret = find_usage_backwards(this->class, 0);
+       if (!ret || ret == 1)
+               return ret;
+
+       return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass);
+}
+
+static inline void print_irqtrace_events(struct task_struct *curr)
+{
+       printk("irq event stamp: %u\n", curr->irq_events);
+       printk("hardirqs last  enabled at (%u): ", curr->hardirq_enable_event);
+       print_ip_sym(curr->hardirq_enable_ip);
+       printk("hardirqs last disabled at (%u): ", curr->hardirq_disable_event);
+       print_ip_sym(curr->hardirq_disable_ip);
+       printk("softirqs last  enabled at (%u): ", curr->softirq_enable_event);
+       print_ip_sym(curr->softirq_enable_ip);
+       printk("softirqs last disabled at (%u): ", curr->softirq_disable_event);
+       print_ip_sym(curr->softirq_disable_ip);
+}
+
+#else
+static inline void print_irqtrace_events(struct task_struct *curr)
+{
+}
+#endif
+
+static int
+print_usage_bug(struct task_struct *curr, struct held_lock *this,
+               enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit)
+{
+       __raw_spin_unlock(&hash_lock);
+       debug_locks_off();
+       if (debug_locks_silent)
+               return 0;
+
+       printk("\n=================================\n");
+       printk(  "[ INFO: inconsistent lock state ]\n");
+       print_kernel_version();
+       printk(  "---------------------------------\n");
+
+       printk("inconsistent {%s} -> {%s} usage.\n",
+               usage_str[prev_bit], usage_str[new_bit]);
+
+       printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] takes:\n",
+               curr->comm, curr->pid,
+               trace_hardirq_context(curr), hardirq_count() >> HARDIRQ_SHIFT,
+               trace_softirq_context(curr), softirq_count() >> SOFTIRQ_SHIFT,
+               trace_hardirqs_enabled(curr),
+               trace_softirqs_enabled(curr));
+       print_lock(this);
+
+       printk("{%s} state was registered at:\n", usage_str[prev_bit]);
+       print_stack_trace(this->class->usage_traces + prev_bit, 1);
+
+       print_irqtrace_events(curr);
+       printk("\nother info that might help us debug this:\n");
+       lockdep_print_held_locks(curr);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+
+       return 0;
+}
+
+/*
+ * Print out an error if an invalid bit is set:
+ */
+static inline int
+valid_state(struct task_struct *curr, struct held_lock *this,
+           enum lock_usage_bit new_bit, enum lock_usage_bit bad_bit)
+{
+       if (unlikely(this->class->usage_mask & (1 << bad_bit)))
+               return print_usage_bug(curr, this, bad_bit, new_bit);
+       return 1;
+}
+
+#define STRICT_READ_CHECKS     1
+
+/*
+ * Mark a lock with a usage bit, and validate the state transition:
+ */
+static int mark_lock(struct task_struct *curr, struct held_lock *this,
+                    enum lock_usage_bit new_bit, unsigned long ip)
+{
+       unsigned int new_mask = 1 << new_bit, ret = 1;
+
+       /*
+        * If already set then do not dirty the cacheline,
+        * nor do any checks:
+        */
+       if (likely(this->class->usage_mask & new_mask))
+               return 1;
+
+       __raw_spin_lock(&hash_lock);
+       /*
+        * Make sure we didnt race:
+        */
+       if (unlikely(this->class->usage_mask & new_mask)) {
+               __raw_spin_unlock(&hash_lock);
+               return 1;
+       }
+
+       this->class->usage_mask |= new_mask;
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+       if (new_bit == LOCK_ENABLED_HARDIRQS ||
+                       new_bit == LOCK_ENABLED_HARDIRQS_READ)
+               ip = curr->hardirq_enable_ip;
+       else if (new_bit == LOCK_ENABLED_SOFTIRQS ||
+                       new_bit == LOCK_ENABLED_SOFTIRQS_READ)
+               ip = curr->softirq_enable_ip;
+#endif
+       if (!save_trace(this->class->usage_traces + new_bit))
+               return 0;
+
+       switch (new_bit) {
+#ifdef CONFIG_TRACE_IRQFLAGS
+       case LOCK_USED_IN_HARDIRQ:
+               if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS))
+                       return 0;
+               if (!valid_state(curr, this, new_bit,
+                                LOCK_ENABLED_HARDIRQS_READ))
+                       return 0;
+               /*
+                * just marked it hardirq-safe, check that this lock
+                * took no hardirq-unsafe lock in the past:
+                */
+               if (!check_usage_forwards(curr, this,
+                                         LOCK_ENABLED_HARDIRQS, "hard"))
+                       return 0;
+#if STRICT_READ_CHECKS
+               /*
+                * just marked it hardirq-safe, check that this lock
+                * took no hardirq-unsafe-read lock in the past:
+                */
+               if (!check_usage_forwards(curr, this,
+                               LOCK_ENABLED_HARDIRQS_READ, "hard-read"))
+                       return 0;
+#endif
+               if (hardirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_USED_IN_SOFTIRQ:
+               if (!valid_state(curr, this, new_bit, LOCK_ENABLED_SOFTIRQS))
+                       return 0;
+               if (!valid_state(curr, this, new_bit,
+                                LOCK_ENABLED_SOFTIRQS_READ))
+                       return 0;
+               /*
+                * just marked it softirq-safe, check that this lock
+                * took no softirq-unsafe lock in the past:
+                */
+               if (!check_usage_forwards(curr, this,
+                                         LOCK_ENABLED_SOFTIRQS, "soft"))
+                       return 0;
+#if STRICT_READ_CHECKS
+               /*
+                * just marked it softirq-safe, check that this lock
+                * took no softirq-unsafe-read lock in the past:
+                */
+               if (!check_usage_forwards(curr, this,
+                               LOCK_ENABLED_SOFTIRQS_READ, "soft-read"))
+                       return 0;
+#endif
+               if (softirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_USED_IN_HARDIRQ_READ:
+               if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS))
+                       return 0;
+               /*
+                * just marked it hardirq-read-safe, check that this lock
+                * took no hardirq-unsafe lock in the past:
+                */
+               if (!check_usage_forwards(curr, this,
+                                         LOCK_ENABLED_HARDIRQS, "hard"))
+                       return 0;
+               if (hardirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_USED_IN_SOFTIRQ_READ:
+               if (!valid_state(curr, this, new_bit, LOCK_ENABLED_SOFTIRQS))
+                       return 0;
+               /*
+                * just marked it softirq-read-safe, check that this lock
+                * took no softirq-unsafe lock in the past:
+                */
+               if (!check_usage_forwards(curr, this,
+                                         LOCK_ENABLED_SOFTIRQS, "soft"))
+                       return 0;
+               if (softirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_ENABLED_HARDIRQS:
+               if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ))
+                       return 0;
+               if (!valid_state(curr, this, new_bit,
+                                LOCK_USED_IN_HARDIRQ_READ))
+                       return 0;
+               /*
+                * just marked it hardirq-unsafe, check that no hardirq-safe
+                * lock in the system ever took it in the past:
+                */
+               if (!check_usage_backwards(curr, this,
+                                          LOCK_USED_IN_HARDIRQ, "hard"))
+                       return 0;
+#if STRICT_READ_CHECKS
+               /*
+                * just marked it hardirq-unsafe, check that no
+                * hardirq-safe-read lock in the system ever took
+                * it in the past:
+                */
+               if (!check_usage_backwards(curr, this,
+                                  LOCK_USED_IN_HARDIRQ_READ, "hard-read"))
+                       return 0;
+#endif
+               if (hardirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_ENABLED_SOFTIRQS:
+               if (!valid_state(curr, this, new_bit, LOCK_USED_IN_SOFTIRQ))
+                       return 0;
+               if (!valid_state(curr, this, new_bit,
+                                LOCK_USED_IN_SOFTIRQ_READ))
+                       return 0;
+               /*
+                * just marked it softirq-unsafe, check that no softirq-safe
+                * lock in the system ever took it in the past:
+                */
+               if (!check_usage_backwards(curr, this,
+                                          LOCK_USED_IN_SOFTIRQ, "soft"))
+                       return 0;
+#if STRICT_READ_CHECKS
+               /*
+                * just marked it softirq-unsafe, check that no
+                * softirq-safe-read lock in the system ever took
+                * it in the past:
+                */
+               if (!check_usage_backwards(curr, this,
+                                  LOCK_USED_IN_SOFTIRQ_READ, "soft-read"))
+                       return 0;
+#endif
+               if (softirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_ENABLED_HARDIRQS_READ:
+               if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ))
+                       return 0;
+#if STRICT_READ_CHECKS
+               /*
+                * just marked it hardirq-read-unsafe, check that no
+                * hardirq-safe lock in the system ever took it in the past:
+                */
+               if (!check_usage_backwards(curr, this,
+                                          LOCK_USED_IN_HARDIRQ, "hard"))
+                       return 0;
+#endif
+               if (hardirq_verbose(this->class))
+                       ret = 2;
+               break;
+       case LOCK_ENABLED_SOFTIRQS_READ:
+               if (!valid_state(curr, this, new_bit, LOCK_USED_IN_SOFTIRQ))
+                       return 0;
+#if STRICT_READ_CHECKS
+               /*
+                * just marked it softirq-read-unsafe, check that no
+                * softirq-safe lock in the system ever took it in the past:
+                */
+               if (!check_usage_backwards(curr, this,
+                                          LOCK_USED_IN_SOFTIRQ, "soft"))
+                       return 0;
+#endif
+               if (softirq_verbose(this->class))
+                       ret = 2;
+               break;
+#endif
+       case LOCK_USED:
+               /*
+                * Add it to the global list of classes:
+                */
+               list_add_tail_rcu(&this->class->lock_entry, &all_lock_classes);
+               debug_atomic_dec(&nr_unused_locks);
+               break;
+       default:
+               debug_locks_off();
+               WARN_ON(1);
+               return 0;
+       }
+
+       __raw_spin_unlock(&hash_lock);
+
+       /*
+        * We must printk outside of the hash_lock:
+        */
+       if (ret == 2) {
+               printk("\nmarked lock as {%s}:\n", usage_str[new_bit]);
+               print_lock(this);
+               print_irqtrace_events(curr);
+               dump_stack();
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+/*
+ * Mark all held locks with a usage bit:
+ */
+static int
+mark_held_locks(struct task_struct *curr, int hardirq, unsigned long ip)
+{
+       enum lock_usage_bit usage_bit;
+       struct held_lock *hlock;
+       int i;
+
+       for (i = 0; i < curr->lockdep_depth; i++) {
+               hlock = curr->held_locks + i;
+
+               if (hardirq) {
+                       if (hlock->read)
+                               usage_bit = LOCK_ENABLED_HARDIRQS_READ;
+                       else
+                               usage_bit = LOCK_ENABLED_HARDIRQS;
+               } else {
+                       if (hlock->read)
+                               usage_bit = LOCK_ENABLED_SOFTIRQS_READ;
+                       else
+                               usage_bit = LOCK_ENABLED_SOFTIRQS;
+               }
+               if (!mark_lock(curr, hlock, usage_bit, ip))
+                       return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * Debugging helper: via this flag we know that we are in
+ * 'early bootup code', and will warn about any invalid irqs-on event:
+ */
+static int early_boot_irqs_enabled;
+
+void early_boot_irqs_off(void)
+{
+       early_boot_irqs_enabled = 0;
+}
+
+void early_boot_irqs_on(void)
+{
+       early_boot_irqs_enabled = 1;
+}
+
+/*
+ * Hardirqs will be enabled:
+ */
+void trace_hardirqs_on(void)
+{
+       struct task_struct *curr = current;
+       unsigned long ip;
+
+       if (unlikely(!debug_locks || current->lockdep_recursion))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(unlikely(!early_boot_irqs_enabled)))
+               return;
+
+       if (unlikely(curr->hardirqs_enabled)) {
+               debug_atomic_inc(&redundant_hardirqs_on);
+               return;
+       }
+       /* we'll do an OFF -> ON transition: */
+       curr->hardirqs_enabled = 1;
+       ip = (unsigned long) __builtin_return_address(0);
+
+       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+               return;
+       if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
+               return;
+       /*
+        * We are going to turn hardirqs on, so set the
+        * usage bit for all held locks:
+        */
+       if (!mark_held_locks(curr, 1, ip))
+               return;
+       /*
+        * If we have softirqs enabled, then set the usage
+        * bit for all held locks. (disabled hardirqs prevented
+        * this bit from being set before)
+        */
+       if (curr->softirqs_enabled)
+               if (!mark_held_locks(curr, 0, ip))
+                       return;
+
+       curr->hardirq_enable_ip = ip;
+       curr->hardirq_enable_event = ++curr->irq_events;
+       debug_atomic_inc(&hardirqs_on_events);
+}
+
+EXPORT_SYMBOL(trace_hardirqs_on);
+
+/*
+ * Hardirqs were disabled:
+ */
+void trace_hardirqs_off(void)
+{
+       struct task_struct *curr = current;
+
+       if (unlikely(!debug_locks || current->lockdep_recursion))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+               return;
+
+       if (curr->hardirqs_enabled) {
+               /*
+                * We have done an ON -> OFF transition:
+                */
+               curr->hardirqs_enabled = 0;
+               curr->hardirq_disable_ip = _RET_IP_;
+               curr->hardirq_disable_event = ++curr->irq_events;
+               debug_atomic_inc(&hardirqs_off_events);
+       } else
+               debug_atomic_inc(&redundant_hardirqs_off);
+}
+
+EXPORT_SYMBOL(trace_hardirqs_off);
+
+/*
+ * Softirqs will be enabled:
+ */
+void trace_softirqs_on(unsigned long ip)
+{
+       struct task_struct *curr = current;
+
+       if (unlikely(!debug_locks))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+               return;
+
+       if (curr->softirqs_enabled) {
+               debug_atomic_inc(&redundant_softirqs_on);
+               return;
+       }
+
+       /*
+        * We'll do an OFF -> ON transition:
+        */
+       curr->softirqs_enabled = 1;
+       curr->softirq_enable_ip = ip;
+       curr->softirq_enable_event = ++curr->irq_events;
+       debug_atomic_inc(&softirqs_on_events);
+       /*
+        * We are going to turn softirqs on, so set the
+        * usage bit for all held locks, if hardirqs are
+        * enabled too:
+        */
+       if (curr->hardirqs_enabled)
+               mark_held_locks(curr, 0, ip);
+}
+
+/*
+ * Softirqs were disabled:
+ */
+void trace_softirqs_off(unsigned long ip)
+{
+       struct task_struct *curr = current;
+
+       if (unlikely(!debug_locks))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+               return;
+
+       if (curr->softirqs_enabled) {
+               /*
+                * We have done an ON -> OFF transition:
+                */
+               curr->softirqs_enabled = 0;
+               curr->softirq_disable_ip = ip;
+               curr->softirq_disable_event = ++curr->irq_events;
+               debug_atomic_inc(&softirqs_off_events);
+               DEBUG_LOCKS_WARN_ON(!softirq_count());
+       } else
+               debug_atomic_inc(&redundant_softirqs_off);
+}
+
+#endif
+
+/*
+ * Initialize a lock instance's lock-class mapping info:
+ */
+void lockdep_init_map(struct lockdep_map *lock, const char *name,
+                     struct lock_class_key *key, int subclass)
+{
+       if (unlikely(!debug_locks))
+               return;
+
+       if (DEBUG_LOCKS_WARN_ON(!key))
+               return;
+       if (DEBUG_LOCKS_WARN_ON(!name))
+               return;
+       /*
+        * Sanity check, the lock-class key must be persistent:
+        */
+       if (!static_obj(key)) {
+               printk("BUG: key %p not in .data!\n", key);
+               DEBUG_LOCKS_WARN_ON(1);
+               return;
+       }
+       lock->name = name;
+       lock->key = key;
+       lock->class_cache = NULL;
+       if (subclass)
+               register_lock_class(lock, subclass, 1);
+}
+
+EXPORT_SYMBOL_GPL(lockdep_init_map);
+
+/*
+ * This gets called for every mutex_lock*()/spin_lock*() operation.
+ * We maintain the dependency maps and validate the locking attempt:
+ */
+static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+                         int trylock, int read, int check, int hardirqs_off,
+                         unsigned long ip)
+{
+       struct task_struct *curr = current;
+       struct lock_class *class = NULL;
+       struct held_lock *hlock;
+       unsigned int depth, id;
+       int chain_head = 0;
+       u64 chain_key;
+
+       if (unlikely(!debug_locks))
+               return 0;
+
+       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+               return 0;
+
+       if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
+               debug_locks_off();
+               printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n");
+               printk("turning off the locking correctness validator.\n");
+               return 0;
+       }
+
+       if (!subclass)
+               class = lock->class_cache;
+       /*
+        * Not cached yet or subclass?
+        */
+       if (unlikely(!class)) {
+               class = register_lock_class(lock, subclass, 0);
+               if (!class)
+                       return 0;
+       }
+       debug_atomic_inc((atomic_t *)&class->ops);
+       if (very_verbose(class)) {
+               printk("\nacquire class [%p] %s", class->key, class->name);
+               if (class->name_version > 1)
+                       printk("#%d", class->name_version);
+               printk("\n");
+               dump_stack();
+       }
+
+       /*
+        * Add the lock to the list of currently held locks.
+        * (we dont increase the depth just yet, up until the
+        * dependency checks are done)
+        */
+       depth = curr->lockdep_depth;
+       if (DEBUG_LOCKS_WARN_ON(depth >= MAX_LOCK_DEPTH))
+               return 0;
+
+       hlock = curr->held_locks + depth;
+
+       hlock->class = class;
+       hlock->acquire_ip = ip;
+       hlock->instance = lock;
+       hlock->trylock = trylock;
+       hlock->read = read;
+       hlock->check = check;
+       hlock->hardirqs_off = hardirqs_off;
+
+       if (check != 2)
+               goto out_calc_hash;
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /*
+        * If non-trylock use in a hardirq or softirq context, then
+        * mark the lock as used in these contexts:
+        */
+       if (!trylock) {
+               if (read) {
+                       if (curr->hardirq_context)
+                               if (!mark_lock(curr, hlock,
+                                               LOCK_USED_IN_HARDIRQ_READ, ip))
+                                       return 0;
+                       if (curr->softirq_context)
+                               if (!mark_lock(curr, hlock,
+                                               LOCK_USED_IN_SOFTIRQ_READ, ip))
+                                       return 0;
+               } else {
+                       if (curr->hardirq_context)
+                               if (!mark_lock(curr, hlock, LOCK_USED_IN_HARDIRQ, ip))
+                                       return 0;
+                       if (curr->softirq_context)
+                               if (!mark_lock(curr, hlock, LOCK_USED_IN_SOFTIRQ, ip))
+                                       return 0;
+               }
+       }
+       if (!hardirqs_off) {
+               if (read) {
+                       if (!mark_lock(curr, hlock,
+                                       LOCK_ENABLED_HARDIRQS_READ, ip))
+                               return 0;
+                       if (curr->softirqs_enabled)
+                               if (!mark_lock(curr, hlock,
+                                               LOCK_ENABLED_SOFTIRQS_READ, ip))
+                                       return 0;
+               } else {
+                       if (!mark_lock(curr, hlock,
+                                       LOCK_ENABLED_HARDIRQS, ip))
+                               return 0;
+                       if (curr->softirqs_enabled)
+                               if (!mark_lock(curr, hlock,
+                                               LOCK_ENABLED_SOFTIRQS, ip))
+                                       return 0;
+               }
+       }
+#endif
+       /* mark it as used: */
+       if (!mark_lock(curr, hlock, LOCK_USED, ip))
+               return 0;
+out_calc_hash:
+       /*
+        * Calculate the chain hash: it's the combined has of all the
+        * lock keys along the dependency chain. We save the hash value
+        * at every step so that we can get the current hash easily
+        * after unlock. The chain hash is then used to cache dependency
+        * results.
+        *
+        * The 'key ID' is what is the most compact key value to drive
+        * the hash, not class->key.
+        */
+       id = class - lock_classes;
+       if (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
+               return 0;
+
+       chain_key = curr->curr_chain_key;
+       if (!depth) {
+               if (DEBUG_LOCKS_WARN_ON(chain_key != 0))
+                       return 0;
+               chain_head = 1;
+       }
+
+       hlock->prev_chain_key = chain_key;
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /*
+        * Keep track of points where we cross into an interrupt context:
+        */
+       hlock->irq_context = 2*(curr->hardirq_context ? 1 : 0) +
+                               curr->softirq_context;
+       if (depth) {
+               struct held_lock *prev_hlock;
+
+               prev_hlock = curr->held_locks + depth-1;
+               /*
+                * If we cross into another context, reset the
+                * hash key (this also prevents the checking and the
+                * adding of the dependency to 'prev'):
+                */
+               if (prev_hlock->irq_context != hlock->irq_context) {
+                       chain_key = 0;
+                       chain_head = 1;
+               }
+       }
+#endif
+       chain_key = iterate_chain_key(chain_key, id);
+       curr->curr_chain_key = chain_key;
+
+       /*
+        * Trylock needs to maintain the stack of held locks, but it
+        * does not add new dependencies, because trylock can be done
+        * in any order.
+        *
+        * We look up the chain_key and do the O(N^2) check and update of
+        * the dependencies only if this is a new dependency chain.
+        * (If lookup_chain_cache() returns with 1 it acquires
+        * hash_lock for us)
+        */
+       if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) {
+               /*
+                * Check whether last held lock:
+                *
+                * - is irq-safe, if this lock is irq-unsafe
+                * - is softirq-safe, if this lock is hardirq-unsafe
+                *
+                * And check whether the new lock's dependency graph
+                * could lead back to the previous lock.
+                *
+                * any of these scenarios could lead to a deadlock. If
+                * All validations
+                */
+               int ret = check_deadlock(curr, hlock, lock, read);
+
+               if (!ret)
+                       return 0;
+               /*
+                * Mark recursive read, as we jump over it when
+                * building dependencies (just like we jump over
+                * trylock entries):
+                */
+               if (ret == 2)
+                       hlock->read = 2;
+               /*
+                * Add dependency only if this lock is not the head
+                * of the chain, and if it's not a secondary read-lock:
+                */
+               if (!chain_head && ret != 2)
+                       if (!check_prevs_add(curr, hlock))
+                               return 0;
+               __raw_spin_unlock(&hash_lock);
+       }
+       curr->lockdep_depth++;
+       check_chain_key(curr);
+       if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) {
+               debug_locks_off();
+               printk("BUG: MAX_LOCK_DEPTH too low!\n");
+               printk("turning off the locking correctness validator.\n");
+               return 0;
+       }
+       if (unlikely(curr->lockdep_depth > max_lockdep_depth))
+               max_lockdep_depth = curr->lockdep_depth;
+
+       return 1;
+}
+
+static int
+print_unlock_inbalance_bug(struct task_struct *curr, struct lockdep_map *lock,
+                          unsigned long ip)
+{
+       if (!debug_locks_off())
+               return 0;
+       if (debug_locks_silent)
+               return 0;
+
+       printk("\n=====================================\n");
+       printk(  "[ BUG: bad unlock balance detected! ]\n");
+       printk(  "-------------------------------------\n");
+       printk("%s/%d is trying to release lock (",
+               curr->comm, curr->pid);
+       print_lockdep_cache(lock);
+       printk(") at:\n");
+       print_ip_sym(ip);
+       printk("but there are no more locks to release!\n");
+       printk("\nother info that might help us debug this:\n");
+       lockdep_print_held_locks(curr);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+
+       return 0;
+}
+
+/*
+ * Common debugging checks for both nested and non-nested unlock:
+ */
+static int check_unlock(struct task_struct *curr, struct lockdep_map *lock,
+                       unsigned long ip)
+{
+       if (unlikely(!debug_locks))
+               return 0;
+       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
+               return 0;
+
+       if (curr->lockdep_depth <= 0)
+               return print_unlock_inbalance_bug(curr, lock, ip);
+
+       return 1;
+}
+
+/*
+ * Remove the lock to the list of currently held locks in a
+ * potentially non-nested (out of order) manner. This is a
+ * relatively rare operation, as all the unlock APIs default
+ * to nested mode (which uses lock_release()):
+ */
+static int
+lock_release_non_nested(struct task_struct *curr,
+                       struct lockdep_map *lock, unsigned long ip)
+{
+       struct held_lock *hlock, *prev_hlock;
+       unsigned int depth;
+       int i;
+
+       /*
+        * Check whether the lock exists in the current stack
+        * of held locks:
+        */
+       depth = curr->lockdep_depth;
+       if (DEBUG_LOCKS_WARN_ON(!depth))
+               return 0;
+
+       prev_hlock = NULL;
+       for (i = depth-1; i >= 0; i--) {
+               hlock = curr->held_locks + i;
+               /*
+                * We must not cross into another context:
+                */
+               if (prev_hlock && prev_hlock->irq_context != hlock->irq_context)
+                       break;
+               if (hlock->instance == lock)
+                       goto found_it;
+               prev_hlock = hlock;
+       }
+       return print_unlock_inbalance_bug(curr, lock, ip);
+
+found_it:
+       /*
+        * We have the right lock to unlock, 'hlock' points to it.
+        * Now we remove it from the stack, and add back the other
+        * entries (if any), recalculating the hash along the way:
+        */
+       curr->lockdep_depth = i;
+       curr->curr_chain_key = hlock->prev_chain_key;
+
+       for (i++; i < depth; i++) {
+               hlock = curr->held_locks + i;
+               if (!__lock_acquire(hlock->instance,
+                       hlock->class->subclass, hlock->trylock,
+                               hlock->read, hlock->check, hlock->hardirqs_off,
+                               hlock->acquire_ip))
+                       return 0;
+       }
+
+       if (DEBUG_LOCKS_WARN_ON(curr->lockdep_depth != depth - 1))
+               return 0;
+       return 1;
+}
+
+/*
+ * Remove the lock to the list of currently held locks - this gets
+ * called on mutex_unlock()/spin_unlock*() (or on a failed
+ * mutex_lock_interruptible()). This is done for unlocks that nest
+ * perfectly. (i.e. the current top of the lock-stack is unlocked)
+ */
+static int lock_release_nested(struct task_struct *curr,
+                              struct lockdep_map *lock, unsigned long ip)
+{
+       struct held_lock *hlock;
+       unsigned int depth;
+
+       /*
+        * Pop off the top of the lock stack:
+        */
+       depth = curr->lockdep_depth - 1;
+       hlock = curr->held_locks + depth;
+
+       /*
+        * Is the unlock non-nested:
+        */
+       if (hlock->instance != lock)
+               return lock_release_non_nested(curr, lock, ip);
+       curr->lockdep_depth--;
+
+       if (DEBUG_LOCKS_WARN_ON(!depth && (hlock->prev_chain_key != 0)))
+               return 0;
+
+       curr->curr_chain_key = hlock->prev_chain_key;
+
+#ifdef CONFIG_DEBUG_LOCKDEP
+       hlock->prev_chain_key = 0;
+       hlock->class = NULL;
+       hlock->acquire_ip = 0;
+       hlock->irq_context = 0;
+#endif
+       return 1;
+}
+
+/*
+ * Remove the lock to the list of currently held locks - this gets
+ * called on mutex_unlock()/spin_unlock*() (or on a failed
+ * mutex_lock_interruptible()). This is done for unlocks that nest
+ * perfectly. (i.e. the current top of the lock-stack is unlocked)
+ */
+static void
+__lock_release(struct lockdep_map *lock, int nested, unsigned long ip)
+{
+       struct task_struct *curr = current;
+
+       if (!check_unlock(curr, lock, ip))
+               return;
+
+       if (nested) {
+               if (!lock_release_nested(curr, lock, ip))
+                       return;
+       } else {
+               if (!lock_release_non_nested(curr, lock, ip))
+                       return;
+       }
+
+       check_chain_key(curr);
+}
+
+/*
+ * Check whether we follow the irq-flags state precisely:
+ */
+static void check_flags(unsigned long flags)
+{
+#if defined(CONFIG_DEBUG_LOCKDEP) && defined(CONFIG_TRACE_IRQFLAGS)
+       if (!debug_locks)
+               return;
+
+       if (irqs_disabled_flags(flags))
+               DEBUG_LOCKS_WARN_ON(current->hardirqs_enabled);
+       else
+               DEBUG_LOCKS_WARN_ON(!current->hardirqs_enabled);
+
+       /*
+        * We dont accurately track softirq state in e.g.
+        * hardirq contexts (such as on 4KSTACKS), so only
+        * check if not in hardirq contexts:
+        */
+       if (!hardirq_count()) {
+               if (softirq_count())
+                       DEBUG_LOCKS_WARN_ON(current->softirqs_enabled);
+               else
+                       DEBUG_LOCKS_WARN_ON(!current->softirqs_enabled);
+       }
+
+       if (!debug_locks)
+               print_irqtrace_events(current);
+#endif
+}
+
+/*
+ * We are not always called with irqs disabled - do that here,
+ * and also avoid lockdep recursion:
+ */
+void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+                 int trylock, int read, int check, unsigned long ip)
+{
+       unsigned long flags;
+
+       if (unlikely(current->lockdep_recursion))
+               return;
+
+       raw_local_irq_save(flags);
+       check_flags(flags);
+
+       current->lockdep_recursion = 1;
+       __lock_acquire(lock, subclass, trylock, read, check,
+                      irqs_disabled_flags(flags), ip);
+       current->lockdep_recursion = 0;
+       raw_local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL_GPL(lock_acquire);
+
+void lock_release(struct lockdep_map *lock, int nested, unsigned long ip)
+{
+       unsigned long flags;
+
+       if (unlikely(current->lockdep_recursion))
+               return;
+
+       raw_local_irq_save(flags);
+       check_flags(flags);
+       current->lockdep_recursion = 1;
+       __lock_release(lock, nested, ip);
+       current->lockdep_recursion = 0;
+       raw_local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL_GPL(lock_release);
+
+/*
+ * Used by the testsuite, sanitize the validator state
+ * after a simulated failure:
+ */
+
+void lockdep_reset(void)
+{
+       unsigned long flags;
+
+       raw_local_irq_save(flags);
+       current->curr_chain_key = 0;
+       current->lockdep_depth = 0;
+       current->lockdep_recursion = 0;
+       memset(current->held_locks, 0, MAX_LOCK_DEPTH*sizeof(struct held_lock));
+       nr_hardirq_chains = 0;
+       nr_softirq_chains = 0;
+       nr_process_chains = 0;
+       debug_locks = 1;
+       raw_local_irq_restore(flags);
+}
+
+static void zap_class(struct lock_class *class)
+{
+       int i;
+
+       /*
+        * Remove all dependencies this lock is
+        * involved in:
+        */
+       for (i = 0; i < nr_list_entries; i++) {
+               if (list_entries[i].class == class)
+                       list_del_rcu(&list_entries[i].entry);
+       }
+       /*
+        * Unhash the class and remove it from the all_lock_classes list:
+        */
+       list_del_rcu(&class->hash_entry);
+       list_del_rcu(&class->lock_entry);
+
+}
+
+static inline int within(void *addr, void *start, unsigned long size)
+{
+       return addr >= start && addr < start + size;
+}
+
+void lockdep_free_key_range(void *start, unsigned long size)
+{
+       struct lock_class *class, *next;
+       struct list_head *head;
+       unsigned long flags;
+       int i;
+
+       raw_local_irq_save(flags);
+       __raw_spin_lock(&hash_lock);
+
+       /*
+        * Unhash all classes that were created by this module:
+        */
+       for (i = 0; i < CLASSHASH_SIZE; i++) {
+               head = classhash_table + i;
+               if (list_empty(head))
+                       continue;
+               list_for_each_entry_safe(class, next, head, hash_entry)
+                       if (within(class->key, start, size))
+                               zap_class(class);
+       }
+
+       __raw_spin_unlock(&hash_lock);
+       raw_local_irq_restore(flags);
+}
+
+void lockdep_reset_lock(struct lockdep_map *lock)
+{
+       struct lock_class *class, *next;
+       struct list_head *head;
+       unsigned long flags;
+       int i, j;
+
+       raw_local_irq_save(flags);
+
+       /*
+        * Remove all classes this lock might have:
+        */
+       for (j = 0; j < MAX_LOCKDEP_SUBCLASSES; j++) {
+               /*
+                * If the class exists we look it up and zap it:
+                */
+               class = look_up_lock_class(lock, j);
+               if (class)
+                       zap_class(class);
+       }
+       /*
+        * Debug check: in the end all mapped classes should
+        * be gone.
+        */
+       __raw_spin_lock(&hash_lock);
+       for (i = 0; i < CLASSHASH_SIZE; i++) {
+               head = classhash_table + i;
+               if (list_empty(head))
+                       continue;
+               list_for_each_entry_safe(class, next, head, hash_entry) {
+                       if (unlikely(class == lock->class_cache)) {
+                               __raw_spin_unlock(&hash_lock);
+                               DEBUG_LOCKS_WARN_ON(1);
+                               goto out_restore;
+                       }
+               }
+       }
+       __raw_spin_unlock(&hash_lock);
+
+out_restore:
+       raw_local_irq_restore(flags);
+}
+
+void __init lockdep_init(void)
+{
+       int i;
+
+       /*
+        * Some architectures have their own start_kernel()
+        * code which calls lockdep_init(), while we also
+        * call lockdep_init() from the start_kernel() itself,
+        * and we want to initialize the hashes only once:
+        */
+       if (lockdep_initialized)
+               return;
+
+       for (i = 0; i < CLASSHASH_SIZE; i++)
+               INIT_LIST_HEAD(classhash_table + i);
+
+       for (i = 0; i < CHAINHASH_SIZE; i++)
+               INIT_LIST_HEAD(chainhash_table + i);
+
+       lockdep_initialized = 1;
+}
+
+void __init lockdep_info(void)
+{
+       printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
+
+       printk("... MAX_LOCKDEP_SUBCLASSES:    %lu\n", MAX_LOCKDEP_SUBCLASSES);
+       printk("... MAX_LOCK_DEPTH:          %lu\n", MAX_LOCK_DEPTH);
+       printk("... MAX_LOCKDEP_KEYS:        %lu\n", MAX_LOCKDEP_KEYS);
+       printk("... CLASSHASH_SIZE:           %lu\n", CLASSHASH_SIZE);
+       printk("... MAX_LOCKDEP_ENTRIES:     %lu\n", MAX_LOCKDEP_ENTRIES);
+       printk("... MAX_LOCKDEP_CHAINS:      %lu\n", MAX_LOCKDEP_CHAINS);
+       printk("... CHAINHASH_SIZE:          %lu\n", CHAINHASH_SIZE);
+
+       printk(" memory used by lock dependency info: %lu kB\n",
+               (sizeof(struct lock_class) * MAX_LOCKDEP_KEYS +
+               sizeof(struct list_head) * CLASSHASH_SIZE +
+               sizeof(struct lock_list) * MAX_LOCKDEP_ENTRIES +
+               sizeof(struct lock_chain) * MAX_LOCKDEP_CHAINS +
+               sizeof(struct list_head) * CHAINHASH_SIZE) / 1024);
+
+       printk(" per task-struct memory footprint: %lu bytes\n",
+               sizeof(struct held_lock) * MAX_LOCK_DEPTH);
+
+#ifdef CONFIG_DEBUG_LOCKDEP
+       if (lockdep_init_error)
+               printk("WARNING: lockdep init error! Arch code didnt call lockdep_init() early enough?\n");
+#endif
+}
+
+static inline int in_range(const void *start, const void *addr, const void *end)
+{
+       return addr >= start && addr <= end;
+}
+
+static void
+print_freed_lock_bug(struct task_struct *curr, const void *mem_from,
+                    const void *mem_to, struct held_lock *hlock)
+{
+       if (!debug_locks_off())
+               return;
+       if (debug_locks_silent)
+               return;
+
+       printk("\n=========================\n");
+       printk(  "[ BUG: held lock freed! ]\n");
+       printk(  "-------------------------\n");
+       printk("%s/%d is freeing memory %p-%p, with a lock still held there!\n",
+               curr->comm, curr->pid, mem_from, mem_to-1);
+       print_lock(hlock);
+       lockdep_print_held_locks(curr);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+}
+
+/*
+ * Called when kernel memory is freed (or unmapped), or if a lock
+ * is destroyed or reinitialized - this code checks whether there is
+ * any held lock in the memory range of <from> to <to>:
+ */
+void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
+{
+       const void *mem_to = mem_from + mem_len, *lock_from, *lock_to;
+       struct task_struct *curr = current;
+       struct held_lock *hlock;
+       unsigned long flags;
+       int i;
+
+       if (unlikely(!debug_locks))
+               return;
+
+       local_irq_save(flags);
+       for (i = 0; i < curr->lockdep_depth; i++) {
+               hlock = curr->held_locks + i;
+
+               lock_from = (void *)hlock->instance;
+               lock_to = (void *)(hlock->instance + 1);
+
+               if (!in_range(mem_from, lock_from, mem_to) &&
+                                       !in_range(mem_from, lock_to, mem_to))
+                       continue;
+
+               print_freed_lock_bug(curr, mem_from, mem_to, hlock);
+               break;
+       }
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
+
+static void print_held_locks_bug(struct task_struct *curr)
+{
+       if (!debug_locks_off())
+               return;
+       if (debug_locks_silent)
+               return;
+
+       printk("\n=====================================\n");
+       printk(  "[ BUG: lock held at task exit time! ]\n");
+       printk(  "-------------------------------------\n");
+       printk("%s/%d is exiting with locks still held!\n",
+               curr->comm, curr->pid);
+       lockdep_print_held_locks(curr);
+
+       printk("\nstack backtrace:\n");
+       dump_stack();
+}
+
+void debug_check_no_locks_held(struct task_struct *task)
+{
+       if (unlikely(task->lockdep_depth > 0))
+               print_held_locks_bug(task);
+}
+
+void debug_show_all_locks(void)
+{
+       struct task_struct *g, *p;
+       int count = 10;
+       int unlock = 1;
+
+       printk("\nShowing all locks held in the system:\n");
+
+       /*
+        * Here we try to get the tasklist_lock as hard as possible,
+        * if not successful after 2 seconds we ignore it (but keep
+        * trying). This is to enable a debug printout even if a
+        * tasklist_lock-holding task deadlocks or crashes.
+        */
+retry:
+       if (!read_trylock(&tasklist_lock)) {
+               if (count == 10)
+                       printk("hm, tasklist_lock locked, retrying... ");
+               if (count) {
+                       count--;
+                       printk(" #%d", 10-count);
+                       mdelay(200);
+                       goto retry;
+               }
+               printk(" ignoring it.\n");
+               unlock = 0;
+       }
+       if (count != 10)
+               printk(" locked it.\n");
+
+       do_each_thread(g, p) {
+               if (p->lockdep_depth)
+                       lockdep_print_held_locks(p);
+               if (!unlock)
+                       if (read_trylock(&tasklist_lock))
+                               unlock = 1;
+       } while_each_thread(g, p);
+
+       printk("\n");
+       printk("=============================================\n\n");
+
+       if (unlock)
+               read_unlock(&tasklist_lock);
+}
+
+EXPORT_SYMBOL_GPL(debug_show_all_locks);
+
+void debug_show_held_locks(struct task_struct *task)
+{
+       lockdep_print_held_locks(task);
+}
+
+EXPORT_SYMBOL_GPL(debug_show_held_locks);
+
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
new file mode 100644 (file)
index 0000000..eab043c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * kernel/lockdep_internals.h
+ *
+ * Runtime locking correctness validator
+ *
+ * lockdep subsystem internal functions and variables.
+ */
+
+/*
+ * MAX_LOCKDEP_ENTRIES is the maximum number of lock dependencies
+ * we track.
+ *
+ * We use the per-lock dependency maps in two ways: we grow it by adding
+ * every to-be-taken lock to all currently held lock's own dependency
+ * table (if it's not there yet), and we check it for lock order
+ * conflicts and deadlocks.
+ */
+#define MAX_LOCKDEP_ENTRIES    8192UL
+
+#define MAX_LOCKDEP_KEYS_BITS  11
+#define MAX_LOCKDEP_KEYS       (1UL << MAX_LOCKDEP_KEYS_BITS)
+
+#define MAX_LOCKDEP_CHAINS_BITS        13
+#define MAX_LOCKDEP_CHAINS     (1UL << MAX_LOCKDEP_CHAINS_BITS)
+
+/*
+ * Stack-trace: tightly packed array of stack backtrace
+ * addresses. Protected by the hash_lock.
+ */
+#define MAX_STACK_TRACE_ENTRIES        262144UL
+
+extern struct list_head all_lock_classes;
+
+extern void
+get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4);
+
+extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str);
+
+extern unsigned long nr_lock_classes;
+extern unsigned long nr_list_entries;
+extern unsigned long nr_lock_chains;
+extern unsigned long nr_stack_trace_entries;
+
+extern unsigned int nr_hardirq_chains;
+extern unsigned int nr_softirq_chains;
+extern unsigned int nr_process_chains;
+extern unsigned int max_lockdep_depth;
+extern unsigned int max_recursion_depth;
+
+#ifdef CONFIG_DEBUG_LOCKDEP
+/*
+ * Various lockdep statistics:
+ */
+extern atomic_t chain_lookup_hits;
+extern atomic_t chain_lookup_misses;
+extern atomic_t hardirqs_on_events;
+extern atomic_t hardirqs_off_events;
+extern atomic_t redundant_hardirqs_on;
+extern atomic_t redundant_hardirqs_off;
+extern atomic_t softirqs_on_events;
+extern atomic_t softirqs_off_events;
+extern atomic_t redundant_softirqs_on;
+extern atomic_t redundant_softirqs_off;
+extern atomic_t nr_unused_locks;
+extern atomic_t nr_cyclic_checks;
+extern atomic_t nr_cyclic_check_recursions;
+extern atomic_t nr_find_usage_forwards_checks;
+extern atomic_t nr_find_usage_forwards_recursions;
+extern atomic_t nr_find_usage_backwards_checks;
+extern atomic_t nr_find_usage_backwards_recursions;
+# define debug_atomic_inc(ptr)         atomic_inc(ptr)
+# define debug_atomic_dec(ptr)         atomic_dec(ptr)
+# define debug_atomic_read(ptr)                atomic_read(ptr)
+#else
+# define debug_atomic_inc(ptr)         do { } while (0)
+# define debug_atomic_dec(ptr)         do { } while (0)
+# define debug_atomic_read(ptr)                0
+#endif
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
new file mode 100644 (file)
index 0000000..f6e72ea
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * kernel/lockdep_proc.c
+ *
+ * Runtime locking correctness validator
+ *
+ * Started by Ingo Molnar:
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * Code for /proc/lockdep and /proc/lockdep_stats:
+ *
+ */
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/debug_locks.h>
+
+#include "lockdep_internals.h"
+
+static void *l_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       struct lock_class *class = v;
+
+       (*pos)++;
+
+       if (class->lock_entry.next != &all_lock_classes)
+               class = list_entry(class->lock_entry.next, struct lock_class,
+                                 lock_entry);
+       else
+               class = NULL;
+       m->private = class;
+
+       return class;
+}
+
+static void *l_start(struct seq_file *m, loff_t *pos)
+{
+       struct lock_class *class = m->private;
+
+       if (&class->lock_entry == all_lock_classes.next)
+               seq_printf(m, "all lock classes:\n");
+
+       return class;
+}
+
+static void l_stop(struct seq_file *m, void *v)
+{
+}
+
+static unsigned long count_forward_deps(struct lock_class *class)
+{
+       struct lock_list *entry;
+       unsigned long ret = 1;
+
+       /*
+        * Recurse this class's dependency list:
+        */
+       list_for_each_entry(entry, &class->locks_after, entry)
+               ret += count_forward_deps(entry->class);
+
+       return ret;
+}
+
+static unsigned long count_backward_deps(struct lock_class *class)
+{
+       struct lock_list *entry;
+       unsigned long ret = 1;
+
+       /*
+        * Recurse this class's dependency list:
+        */
+       list_for_each_entry(entry, &class->locks_before, entry)
+               ret += count_backward_deps(entry->class);
+
+       return ret;
+}
+
+static int l_show(struct seq_file *m, void *v)
+{
+       unsigned long nr_forward_deps, nr_backward_deps;
+       struct lock_class *class = m->private;
+       char str[128], c1, c2, c3, c4;
+       const char *name;
+
+       seq_printf(m, "%p", class->key);
+#ifdef CONFIG_DEBUG_LOCKDEP
+       seq_printf(m, " OPS:%8ld", class->ops);
+#endif
+       nr_forward_deps = count_forward_deps(class);
+       seq_printf(m, " FD:%5ld", nr_forward_deps);
+
+       nr_backward_deps = count_backward_deps(class);
+       seq_printf(m, " BD:%5ld", nr_backward_deps);
+
+       get_usage_chars(class, &c1, &c2, &c3, &c4);
+       seq_printf(m, " %c%c%c%c", c1, c2, c3, c4);
+
+       name = class->name;
+       if (!name) {
+               name = __get_key_name(class->key, str);
+               seq_printf(m, ": %s", name);
+       } else{
+               seq_printf(m, ": %s", name);
+               if (class->name_version > 1)
+                       seq_printf(m, "#%d", class->name_version);
+               if (class->subclass)
+                       seq_printf(m, "/%d", class->subclass);
+       }
+       seq_puts(m, "\n");
+
+       return 0;
+}
+
+static struct seq_operations lockdep_ops = {
+       .start  = l_start,
+       .next   = l_next,
+       .stop   = l_stop,
+       .show   = l_show,
+};
+
+static int lockdep_open(struct inode *inode, struct file *file)
+{
+       int res = seq_open(file, &lockdep_ops);
+       if (!res) {
+               struct seq_file *m = file->private_data;
+
+               if (!list_empty(&all_lock_classes))
+                       m->private = list_entry(all_lock_classes.next,
+                                       struct lock_class, lock_entry);
+               else
+                       m->private = NULL;
+       }
+       return res;
+}
+
+static struct file_operations proc_lockdep_operations = {
+       .open           = lockdep_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static void lockdep_stats_debug_show(struct seq_file *m)
+{
+#ifdef CONFIG_DEBUG_LOCKDEP
+       unsigned int hi1 = debug_atomic_read(&hardirqs_on_events),
+                    hi2 = debug_atomic_read(&hardirqs_off_events),
+                    hr1 = debug_atomic_read(&redundant_hardirqs_on),
+                    hr2 = debug_atomic_read(&redundant_hardirqs_off),
+                    si1 = debug_atomic_read(&softirqs_on_events),
+                    si2 = debug_atomic_read(&softirqs_off_events),
+                    sr1 = debug_atomic_read(&redundant_softirqs_on),
+                    sr2 = debug_atomic_read(&redundant_softirqs_off);
+
+       seq_printf(m, " chain lookup misses:           %11u\n",
+               debug_atomic_read(&chain_lookup_misses));
+       seq_printf(m, " chain lookup hits:             %11u\n",
+               debug_atomic_read(&chain_lookup_hits));
+       seq_printf(m, " cyclic checks:                 %11u\n",
+               debug_atomic_read(&nr_cyclic_checks));
+       seq_printf(m, " cyclic-check recursions:       %11u\n",
+               debug_atomic_read(&nr_cyclic_check_recursions));
+       seq_printf(m, " find-mask forwards checks:     %11u\n",
+               debug_atomic_read(&nr_find_usage_forwards_checks));
+       seq_printf(m, " find-mask forwards recursions: %11u\n",
+               debug_atomic_read(&nr_find_usage_forwards_recursions));
+       seq_printf(m, " find-mask backwards checks:    %11u\n",
+               debug_atomic_read(&nr_find_usage_backwards_checks));
+       seq_printf(m, " find-mask backwards recursions:%11u\n",
+               debug_atomic_read(&nr_find_usage_backwards_recursions));
+
+       seq_printf(m, " hardirq on events:             %11u\n", hi1);
+       seq_printf(m, " hardirq off events:            %11u\n", hi2);
+       seq_printf(m, " redundant hardirq ons:         %11u\n", hr1);
+       seq_printf(m, " redundant hardirq offs:        %11u\n", hr2);
+       seq_printf(m, " softirq on events:             %11u\n", si1);
+       seq_printf(m, " softirq off events:            %11u\n", si2);
+       seq_printf(m, " redundant softirq ons:         %11u\n", sr1);
+       seq_printf(m, " redundant softirq offs:        %11u\n", sr2);
+#endif
+}
+
+static int lockdep_stats_show(struct seq_file *m, void *v)
+{
+       struct lock_class *class;
+       unsigned long nr_unused = 0, nr_uncategorized = 0,
+                     nr_irq_safe = 0, nr_irq_unsafe = 0,
+                     nr_softirq_safe = 0, nr_softirq_unsafe = 0,
+                     nr_hardirq_safe = 0, nr_hardirq_unsafe = 0,
+                     nr_irq_read_safe = 0, nr_irq_read_unsafe = 0,
+                     nr_softirq_read_safe = 0, nr_softirq_read_unsafe = 0,
+                     nr_hardirq_read_safe = 0, nr_hardirq_read_unsafe = 0,
+                     sum_forward_deps = 0, factor = 0;
+
+       list_for_each_entry(class, &all_lock_classes, lock_entry) {
+
+               if (class->usage_mask == 0)
+                       nr_unused++;
+               if (class->usage_mask == LOCKF_USED)
+                       nr_uncategorized++;
+               if (class->usage_mask & LOCKF_USED_IN_IRQ)
+                       nr_irq_safe++;
+               if (class->usage_mask & LOCKF_ENABLED_IRQS)
+                       nr_irq_unsafe++;
+               if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ)
+                       nr_softirq_safe++;
+               if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS)
+                       nr_softirq_unsafe++;
+               if (class->usage_mask & LOCKF_USED_IN_HARDIRQ)
+                       nr_hardirq_safe++;
+               if (class->usage_mask & LOCKF_ENABLED_HARDIRQS)
+                       nr_hardirq_unsafe++;
+               if (class->usage_mask & LOCKF_USED_IN_IRQ_READ)
+                       nr_irq_read_safe++;
+               if (class->usage_mask & LOCKF_ENABLED_IRQS_READ)
+                       nr_irq_read_unsafe++;
+               if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ)
+                       nr_softirq_read_safe++;
+               if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ)
+                       nr_softirq_read_unsafe++;
+               if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ)
+                       nr_hardirq_read_safe++;
+               if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ)
+                       nr_hardirq_read_unsafe++;
+
+               sum_forward_deps += count_forward_deps(class);
+       }
+#ifdef CONFIG_LOCKDEP_DEBUG
+       DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused);
+#endif
+       seq_printf(m, " lock-classes:                  %11lu [max: %lu]\n",
+                       nr_lock_classes, MAX_LOCKDEP_KEYS);
+       seq_printf(m, " direct dependencies:           %11lu [max: %lu]\n",
+                       nr_list_entries, MAX_LOCKDEP_ENTRIES);
+       seq_printf(m, " indirect dependencies:         %11lu\n",
+                       sum_forward_deps);
+
+       /*
+        * Total number of dependencies:
+        *
+        * All irq-safe locks may nest inside irq-unsafe locks,
+        * plus all the other known dependencies:
+        */
+       seq_printf(m, " all direct dependencies:       %11lu\n",
+                       nr_irq_unsafe * nr_irq_safe +
+                       nr_hardirq_unsafe * nr_hardirq_safe +
+                       nr_list_entries);
+
+       /*
+        * Estimated factor between direct and indirect
+        * dependencies:
+        */
+       if (nr_list_entries)
+               factor = sum_forward_deps / nr_list_entries;
+
+       seq_printf(m, " dependency chains:             %11lu [max: %lu]\n",
+                       nr_lock_chains, MAX_LOCKDEP_CHAINS);
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+       seq_printf(m, " in-hardirq chains:             %11u\n",
+                       nr_hardirq_chains);
+       seq_printf(m, " in-softirq chains:             %11u\n",
+                       nr_softirq_chains);
+#endif
+       seq_printf(m, " in-process chains:             %11u\n",
+                       nr_process_chains);
+       seq_printf(m, " stack-trace entries:           %11lu [max: %lu]\n",
+                       nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
+       seq_printf(m, " combined max dependencies:     %11u\n",
+                       (nr_hardirq_chains + 1) *
+                       (nr_softirq_chains + 1) *
+                       (nr_process_chains + 1)
+       );
+       seq_printf(m, " hardirq-safe locks:            %11lu\n",
+                       nr_hardirq_safe);
+       seq_printf(m, " hardirq-unsafe locks:          %11lu\n",
+                       nr_hardirq_unsafe);
+       seq_printf(m, " softirq-safe locks:            %11lu\n",
+                       nr_softirq_safe);
+       seq_printf(m, " softirq-unsafe locks:          %11lu\n",
+                       nr_softirq_unsafe);
+       seq_printf(m, " irq-safe locks:                %11lu\n",
+                       nr_irq_safe);
+       seq_printf(m, " irq-unsafe locks:              %11lu\n",
+                       nr_irq_unsafe);
+
+       seq_printf(m, " hardirq-read-safe locks:       %11lu\n",
+                       nr_hardirq_read_safe);
+       seq_printf(m, " hardirq-read-unsafe locks:     %11lu\n",
+                       nr_hardirq_read_unsafe);
+       seq_printf(m, " softirq-read-safe locks:       %11lu\n",
+                       nr_softirq_read_safe);
+       seq_printf(m, " softirq-read-unsafe locks:     %11lu\n",
+                       nr_softirq_read_unsafe);
+       seq_printf(m, " irq-read-safe locks:           %11lu\n",
+                       nr_irq_read_safe);
+       seq_printf(m, " irq-read-unsafe locks:         %11lu\n",
+                       nr_irq_read_unsafe);
+
+       seq_printf(m, " uncategorized locks:           %11lu\n",
+                       nr_uncategorized);
+       seq_printf(m, " unused locks:                  %11lu\n",
+                       nr_unused);
+       seq_printf(m, " max locking depth:             %11u\n",
+                       max_lockdep_depth);
+       seq_printf(m, " max recursion depth:           %11u\n",
+                       max_recursion_depth);
+       lockdep_stats_debug_show(m);
+       seq_printf(m, " debug_locks:                   %11u\n",
+                       debug_locks);
+
+       return 0;
+}
+
+static int lockdep_stats_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, lockdep_stats_show, NULL);
+}
+
+static struct file_operations proc_lockdep_stats_operations = {
+       .open           = lockdep_stats_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init lockdep_proc_init(void)
+{
+       struct proc_dir_entry *entry;
+
+       entry = create_proc_entry("lockdep", S_IRUSR, NULL);
+       if (entry)
+               entry->proc_fops = &proc_lockdep_operations;
+
+       entry = create_proc_entry("lockdep_stats", S_IRUSR, NULL);
+       if (entry)
+               entry->proc_fops = &proc_lockdep_stats_operations;
+
+       return 0;
+}
+
+__initcall(lockdep_proc_init);
+
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
new file mode 100644 (file)
index 0000000..da8d6bf
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * RT-Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This code is based on the rt.c implementation in the preempt-rt tree.
+ * Portions of said code are
+ *
+ *  Copyright (C) 2004  LynuxWorks, Inc., Igor Manyilov, Bill Huey
+ *  Copyright (C) 2006  Esben Nielsen
+ *  Copyright (C) 2006  Kihon Technologies Inc.,
+ *                     Steven Rostedt <rostedt@goodmis.org>
+ *
+ * See rt.c in preempt-rt for proper credits and further information
+ */
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include <linux/syscalls.h>
+#include <linux/interrupt.h>
+#include <linux/plist.h>
+#include <linux/fs.h>
+#include <linux/debug_locks.h>
+
+#include "rtmutex_common.h"
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
+# define TRACE_WARN_ON(x)                      WARN_ON(x)
+# define TRACE_BUG_ON(x)                       BUG_ON(x)
+
+# define TRACE_OFF()                                           \
+do {                                                           \
+       if (rt_trace_on) {                                      \
+               rt_trace_on = 0;                                \
+               console_verbose();                              \
+               if (spin_is_locked(&current->pi_lock))          \
+                       spin_unlock(&current->pi_lock);         \
+       }                                                       \
+} while (0)
+
+# define TRACE_OFF_NOLOCK()                                    \
+do {                                                           \
+       if (rt_trace_on) {                                      \
+               rt_trace_on = 0;                                \
+               console_verbose();                              \
+       }                                                       \
+} while (0)
+
+# define TRACE_BUG_LOCKED()                    \
+do {                                           \
+       TRACE_OFF();                            \
+       BUG();                                  \
+} while (0)
+
+# define TRACE_WARN_ON_LOCKED(c)               \
+do {                                           \
+       if (unlikely(c)) {                      \
+               TRACE_OFF();                    \
+               WARN_ON(1);                     \
+       }                                       \
+} while (0)
+
+# define TRACE_BUG_ON_LOCKED(c)                        \
+do {                                           \
+       if (unlikely(c))                        \
+               TRACE_BUG_LOCKED();             \
+} while (0)
+
+#ifdef CONFIG_SMP
+# define SMP_TRACE_BUG_ON_LOCKED(c)    TRACE_BUG_ON_LOCKED(c)
+#else
+# define SMP_TRACE_BUG_ON_LOCKED(c)    do { } while (0)
+#endif
+
+/*
+ * deadlock detection flag. We turn it off when we detect
+ * the first problem because we dont want to recurse back
+ * into the tracing code when doing error printk or
+ * executing a BUG():
+ */
+int rt_trace_on = 1;
+
+void deadlock_trace_off(void)
+{
+       rt_trace_on = 0;
+}
+
+static void printk_task(struct task_struct *p)
+{
+       if (p)
+               printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio);
+       else
+               printk("<none>");
+}
+
+static void printk_lock(struct rt_mutex *lock, int print_owner)
+{
+       if (lock->name)
+               printk(" [%p] {%s}\n",
+                       lock, lock->name);
+       else
+               printk(" [%p] {%s:%d}\n",
+                       lock, lock->file, lock->line);
+
+       if (print_owner && rt_mutex_owner(lock)) {
+               printk(".. ->owner: %p\n", lock->owner);
+               printk(".. held by:  ");
+               printk_task(rt_mutex_owner(lock));
+               printk("\n");
+       }
+}
+
+void rt_mutex_debug_task_free(struct task_struct *task)
+{
+       WARN_ON(!plist_head_empty(&task->pi_waiters));
+       WARN_ON(task->pi_blocked_on);
+}
+
+/*
+ * We fill out the fields in the waiter to store the information about
+ * the deadlock. We print when we return. act_waiter can be NULL in
+ * case of a remove waiter operation.
+ */
+void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *act_waiter,
+                            struct rt_mutex *lock)
+{
+       struct task_struct *task;
+
+       if (!rt_trace_on || detect || !act_waiter)
+               return;
+
+       task = rt_mutex_owner(act_waiter->lock);
+       if (task && task != current) {
+               act_waiter->deadlock_task_pid = task->pid;
+               act_waiter->deadlock_lock = lock;
+       }
+}
+
+void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
+{
+       struct task_struct *task;
+
+       if (!waiter->deadlock_lock || !rt_trace_on)
+               return;
+
+       task = find_task_by_pid(waiter->deadlock_task_pid);
+       if (!task)
+               return;
+
+       TRACE_OFF_NOLOCK();
+
+       printk("\n============================================\n");
+       printk(  "[ BUG: circular locking deadlock detected! ]\n");
+       printk(  "--------------------------------------------\n");
+       printk("%s/%d is deadlocking current task %s/%d\n\n",
+              task->comm, task->pid, current->comm, current->pid);
+
+       printk("\n1) %s/%d is trying to acquire this lock:\n",
+              current->comm, current->pid);
+       printk_lock(waiter->lock, 1);
+
+       printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid);
+       printk_lock(waiter->deadlock_lock, 1);
+
+       debug_show_held_locks(current);
+       debug_show_held_locks(task);
+
+       printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid);
+       show_stack(task, NULL);
+       printk("\n%s/%d's [current] stackdump:\n\n",
+              current->comm, current->pid);
+       dump_stack();
+       debug_show_all_locks();
+
+       printk("[ turning off deadlock detection."
+              "Please report this trace. ]\n\n");
+       local_irq_disable();
+}
+
+void debug_rt_mutex_lock(struct rt_mutex *lock)
+{
+}
+
+void debug_rt_mutex_unlock(struct rt_mutex *lock)
+{
+       TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current);
+}
+
+void
+debug_rt_mutex_proxy_lock(struct rt_mutex *lock, struct task_struct *powner)
+{
+}
+
+void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock)
+{
+       TRACE_WARN_ON_LOCKED(!rt_mutex_owner(lock));
+}
+
+void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
+{
+       memset(waiter, 0x11, sizeof(*waiter));
+       plist_node_init(&waiter->list_entry, MAX_PRIO);
+       plist_node_init(&waiter->pi_list_entry, MAX_PRIO);
+}
+
+void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
+{
+       TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry));
+       TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
+       TRACE_WARN_ON(waiter->task);
+       memset(waiter, 0x22, sizeof(*waiter));
+}
+
+void debug_rt_mutex_init(struct rt_mutex *lock, const char *name)
+{
+       /*
+        * Make sure we are not reinitializing a held lock:
+        */
+       debug_check_no_locks_freed((void *)lock, sizeof(*lock));
+       lock->name = name;
+}
+
+void
+rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task)
+{
+}
+
+void rt_mutex_deadlock_account_unlock(struct task_struct *task)
+{
+}
+
diff --git a/kernel/rtmutex-debug.h b/kernel/rtmutex-debug.h
new file mode 100644 (file)
index 0000000..14193d5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * RT-Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains macros used solely by rtmutex.c. Debug version.
+ */
+
+extern void
+rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task);
+extern void rt_mutex_deadlock_account_unlock(struct task_struct *task);
+extern void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter);
+extern void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter);
+extern void debug_rt_mutex_init(struct rt_mutex *lock, const char *name);
+extern void debug_rt_mutex_lock(struct rt_mutex *lock);
+extern void debug_rt_mutex_unlock(struct rt_mutex *lock);
+extern void debug_rt_mutex_proxy_lock(struct rt_mutex *lock,
+                                     struct task_struct *powner);
+extern void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock);
+extern void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *waiter,
+                                   struct rt_mutex *lock);
+extern void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter);
+# define debug_rt_mutex_reset_waiter(w)                        \
+       do { (w)->deadlock_lock = NULL; } while (0)
+
+static inline int debug_rt_mutex_detect_deadlock(struct rt_mutex_waiter *waiter,
+                                                int detect)
+{
+       return (waiter != NULL);
+}
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
new file mode 100644 (file)
index 0000000..6dcea9d
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * RT-Mutex-tester: scriptable tester for rt mutexes
+ *
+ * started by Thomas Gleixner:
+ *
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ */
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+
+#include "rtmutex.h"
+
+#define MAX_RT_TEST_THREADS    8
+#define MAX_RT_TEST_MUTEXES    8
+
+static spinlock_t rttest_lock;
+static atomic_t rttest_event;
+
+struct test_thread_data {
+       int                     opcode;
+       int                     opdata;
+       int                     mutexes[MAX_RT_TEST_MUTEXES];
+       int                     bkl;
+       int                     event;
+       struct sys_device       sysdev;
+};
+
+static struct test_thread_data thread_data[MAX_RT_TEST_THREADS];
+static struct task_struct *threads[MAX_RT_TEST_THREADS];
+static struct rt_mutex mutexes[MAX_RT_TEST_MUTEXES];
+
+enum test_opcodes {
+       RTTEST_NOP = 0,
+       RTTEST_SCHEDOT,         /* 1 Sched other, data = nice */
+       RTTEST_SCHEDRT,         /* 2 Sched fifo, data = prio */
+       RTTEST_LOCK,            /* 3 Lock uninterruptible, data = lockindex */
+       RTTEST_LOCKNOWAIT,      /* 4 Lock uninterruptible no wait in wakeup, data = lockindex */
+       RTTEST_LOCKINT,         /* 5 Lock interruptible, data = lockindex */
+       RTTEST_LOCKINTNOWAIT,   /* 6 Lock interruptible no wait in wakeup, data = lockindex */
+       RTTEST_LOCKCONT,        /* 7 Continue locking after the wakeup delay */
+       RTTEST_UNLOCK,          /* 8 Unlock, data = lockindex */
+       RTTEST_LOCKBKL,         /* 9 Lock BKL */
+       RTTEST_UNLOCKBKL,       /* 10 Unlock BKL */
+       RTTEST_SIGNAL,          /* 11 Signal other test thread, data = thread id */
+       RTTEST_RESETEVENT = 98, /* 98 Reset event counter */
+       RTTEST_RESET = 99,      /* 99 Reset all pending operations */
+};
+
+static int handle_op(struct test_thread_data *td, int lockwakeup)
+{
+       int i, id, ret = -EINVAL;
+
+       switch(td->opcode) {
+
+       case RTTEST_NOP:
+               return 0;
+
+       case RTTEST_LOCKCONT:
+               td->mutexes[td->opdata] = 1;
+               td->event = atomic_add_return(1, &rttest_event);
+               return 0;
+
+       case RTTEST_RESET:
+               for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) {
+                       if (td->mutexes[i] == 4) {
+                               rt_mutex_unlock(&mutexes[i]);
+                               td->mutexes[i] = 0;
+                       }
+               }
+
+               if (!lockwakeup && td->bkl == 4) {
+                       unlock_kernel();
+                       td->bkl = 0;
+               }
+               return 0;
+
+       case RTTEST_RESETEVENT:
+               atomic_set(&rttest_event, 0);
+               return 0;
+
+       default:
+               if (lockwakeup)
+                       return ret;
+       }
+
+       switch(td->opcode) {
+
+       case RTTEST_LOCK:
+       case RTTEST_LOCKNOWAIT:
+               id = td->opdata;
+               if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
+                       return ret;
+
+               td->mutexes[id] = 1;
+               td->event = atomic_add_return(1, &rttest_event);
+               rt_mutex_lock(&mutexes[id]);
+               td->event = atomic_add_return(1, &rttest_event);
+               td->mutexes[id] = 4;
+               return 0;
+
+       case RTTEST_LOCKINT:
+       case RTTEST_LOCKINTNOWAIT:
+               id = td->opdata;
+               if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
+                       return ret;
+
+               td->mutexes[id] = 1;
+               td->event = atomic_add_return(1, &rttest_event);
+               ret = rt_mutex_lock_interruptible(&mutexes[id], 0);
+               td->event = atomic_add_return(1, &rttest_event);
+               td->mutexes[id] = ret ? 0 : 4;
+               return ret ? -EINTR : 0;
+
+       case RTTEST_UNLOCK:
+               id = td->opdata;
+               if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4)
+                       return ret;
+
+               td->event = atomic_add_return(1, &rttest_event);
+               rt_mutex_unlock(&mutexes[id]);
+               td->event = atomic_add_return(1, &rttest_event);
+               td->mutexes[id] = 0;
+               return 0;
+
+       case RTTEST_LOCKBKL:
+               if (td->bkl)
+                       return 0;
+               td->bkl = 1;
+               lock_kernel();
+               td->bkl = 4;
+               return 0;
+
+       case RTTEST_UNLOCKBKL:
+               if (td->bkl != 4)
+                       break;
+               unlock_kernel();
+               td->bkl = 0;
+               return 0;
+
+       default:
+               break;
+       }
+       return ret;
+}
+
+/*
+ * Schedule replacement for rtsem_down(). Only called for threads with
+ * PF_MUTEX_TESTER set.
+ *
+ * This allows us to have finegrained control over the event flow.
+ *
+ */
+void schedule_rt_mutex_test(struct rt_mutex *mutex)
+{
+       int tid, op, dat;
+       struct test_thread_data *td;
+
+       /* We have to lookup the task */
+       for (tid = 0; tid < MAX_RT_TEST_THREADS; tid++) {
+               if (threads[tid] == current)
+                       break;
+       }
+
+       BUG_ON(tid == MAX_RT_TEST_THREADS);
+
+       td = &thread_data[tid];
+
+       op = td->opcode;
+       dat = td->opdata;
+
+       switch (op) {
+       case RTTEST_LOCK:
+       case RTTEST_LOCKINT:
+       case RTTEST_LOCKNOWAIT:
+       case RTTEST_LOCKINTNOWAIT:
+               if (mutex != &mutexes[dat])
+                       break;
+
+               if (td->mutexes[dat] != 1)
+                       break;
+
+               td->mutexes[dat] = 2;
+               td->event = atomic_add_return(1, &rttest_event);
+               break;
+
+       case RTTEST_LOCKBKL:
+       default:
+               break;
+       }
+
+       schedule();
+
+
+       switch (op) {
+       case RTTEST_LOCK:
+       case RTTEST_LOCKINT:
+               if (mutex != &mutexes[dat])
+                       return;
+
+               if (td->mutexes[dat] != 2)
+                       return;
+
+               td->mutexes[dat] = 3;
+               td->event = atomic_add_return(1, &rttest_event);
+               break;
+
+       case RTTEST_LOCKNOWAIT:
+       case RTTEST_LOCKINTNOWAIT:
+               if (mutex != &mutexes[dat])
+                       return;
+
+               if (td->mutexes[dat] != 2)
+                       return;
+
+               td->mutexes[dat] = 1;
+               td->event = atomic_add_return(1, &rttest_event);
+               return;
+
+       case RTTEST_LOCKBKL:
+               return;
+       default:
+               return;
+       }
+
+       td->opcode = 0;
+
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               if (td->opcode > 0) {
+                       int ret;
+
+                       set_current_state(TASK_RUNNING);
+                       ret = handle_op(td, 1);
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (td->opcode == RTTEST_LOCKCONT)
+                               break;
+                       td->opcode = ret;
+               }
+
+               /* Wait for the next command to be executed */
+               schedule();
+       }
+
+       /* Restore previous command and data */
+       td->opcode = op;
+       td->opdata = dat;
+}
+
+static int test_func(void *data)
+{
+       struct test_thread_data *td = data;
+       int ret;
+
+       current->flags |= PF_MUTEX_TESTER;
+       allow_signal(SIGHUP);
+
+       for(;;) {
+
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               if (td->opcode > 0) {
+                       set_current_state(TASK_RUNNING);
+                       ret = handle_op(td, 0);
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       td->opcode = ret;
+               }
+
+               /* Wait for the next command to be executed */
+               schedule();
+               try_to_freeze();
+
+               if (signal_pending(current))
+                       flush_signals(current);
+
+               if(kthread_should_stop())
+                       break;
+       }
+       return 0;
+}
+
+/**
+ * sysfs_test_command - interface for test commands
+ * @dev:       thread reference
+ * @buf:       command for actual step
+ * @count:     length of buffer
+ *
+ * command syntax:
+ *
+ * opcode:data
+ */
+static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf,
+                                 size_t count)
+{
+       struct sched_param schedpar;
+       struct test_thread_data *td;
+       char cmdbuf[32];
+       int op, dat, tid, ret;
+
+       td = container_of(dev, struct test_thread_data, sysdev);
+       tid = td->sysdev.id;
+
+       /* strings from sysfs write are not 0 terminated! */
+       if (count >= sizeof(cmdbuf))
+               return -EINVAL;
+
+       /* strip of \n: */
+       if (buf[count-1] == '\n')
+               count--;
+       if (count < 1)
+               return -EINVAL;
+
+       memcpy(cmdbuf, buf, count);
+       cmdbuf[count] = 0;
+
+       if (sscanf(cmdbuf, "%d:%d", &op, &dat) != 2)
+               return -EINVAL;
+
+       switch (op) {
+       case RTTEST_SCHEDOT:
+               schedpar.sched_priority = 0;
+               ret = sched_setscheduler(threads[tid], SCHED_NORMAL, &schedpar);
+               if (ret)
+                       return ret;
+               set_user_nice(current, 0);
+               break;
+
+       case RTTEST_SCHEDRT:
+               schedpar.sched_priority = dat;
+               ret = sched_setscheduler(threads[tid], SCHED_FIFO, &schedpar);
+               if (ret)
+                       return ret;
+               break;
+
+       case RTTEST_SIGNAL:
+               send_sig(SIGHUP, threads[tid], 0);
+               break;
+
+       default:
+               if (td->opcode > 0)
+                       return -EBUSY;
+               td->opdata = dat;
+               td->opcode = op;
+               wake_up_process(threads[tid]);
+       }
+
+       return count;
+}
+
+/**
+ * sysfs_test_status - sysfs interface for rt tester
+ * @dev:       thread to query
+ * @buf:       char buffer to be filled with thread status info
+ */
+static ssize_t sysfs_test_status(struct sys_device *dev, char *buf)
+{
+       struct test_thread_data *td;
+       struct task_struct *tsk;
+       char *curr = buf;
+       int i;
+
+       td = container_of(dev, struct test_thread_data, sysdev);
+       tsk = threads[td->sysdev.id];
+
+       spin_lock(&rttest_lock);
+
+       curr += sprintf(curr,
+               "O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, K: %d, M:",
+               td->opcode, td->event, tsk->state,
+                       (MAX_RT_PRIO - 1) - tsk->prio,
+                       (MAX_RT_PRIO - 1) - tsk->normal_prio,
+               tsk->pi_blocked_on, td->bkl);
+
+       for (i = MAX_RT_TEST_MUTEXES - 1; i >=0 ; i--)
+               curr += sprintf(curr, "%d", td->mutexes[i]);
+
+       spin_unlock(&rttest_lock);
+
+       curr += sprintf(curr, ", T: %p, R: %p\n", tsk,
+                       mutexes[td->sysdev.id].owner);
+
+       return curr - buf;
+}
+
+static SYSDEV_ATTR(status, 0600, sysfs_test_status, NULL);
+static SYSDEV_ATTR(command, 0600, NULL, sysfs_test_command);
+
+static struct sysdev_class rttest_sysclass = {
+       set_kset_name("rttest"),
+};
+
+static int init_test_thread(int id)
+{
+       thread_data[id].sysdev.cls = &rttest_sysclass;
+       thread_data[id].sysdev.id = id;
+
+       threads[id] = kthread_run(test_func, &thread_data[id], "rt-test-%d", id);
+       if (IS_ERR(threads[id]))
+               return PTR_ERR(threads[id]);
+
+       return sysdev_register(&thread_data[id].sysdev);
+}
+
+static int init_rttest(void)
+{
+       int ret, i;
+
+       spin_lock_init(&rttest_lock);
+
+       for (i = 0; i < MAX_RT_TEST_MUTEXES; i++)
+               rt_mutex_init(&mutexes[i]);
+
+       ret = sysdev_class_register(&rttest_sysclass);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < MAX_RT_TEST_THREADS; i++) {
+               ret = init_test_thread(i);
+               if (ret)
+                       break;
+               ret = sysdev_create_file(&thread_data[i].sysdev, &attr_status);
+               if (ret)
+                       break;
+               ret = sysdev_create_file(&thread_data[i].sysdev, &attr_command);
+               if (ret)
+                       break;
+       }
+
+       printk("Initializing RT-Tester: %s\n", ret ? "Failed" : "OK" );
+
+       return ret;
+}
+
+device_initcall(init_rttest);
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
new file mode 100644 (file)
index 0000000..3e13a1e
--- /dev/null
@@ -0,0 +1,991 @@
+/*
+ * RT-Mutexes: simple blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner.
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *  Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt
+ *  Copyright (C) 2006 Esben Nielsen
+ *
+ *  See Documentation/rt-mutex-design.txt for details.
+ */
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+
+#include "rtmutex_common.h"
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
+/*
+ * lock->owner state tracking:
+ *
+ * lock->owner holds the task_struct pointer of the owner. Bit 0 and 1
+ * are used to keep track of the "owner is pending" and "lock has
+ * waiters" state.
+ *
+ * owner       bit1    bit0
+ * NULL                0       0       lock is free (fast acquire possible)
+ * NULL                0       1       invalid state
+ * NULL                1       0       Transitional State*
+ * NULL                1       1       invalid state
+ * taskpointer 0       0       lock is held (fast release possible)
+ * taskpointer 0       1       task is pending owner
+ * taskpointer 1       0       lock is held and has waiters
+ * taskpointer 1       1       task is pending owner and lock has more waiters
+ *
+ * Pending ownership is assigned to the top (highest priority)
+ * waiter of the lock, when the lock is released. The thread is woken
+ * up and can now take the lock. Until the lock is taken (bit 0
+ * cleared) a competing higher priority thread can steal the lock
+ * which puts the woken up thread back on the waiters list.
+ *
+ * The fast atomic compare exchange based acquire and release is only
+ * possible when bit 0 and 1 of lock->owner are 0.
+ *
+ * (*) There's a small time where the owner can be NULL and the
+ * "lock has waiters" bit is set.  This can happen when grabbing the lock.
+ * To prevent a cmpxchg of the owner releasing the lock, we need to set this
+ * bit before looking at the lock, hence the reason this is a transitional
+ * state.
+ */
+
+static void
+rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
+                  unsigned long mask)
+{
+       unsigned long val = (unsigned long)owner | mask;
+
+       if (rt_mutex_has_waiters(lock))
+               val |= RT_MUTEX_HAS_WAITERS;
+
+       lock->owner = (struct task_struct *)val;
+}
+
+static inline void clear_rt_mutex_waiters(struct rt_mutex *lock)
+{
+       lock->owner = (struct task_struct *)
+                       ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
+}
+
+static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
+{
+       if (!rt_mutex_has_waiters(lock))
+               clear_rt_mutex_waiters(lock);
+}
+
+/*
+ * We can speed up the acquire/release, if the architecture
+ * supports cmpxchg and if there's no debugging state to be set up
+ */
+#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
+# define rt_mutex_cmpxchg(l,c,n)       (cmpxchg(&l->owner, c, n) == c)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+       unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+       do {
+               owner = *p;
+       } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
+}
+#else
+# define rt_mutex_cmpxchg(l,c,n)       (0)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+       lock->owner = (struct task_struct *)
+                       ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
+}
+#endif
+
+/*
+ * Calculate task priority from the waiter list priority
+ *
+ * Return task->normal_prio when the waiter list is empty or when
+ * the waiter is not allowed to do priority boosting
+ */
+int rt_mutex_getprio(struct task_struct *task)
+{
+       if (likely(!task_has_pi_waiters(task)))
+               return task->normal_prio;
+
+       return min(task_top_pi_waiter(task)->pi_list_entry.prio,
+                  task->normal_prio);
+}
+
+/*
+ * Adjust the priority of a task, after its pi_waiters got modified.
+ *
+ * This can be both boosting and unboosting. task->pi_lock must be held.
+ */
+static void __rt_mutex_adjust_prio(struct task_struct *task)
+{
+       int prio = rt_mutex_getprio(task);
+
+       if (task->prio != prio)
+               rt_mutex_setprio(task, prio);
+}
+
+/*
+ * Adjust task priority (undo boosting). Called from the exit path of
+ * rt_mutex_slowunlock() and rt_mutex_slowlock().
+ *
+ * (Note: We do this outside of the protection of lock->wait_lock to
+ * allow the lock to be taken while or before we readjust the priority
+ * of task. We do not use the spin_xx_mutex() variants here as we are
+ * outside of the debug path.)
+ */
+static void rt_mutex_adjust_prio(struct task_struct *task)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&task->pi_lock, flags);
+       __rt_mutex_adjust_prio(task);
+       spin_unlock_irqrestore(&task->pi_lock, flags);
+}
+
+/*
+ * Max number of times we'll walk the boosting chain:
+ */
+int max_lock_depth = 1024;
+
+/*
+ * Adjust the priority chain. Also used for deadlock detection.
+ * Decreases task's usage by one - may thus free the task.
+ * Returns 0 or -EDEADLK.
+ */
+static int rt_mutex_adjust_prio_chain(struct task_struct *task,
+                                     int deadlock_detect,
+                                     struct rt_mutex *orig_lock,
+                                     struct rt_mutex_waiter *orig_waiter,
+                                     struct task_struct *top_task)
+{
+       struct rt_mutex *lock;
+       struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter;
+       int detect_deadlock, ret = 0, depth = 0;
+       unsigned long flags;
+
+       detect_deadlock = debug_rt_mutex_detect_deadlock(orig_waiter,
+                                                        deadlock_detect);
+
+       /*
+        * The (de)boosting is a step by step approach with a lot of
+        * pitfalls. We want this to be preemptible and we want hold a
+        * maximum of two locks per step. So we have to check
+        * carefully whether things change under us.
+        */
+ again:
+       if (++depth > max_lock_depth) {
+               static int prev_max;
+
+               /*
+                * Print this only once. If the admin changes the limit,
+                * print a new message when reaching the limit again.
+                */
+               if (prev_max != max_lock_depth) {
+                       prev_max = max_lock_depth;
+                       printk(KERN_WARNING "Maximum lock depth %d reached "
+                              "task: %s (%d)\n", max_lock_depth,
+                              top_task->comm, top_task->pid);
+               }
+               put_task_struct(task);
+
+               return deadlock_detect ? -EDEADLK : 0;
+       }
+ retry:
+       /*
+        * Task can not go away as we did a get_task() before !
+        */
+       spin_lock_irqsave(&task->pi_lock, flags);
+
+       waiter = task->pi_blocked_on;
+       /*
+        * Check whether the end of the boosting chain has been
+        * reached or the state of the chain has changed while we
+        * dropped the locks.
+        */
+       if (!waiter || !waiter->task)
+               goto out_unlock_pi;
+
+       if (top_waiter && (!task_has_pi_waiters(task) ||
+                          top_waiter != task_top_pi_waiter(task)))
+               goto out_unlock_pi;
+
+       /*
+        * When deadlock detection is off then we check, if further
+        * priority adjustment is necessary.
+        */
+       if (!detect_deadlock && waiter->list_entry.prio == task->prio)
+               goto out_unlock_pi;
+
+       lock = waiter->lock;
+       if (!spin_trylock(&lock->wait_lock)) {
+               spin_unlock_irqrestore(&task->pi_lock, flags);
+               cpu_relax();
+               goto retry;
+       }
+
+       /* Deadlock detection */
+       if (lock == orig_lock || rt_mutex_owner(lock) == top_task) {
+               debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock);
+               spin_unlock(&lock->wait_lock);
+               ret = deadlock_detect ? -EDEADLK : 0;
+               goto out_unlock_pi;
+       }
+
+       top_waiter = rt_mutex_top_waiter(lock);
+
+       /* Requeue the waiter */
+       plist_del(&waiter->list_entry, &lock->wait_list);
+       waiter->list_entry.prio = task->prio;
+       plist_add(&waiter->list_entry, &lock->wait_list);
+
+       /* Release the task */
+       spin_unlock_irqrestore(&task->pi_lock, flags);
+       put_task_struct(task);
+
+       /* Grab the next task */
+       task = rt_mutex_owner(lock);
+       spin_lock_irqsave(&task->pi_lock, flags);
+
+       if (waiter == rt_mutex_top_waiter(lock)) {
+               /* Boost the owner */
+               plist_del(&top_waiter->pi_list_entry, &task->pi_waiters);
+               waiter->pi_list_entry.prio = waiter->list_entry.prio;
+               plist_add(&waiter->pi_list_entry, &task->pi_waiters);
+               __rt_mutex_adjust_prio(task);
+
+       } else if (top_waiter == waiter) {
+               /* Deboost the owner */
+               plist_del(&waiter->pi_list_entry, &task->pi_waiters);
+               waiter = rt_mutex_top_waiter(lock);
+               waiter->pi_list_entry.prio = waiter->list_entry.prio;
+               plist_add(&waiter->pi_list_entry, &task->pi_waiters);
+               __rt_mutex_adjust_prio(task);
+       }
+
+       get_task_struct(task);
+       spin_unlock_irqrestore(&task->pi_lock, flags);
+
+       top_waiter = rt_mutex_top_waiter(lock);
+       spin_unlock(&lock->wait_lock);
+
+       if (!detect_deadlock && waiter != top_waiter)
+               goto out_put_task;
+
+       goto again;
+
+ out_unlock_pi:
+       spin_unlock_irqrestore(&task->pi_lock, flags);
+ out_put_task:
+       put_task_struct(task);
+
+       return ret;
+}
+
+/*
+ * Optimization: check if we can steal the lock from the
+ * assigned pending owner [which might not have taken the
+ * lock yet]:
+ */
+static inline int try_to_steal_lock(struct rt_mutex *lock)
+{
+       struct task_struct *pendowner = rt_mutex_owner(lock);
+       struct rt_mutex_waiter *next;
+       unsigned long flags;
+
+       if (!rt_mutex_owner_pending(lock))
+               return 0;
+
+       if (pendowner == current)
+               return 1;
+
+       spin_lock_irqsave(&pendowner->pi_lock, flags);
+       if (current->prio >= pendowner->prio) {
+               spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+               return 0;
+       }
+
+       /*
+        * Check if a waiter is enqueued on the pending owners
+        * pi_waiters list. Remove it and readjust pending owners
+        * priority.
+        */
+       if (likely(!rt_mutex_has_waiters(lock))) {
+               spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+               return 1;
+       }
+
+       /* No chain handling, pending owner is not blocked on anything: */
+       next = rt_mutex_top_waiter(lock);
+       plist_del(&next->pi_list_entry, &pendowner->pi_waiters);
+       __rt_mutex_adjust_prio(pendowner);
+       spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+
+       /*
+        * We are going to steal the lock and a waiter was
+        * enqueued on the pending owners pi_waiters queue. So
+        * we have to enqueue this waiter into
+        * current->pi_waiters list. This covers the case,
+        * where current is boosted because it holds another
+        * lock and gets unboosted because the booster is
+        * interrupted, so we would delay a waiter with higher
+        * priority as current->normal_prio.
+        *
+        * Note: in the rare case of a SCHED_OTHER task changing
+        * its priority and thus stealing the lock, next->task
+        * might be current:
+        */
+       if (likely(next->task != current)) {
+               spin_lock_irqsave(&current->pi_lock, flags);
+               plist_add(&next->pi_list_entry, &current->pi_waiters);
+               __rt_mutex_adjust_prio(current);
+               spin_unlock_irqrestore(&current->pi_lock, flags);
+       }
+       return 1;
+}
+
+/*
+ * Try to take an rt-mutex
+ *
+ * This fails
+ * - when the lock has a real owner
+ * - when a different pending owner exists and has higher priority than current
+ *
+ * Must be called with lock->wait_lock held.
+ */
+static int try_to_take_rt_mutex(struct rt_mutex *lock)
+{
+       /*
+        * We have to be careful here if the atomic speedups are
+        * enabled, such that, when
+        *  - no other waiter is on the lock
+        *  - the lock has been released since we did the cmpxchg
+        * the lock can be released or taken while we are doing the
+        * checks and marking the lock with RT_MUTEX_HAS_WAITERS.
+        *
+        * The atomic acquire/release aware variant of
+        * mark_rt_mutex_waiters uses a cmpxchg loop. After setting
+        * the WAITERS bit, the atomic release / acquire can not
+        * happen anymore and lock->wait_lock protects us from the
+        * non-atomic case.
+        *
+        * Note, that this might set lock->owner =
+        * RT_MUTEX_HAS_WAITERS in the case the lock is not contended
+        * any more. This is fixed up when we take the ownership.
+        * This is the transitional state explained at the top of this file.
+        */
+       mark_rt_mutex_waiters(lock);
+
+       if (rt_mutex_owner(lock) && !try_to_steal_lock(lock))
+               return 0;
+
+       /* We got the lock. */
+       debug_rt_mutex_lock(lock);
+
+       rt_mutex_set_owner(lock, current, 0);
+
+       rt_mutex_deadlock_account_lock(lock, current);
+
+       return 1;
+}
+
+/*
+ * Task blocks on lock.
+ *
+ * Prepare waiter and propagate pi chain
+ *
+ * This must be called with lock->wait_lock held.
+ */
+static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
+                                  struct rt_mutex_waiter *waiter,
+                                  int detect_deadlock)
+{
+       struct task_struct *owner = rt_mutex_owner(lock);
+       struct rt_mutex_waiter *top_waiter = waiter;
+       unsigned long flags;
+       int boost = 0, res;
+
+       spin_lock_irqsave(&current->pi_lock, flags);
+       __rt_mutex_adjust_prio(current);
+       waiter->task = current;
+       waiter->lock = lock;
+       plist_node_init(&waiter->list_entry, current->prio);
+       plist_node_init(&waiter->pi_list_entry, current->prio);
+
+       /* Get the top priority waiter on the lock */
+       if (rt_mutex_has_waiters(lock))
+               top_waiter = rt_mutex_top_waiter(lock);
+       plist_add(&waiter->list_entry, &lock->wait_list);
+
+       current->pi_blocked_on = waiter;
+
+       spin_unlock_irqrestore(&current->pi_lock, flags);
+
+       if (waiter == rt_mutex_top_waiter(lock)) {
+               spin_lock_irqsave(&owner->pi_lock, flags);
+               plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
+               plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
+
+               __rt_mutex_adjust_prio(owner);
+               if (owner->pi_blocked_on) {
+                       boost = 1;
+                       /* gets dropped in rt_mutex_adjust_prio_chain()! */
+                       get_task_struct(owner);
+               }
+               spin_unlock_irqrestore(&owner->pi_lock, flags);
+       }
+       else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) {
+               spin_lock_irqsave(&owner->pi_lock, flags);
+               if (owner->pi_blocked_on) {
+                       boost = 1;
+                       /* gets dropped in rt_mutex_adjust_prio_chain()! */
+                       get_task_struct(owner);
+               }
+               spin_unlock_irqrestore(&owner->pi_lock, flags);
+       }
+       if (!boost)
+               return 0;
+
+       spin_unlock(&lock->wait_lock);
+
+       res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter,
+                                        current);
+
+       spin_lock(&lock->wait_lock);
+
+       return res;
+}
+
+/*
+ * Wake up the next waiter on the lock.
+ *
+ * Remove the top waiter from the current tasks waiter list and from
+ * the lock waiter list. Set it as pending owner. Then wake it up.
+ *
+ * Called with lock->wait_lock held.
+ */
+static void wakeup_next_waiter(struct rt_mutex *lock)
+{
+       struct rt_mutex_waiter *waiter;
+       struct task_struct *pendowner;
+       unsigned long flags;
+
+       spin_lock_irqsave(&current->pi_lock, flags);
+
+       waiter = rt_mutex_top_waiter(lock);
+       plist_del(&waiter->list_entry, &lock->wait_list);
+
+       /*
+        * Remove it from current->pi_waiters. We do not adjust a
+        * possible priority boost right now. We execute wakeup in the
+        * boosted mode and go back to normal after releasing
+        * lock->wait_lock.
+        */
+       plist_del(&waiter->pi_list_entry, &current->pi_waiters);
+       pendowner = waiter->task;
+       waiter->task = NULL;
+
+       rt_mutex_set_owner(lock, pendowner, RT_MUTEX_OWNER_PENDING);
+
+       spin_unlock_irqrestore(&current->pi_lock, flags);
+
+       /*
+        * Clear the pi_blocked_on variable and enqueue a possible
+        * waiter into the pi_waiters list of the pending owner. This
+        * prevents that in case the pending owner gets unboosted a
+        * waiter with higher priority than pending-owner->normal_prio
+        * is blocked on the unboosted (pending) owner.
+        */
+       spin_lock_irqsave(&pendowner->pi_lock, flags);
+
+       WARN_ON(!pendowner->pi_blocked_on);
+       WARN_ON(pendowner->pi_blocked_on != waiter);
+       WARN_ON(pendowner->pi_blocked_on->lock != lock);
+
+       pendowner->pi_blocked_on = NULL;
+
+       if (rt_mutex_has_waiters(lock)) {
+               struct rt_mutex_waiter *next;
+
+               next = rt_mutex_top_waiter(lock);
+               plist_add(&next->pi_list_entry, &pendowner->pi_waiters);
+       }
+       spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+
+       wake_up_process(pendowner);
+}
+
+/*
+ * Remove a waiter from a lock
+ *
+ * Must be called with lock->wait_lock held
+ */
+static void remove_waiter(struct rt_mutex *lock,
+                         struct rt_mutex_waiter *waiter)
+{
+       int first = (waiter == rt_mutex_top_waiter(lock));
+       struct task_struct *owner = rt_mutex_owner(lock);
+       unsigned long flags;
+       int boost = 0;
+
+       spin_lock_irqsave(&current->pi_lock, flags);
+       plist_del(&waiter->list_entry, &lock->wait_list);
+       waiter->task = NULL;
+       current->pi_blocked_on = NULL;
+       spin_unlock_irqrestore(&current->pi_lock, flags);
+
+       if (first && owner != current) {
+
+               spin_lock_irqsave(&owner->pi_lock, flags);
+
+               plist_del(&waiter->pi_list_entry, &owner->pi_waiters);
+
+               if (rt_mutex_has_waiters(lock)) {
+                       struct rt_mutex_waiter *next;
+
+                       next = rt_mutex_top_waiter(lock);
+                       plist_add(&next->pi_list_entry, &owner->pi_waiters);
+               }
+               __rt_mutex_adjust_prio(owner);
+
+               if (owner->pi_blocked_on) {
+                       boost = 1;
+                       /* gets dropped in rt_mutex_adjust_prio_chain()! */
+                       get_task_struct(owner);
+               }
+               spin_unlock_irqrestore(&owner->pi_lock, flags);
+       }
+
+       WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
+
+       if (!boost)
+               return;
+
+       spin_unlock(&lock->wait_lock);
+
+       rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current);
+
+       spin_lock(&lock->wait_lock);
+}
+
+/*
+ * Recheck the pi chain, in case we got a priority setting
+ *
+ * Called from sched_setscheduler
+ */
+void rt_mutex_adjust_pi(struct task_struct *task)
+{
+       struct rt_mutex_waiter *waiter;
+       unsigned long flags;
+
+       spin_lock_irqsave(&task->pi_lock, flags);
+
+       waiter = task->pi_blocked_on;
+       if (!waiter || waiter->list_entry.prio == task->prio) {
+               spin_unlock_irqrestore(&task->pi_lock, flags);
+               return;
+       }
+
+       /* gets dropped in rt_mutex_adjust_prio_chain()! */
+       get_task_struct(task);
+       spin_unlock_irqrestore(&task->pi_lock, flags);
+
+       rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task);
+}
+
+/*
+ * Slow path lock function:
+ */
+static int __sched
+rt_mutex_slowlock(struct rt_mutex *lock, int state,
+                 struct hrtimer_sleeper *timeout,
+                 int detect_deadlock)
+{
+       struct rt_mutex_waiter waiter;
+       int ret = 0;
+
+       debug_rt_mutex_init_waiter(&waiter);
+       waiter.task = NULL;
+
+       spin_lock(&lock->wait_lock);
+
+       /* Try to acquire the lock again: */
+       if (try_to_take_rt_mutex(lock)) {
+               spin_unlock(&lock->wait_lock);
+               return 0;
+       }
+
+       set_current_state(state);
+
+       /* Setup the timer, when timeout != NULL */
+       if (unlikely(timeout))
+               hrtimer_start(&timeout->timer, timeout->timer.expires,
+                             HRTIMER_ABS);
+
+       for (;;) {
+               /* Try to acquire the lock: */
+               if (try_to_take_rt_mutex(lock))
+                       break;
+
+               /*
+                * TASK_INTERRUPTIBLE checks for signals and
+                * timeout. Ignored otherwise.
+                */
+               if (unlikely(state == TASK_INTERRUPTIBLE)) {
+                       /* Signal pending? */
+                       if (signal_pending(current))
+                               ret = -EINTR;
+                       if (timeout && !timeout->task)
+                               ret = -ETIMEDOUT;
+                       if (ret)
+                               break;
+               }
+
+               /*
+                * waiter.task is NULL the first time we come here and
+                * when we have been woken up by the previous owner
+                * but the lock got stolen by a higher prio task.
+                */
+               if (!waiter.task) {
+                       ret = task_blocks_on_rt_mutex(lock, &waiter,
+                                                     detect_deadlock);
+                       /*
+                        * If we got woken up by the owner then start loop
+                        * all over without going into schedule to try
+                        * to get the lock now:
+                        */
+                       if (unlikely(!waiter.task))
+                               continue;
+
+                       if (unlikely(ret))
+                               break;
+               }
+
+               spin_unlock(&lock->wait_lock);
+
+               debug_rt_mutex_print_deadlock(&waiter);
+
+               if (waiter.task)
+                       schedule_rt_mutex(lock);
+
+               spin_lock(&lock->wait_lock);
+               set_current_state(state);
+       }
+
+       set_current_state(TASK_RUNNING);
+
+       if (unlikely(waiter.task))
+               remove_waiter(lock, &waiter);
+
+       /*
+        * try_to_take_rt_mutex() sets the waiter bit
+        * unconditionally. We might have to fix that up.
+        */
+       fixup_rt_mutex_waiters(lock);
+
+       spin_unlock(&lock->wait_lock);
+
+       /* Remove pending timer: */
+       if (unlikely(timeout))
+               hrtimer_cancel(&timeout->timer);
+
+       /*
+        * Readjust priority, when we did not get the lock. We might
+        * have been the pending owner and boosted. Since we did not
+        * take the lock, the PI boost has to go.
+        */
+       if (unlikely(ret))
+               rt_mutex_adjust_prio(current);
+
+       debug_rt_mutex_free_waiter(&waiter);
+
+       return ret;
+}
+
+/*
+ * Slow path try-lock function:
+ */
+static inline int
+rt_mutex_slowtrylock(struct rt_mutex *lock)
+{
+       int ret = 0;
+
+       spin_lock(&lock->wait_lock);
+
+       if (likely(rt_mutex_owner(lock) != current)) {
+
+               ret = try_to_take_rt_mutex(lock);
+               /*
+                * try_to_take_rt_mutex() sets the lock waiters
+                * bit unconditionally. Clean this up.
+                */
+               fixup_rt_mutex_waiters(lock);
+       }
+
+       spin_unlock(&lock->wait_lock);
+
+       return ret;
+}
+
+/*
+ * Slow path to release a rt-mutex:
+ */
+static void __sched
+rt_mutex_slowunlock(struct rt_mutex *lock)
+{
+       spin_lock(&lock->wait_lock);
+
+       debug_rt_mutex_unlock(lock);
+
+       rt_mutex_deadlock_account_unlock(current);
+
+       if (!rt_mutex_has_waiters(lock)) {
+               lock->owner = NULL;
+               spin_unlock(&lock->wait_lock);
+               return;
+       }
+
+       wakeup_next_waiter(lock);
+
+       spin_unlock(&lock->wait_lock);
+
+       /* Undo pi boosting if necessary: */
+       rt_mutex_adjust_prio(current);
+}
+
+/*
+ * debug aware fast / slowpath lock,trylock,unlock
+ *
+ * The atomic acquire/release ops are compiled away, when either the
+ * architecture does not support cmpxchg or when debugging is enabled.
+ */
+static inline int
+rt_mutex_fastlock(struct rt_mutex *lock, int state,
+                 int detect_deadlock,
+                 int (*slowfn)(struct rt_mutex *lock, int state,
+                               struct hrtimer_sleeper *timeout,
+                               int detect_deadlock))
+{
+       if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) {
+               rt_mutex_deadlock_account_lock(lock, current);
+               return 0;
+       } else
+               return slowfn(lock, state, NULL, detect_deadlock);
+}
+
+static inline int
+rt_mutex_timed_fastlock(struct rt_mutex *lock, int state,
+                       struct hrtimer_sleeper *timeout, int detect_deadlock,
+                       int (*slowfn)(struct rt_mutex *lock, int state,
+                                     struct hrtimer_sleeper *timeout,
+                                     int detect_deadlock))
+{
+       if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) {
+               rt_mutex_deadlock_account_lock(lock, current);
+               return 0;
+       } else
+               return slowfn(lock, state, timeout, detect_deadlock);
+}
+
+static inline int
+rt_mutex_fasttrylock(struct rt_mutex *lock,
+                    int (*slowfn)(struct rt_mutex *lock))
+{
+       if (likely(rt_mutex_cmpxchg(lock, NULL, current))) {
+               rt_mutex_deadlock_account_lock(lock, current);
+               return 1;
+       }
+       return slowfn(lock);
+}
+
+static inline void
+rt_mutex_fastunlock(struct rt_mutex *lock,
+                   void (*slowfn)(struct rt_mutex *lock))
+{
+       if (likely(rt_mutex_cmpxchg(lock, current, NULL)))
+               rt_mutex_deadlock_account_unlock(current);
+       else
+               slowfn(lock);
+}
+
+/**
+ * rt_mutex_lock - lock a rt_mutex
+ *
+ * @lock: the rt_mutex to be locked
+ */
+void __sched rt_mutex_lock(struct rt_mutex *lock)
+{
+       might_sleep();
+
+       rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_lock);
+
+/**
+ * rt_mutex_lock_interruptible - lock a rt_mutex interruptible
+ *
+ * @lock:              the rt_mutex to be locked
+ * @detect_deadlock:   deadlock detection on/off
+ *
+ * Returns:
+ *  0          on success
+ * -EINTR      when interrupted by a signal
+ * -EDEADLK    when the lock would deadlock (when deadlock detection is on)
+ */
+int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock,
+                                                int detect_deadlock)
+{
+       might_sleep();
+
+       return rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE,
+                                detect_deadlock, rt_mutex_slowlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
+
+/**
+ * rt_mutex_lock_interruptible_ktime - lock a rt_mutex interruptible
+ *                                    the timeout structure is provided
+ *                                    by the caller
+ *
+ * @lock:              the rt_mutex to be locked
+ * @timeout:           timeout structure or NULL (no timeout)
+ * @detect_deadlock:   deadlock detection on/off
+ *
+ * Returns:
+ *  0          on success
+ * -EINTR      when interrupted by a signal
+ * -ETIMEOUT   when the timeout expired
+ * -EDEADLK    when the lock would deadlock (when deadlock detection is on)
+ */
+int
+rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout,
+                   int detect_deadlock)
+{
+       might_sleep();
+
+       return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout,
+                                      detect_deadlock, rt_mutex_slowlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
+
+/**
+ * rt_mutex_trylock - try to lock a rt_mutex
+ *
+ * @lock:      the rt_mutex to be locked
+ *
+ * Returns 1 on success and 0 on contention
+ */
+int __sched rt_mutex_trylock(struct rt_mutex *lock)
+{
+       return rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_trylock);
+
+/**
+ * rt_mutex_unlock - unlock a rt_mutex
+ *
+ * @lock: the rt_mutex to be unlocked
+ */
+void __sched rt_mutex_unlock(struct rt_mutex *lock)
+{
+       rt_mutex_fastunlock(lock, rt_mutex_slowunlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_unlock);
+
+/***
+ * rt_mutex_destroy - mark a mutex unusable
+ * @lock: the mutex to be destroyed
+ *
+ * This function marks the mutex uninitialized, and any subsequent
+ * use of the mutex is forbidden. The mutex must not be locked when
+ * this function is called.
+ */
+void rt_mutex_destroy(struct rt_mutex *lock)
+{
+       WARN_ON(rt_mutex_is_locked(lock));
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+       lock->magic = NULL;
+#endif
+}
+
+EXPORT_SYMBOL_GPL(rt_mutex_destroy);
+
+/**
+ * __rt_mutex_init - initialize the rt lock
+ *
+ * @lock: the rt lock to be initialized
+ *
+ * Initialize the rt lock to unlocked state.
+ *
+ * Initializing of a locked rt lock is not allowed
+ */
+void __rt_mutex_init(struct rt_mutex *lock, const char *name)
+{
+       lock->owner = NULL;
+       spin_lock_init(&lock->wait_lock);
+       plist_head_init(&lock->wait_list, &lock->wait_lock);
+
+       debug_rt_mutex_init(lock, name);
+}
+EXPORT_SYMBOL_GPL(__rt_mutex_init);
+
+/**
+ * rt_mutex_init_proxy_locked - initialize and lock a rt_mutex on behalf of a
+ *                             proxy owner
+ *
+ * @lock:      the rt_mutex to be locked
+ * @proxy_owner:the task to set as owner
+ *
+ * No locking. Caller has to do serializing itself
+ * Special API call for PI-futex support
+ */
+void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
+                               struct task_struct *proxy_owner)
+{
+       __rt_mutex_init(lock, NULL);
+       debug_rt_mutex_proxy_lock(lock, proxy_owner);
+       rt_mutex_set_owner(lock, proxy_owner, 0);
+       rt_mutex_deadlock_account_lock(lock, proxy_owner);
+}
+
+/**
+ * rt_mutex_proxy_unlock - release a lock on behalf of owner
+ *
+ * @lock:      the rt_mutex to be locked
+ *
+ * No locking. Caller has to do serializing itself
+ * Special API call for PI-futex support
+ */
+void rt_mutex_proxy_unlock(struct rt_mutex *lock,
+                          struct task_struct *proxy_owner)
+{
+       debug_rt_mutex_proxy_unlock(lock);
+       rt_mutex_set_owner(lock, NULL, 0);
+       rt_mutex_deadlock_account_unlock(proxy_owner);
+}
+
+/**
+ * rt_mutex_next_owner - return the next owner of the lock
+ *
+ * @lock: the rt lock query
+ *
+ * Returns the next owner of the lock or NULL
+ *
+ * Caller has to serialize against other accessors to the lock
+ * itself.
+ *
+ * Special API call for PI-futex support
+ */
+struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock)
+{
+       if (!rt_mutex_has_waiters(lock))
+               return NULL;
+
+       return rt_mutex_top_waiter(lock)->task;
+}
diff --git a/kernel/rtmutex.h b/kernel/rtmutex.h
new file mode 100644 (file)
index 0000000..a1a1dd0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * RT-Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains macros used solely by rtmutex.c.
+ * Non-debug version.
+ */
+
+#define rt_mutex_deadlock_check(l)                     (0)
+#define rt_mutex_deadlock_account_lock(m, t)           do { } while (0)
+#define rt_mutex_deadlock_account_unlock(l)            do { } while (0)
+#define debug_rt_mutex_init_waiter(w)                  do { } while (0)
+#define debug_rt_mutex_free_waiter(w)                  do { } while (0)
+#define debug_rt_mutex_lock(l)                         do { } while (0)
+#define debug_rt_mutex_proxy_lock(l,p)                 do { } while (0)
+#define debug_rt_mutex_proxy_unlock(l)                 do { } while (0)
+#define debug_rt_mutex_unlock(l)                       do { } while (0)
+#define debug_rt_mutex_init(m, n)                      do { } while (0)
+#define debug_rt_mutex_deadlock(d, a ,l)               do { } while (0)
+#define debug_rt_mutex_print_deadlock(w)               do { } while (0)
+#define debug_rt_mutex_detect_deadlock(w,d)            (d)
+#define debug_rt_mutex_reset_waiter(w)                 do { } while (0)
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
new file mode 100644 (file)
index 0000000..9c75856
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * RT Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains the private data structure and API definitions.
+ */
+
+#ifndef __KERNEL_RTMUTEX_COMMON_H
+#define __KERNEL_RTMUTEX_COMMON_H
+
+#include <linux/rtmutex.h>
+
+/*
+ * The rtmutex in kernel tester is independent of rtmutex debugging. We
+ * call schedule_rt_mutex_test() instead of schedule() for the tasks which
+ * belong to the tester. That way we can delay the wakeup path of those
+ * threads to provoke lock stealing and testing of  complex boosting scenarios.
+ */
+#ifdef CONFIG_RT_MUTEX_TESTER
+
+extern void schedule_rt_mutex_test(struct rt_mutex *lock);
+
+#define schedule_rt_mutex(_lock)                               \
+  do {                                                         \
+       if (!(current->flags & PF_MUTEX_TESTER))                \
+               schedule();                                     \
+       else                                                    \
+               schedule_rt_mutex_test(_lock);                  \
+  } while (0)
+
+#else
+# define schedule_rt_mutex(_lock)                      schedule()
+#endif
+
+/*
+ * This is the control structure for tasks blocked on a rt_mutex,
+ * which is allocated on the kernel stack on of the blocked task.
+ *
+ * @list_entry:                pi node to enqueue into the mutex waiters list
+ * @pi_list_entry:     pi node to enqueue into the mutex owner waiters list
+ * @task:              task reference to the blocked task
+ */
+struct rt_mutex_waiter {
+       struct plist_node       list_entry;
+       struct plist_node       pi_list_entry;
+       struct task_struct      *task;
+       struct rt_mutex         *lock;
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+       unsigned long           ip;
+       pid_t                   deadlock_task_pid;
+       struct rt_mutex         *deadlock_lock;
+#endif
+};
+
+/*
+ * Various helpers to access the waiters-plist:
+ */
+static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
+{
+       return !plist_head_empty(&lock->wait_list);
+}
+
+static inline struct rt_mutex_waiter *
+rt_mutex_top_waiter(struct rt_mutex *lock)
+{
+       struct rt_mutex_waiter *w;
+
+       w = plist_first_entry(&lock->wait_list, struct rt_mutex_waiter,
+                              list_entry);
+       BUG_ON(w->lock != lock);
+
+       return w;
+}
+
+static inline int task_has_pi_waiters(struct task_struct *p)
+{
+       return !plist_head_empty(&p->pi_waiters);
+}
+
+static inline struct rt_mutex_waiter *
+task_top_pi_waiter(struct task_struct *p)
+{
+       return plist_first_entry(&p->pi_waiters, struct rt_mutex_waiter,
+                                 pi_list_entry);
+}
+
+/*
+ * lock->owner state tracking:
+ */
+#define RT_MUTEX_OWNER_PENDING 1UL
+#define RT_MUTEX_HAS_WAITERS   2UL
+#define RT_MUTEX_OWNER_MASKALL 3UL
+
+static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
+{
+       return (struct task_struct *)
+               ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
+}
+
+static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock)
+{
+       return (struct task_struct *)
+               ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
+}
+
+static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock)
+{
+       return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING;
+}
+
+/*
+ * PI-futex support (proxy locking functions, etc.):
+ */
+extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock);
+extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
+                                      struct task_struct *proxy_owner);
+extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
+                                 struct task_struct *proxy_owner);
+#endif
diff --git a/kernel/rwsem.c b/kernel/rwsem.c
new file mode 100644 (file)
index 0000000..291ded5
--- /dev/null
@@ -0,0 +1,147 @@
+/* kernel/rwsem.c: R/W semaphores, public implementation
+ *
+ * Written by David Howells (dhowells@redhat.com).
+ * Derived from asm-i386/semaphore.h
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+/*
+ * lock for reading
+ */
+void down_read(struct rw_semaphore *sem)
+{
+       might_sleep();
+       rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
+
+       __down_read(sem);
+}
+
+EXPORT_SYMBOL(down_read);
+
+/*
+ * trylock for reading -- returns 1 if successful, 0 if contention
+ */
+int down_read_trylock(struct rw_semaphore *sem)
+{
+       int ret = __down_read_trylock(sem);
+
+       if (ret == 1)
+               rwsem_acquire_read(&sem->dep_map, 0, 1, _RET_IP_);
+       return ret;
+}
+
+EXPORT_SYMBOL(down_read_trylock);
+
+/*
+ * lock for writing
+ */
+void down_write(struct rw_semaphore *sem)
+{
+       might_sleep();
+       rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
+
+       __down_write(sem);
+}
+
+EXPORT_SYMBOL(down_write);
+
+/*
+ * trylock for writing -- returns 1 if successful, 0 if contention
+ */
+int down_write_trylock(struct rw_semaphore *sem)
+{
+       int ret = __down_write_trylock(sem);
+
+       if (ret == 1)
+               rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
+       return ret;
+}
+
+EXPORT_SYMBOL(down_write_trylock);
+
+/*
+ * release a read lock
+ */
+void up_read(struct rw_semaphore *sem)
+{
+       rwsem_release(&sem->dep_map, 1, _RET_IP_);
+
+       __up_read(sem);
+}
+
+EXPORT_SYMBOL(up_read);
+
+/*
+ * release a write lock
+ */
+void up_write(struct rw_semaphore *sem)
+{
+       rwsem_release(&sem->dep_map, 1, _RET_IP_);
+
+       __up_write(sem);
+}
+
+EXPORT_SYMBOL(up_write);
+
+/*
+ * downgrade write lock to read lock
+ */
+void downgrade_write(struct rw_semaphore *sem)
+{
+       /*
+        * lockdep: a downgraded write will live on as a write
+        * dependency.
+        */
+       __downgrade_write(sem);
+}
+
+EXPORT_SYMBOL(downgrade_write);
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+void down_read_nested(struct rw_semaphore *sem, int subclass)
+{
+       might_sleep();
+       rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);
+
+       __down_read(sem);
+}
+
+EXPORT_SYMBOL(down_read_nested);
+
+void down_read_non_owner(struct rw_semaphore *sem)
+{
+       might_sleep();
+
+       __down_read(sem);
+}
+
+EXPORT_SYMBOL(down_read_non_owner);
+
+void down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+       might_sleep();
+       rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
+
+       __down_write_nested(sem, subclass);
+}
+
+EXPORT_SYMBOL(down_write_nested);
+
+void up_read_non_owner(struct rw_semaphore *sem)
+{
+       __up_read(sem);
+}
+
+EXPORT_SYMBOL(up_read_non_owner);
+
+#endif
+
+
diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..b71816e
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ */
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <linux/stacktrace.h>
+
+void print_stack_trace(struct stack_trace *trace, int spaces)
+{
+       int i, j;
+
+       for (i = 0; i < trace->nr_entries; i++) {
+               unsigned long ip = trace->entries[i];
+
+               for (j = 0; j < spaces + 1; j++)
+                       printk(" ");
+               print_ip_sym(ip);
+       }
+}
+
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
new file mode 100644 (file)
index 0000000..b90b2a7
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * taskstats.c - Export per-task statistics to userland
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2006
+ *           (C) Balbir Singh,   IBM Corp. 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/taskstats_kern.h>
+#include <linux/delayacct.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+#include <net/genetlink.h>
+#include <asm/atomic.h>
+
+/*
+ * Maximum length of a cpumask that can be specified in
+ * the TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK attribute
+ */
+#define TASKSTATS_CPUMASK_MAXLEN       (100+6*NR_CPUS)
+
+static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 };
+static int family_registered;
+kmem_cache_t *taskstats_cache;
+
+static struct genl_family family = {
+       .id             = GENL_ID_GENERATE,
+       .name           = TASKSTATS_GENL_NAME,
+       .version        = TASKSTATS_GENL_VERSION,
+       .maxattr        = TASKSTATS_CMD_ATTR_MAX,
+};
+
+static struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1]
+__read_mostly = {
+       [TASKSTATS_CMD_ATTR_PID]  = { .type = NLA_U32 },
+       [TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 },
+       [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
+       [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};
+
+struct listener {
+       struct list_head list;
+       pid_t pid;
+       char valid;
+};
+
+struct listener_list {
+       struct rw_semaphore sem;
+       struct list_head list;
+};
+static DEFINE_PER_CPU(struct listener_list, listener_array);
+
+enum actions {
+       REGISTER,
+       DEREGISTER,
+       CPU_DONT_CARE
+};
+
+static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
+                       void **replyp, size_t size)
+{
+       struct sk_buff *skb;
+       void *reply;
+
+       /*
+        * If new attributes are added, please revisit this allocation
+        */
+       skb = nlmsg_new(size);
+       if (!skb)
+               return -ENOMEM;
+
+       if (!info) {
+               int seq = get_cpu_var(taskstats_seqnum)++;
+               put_cpu_var(taskstats_seqnum);
+
+               reply = genlmsg_put(skb, 0, seq,
+                               family.id, 0, 0,
+                               cmd, family.version);
+       } else
+               reply = genlmsg_put(skb, info->snd_pid, info->snd_seq,
+                               family.id, 0, 0,
+                               cmd, family.version);
+       if (reply == NULL) {
+               nlmsg_free(skb);
+               return -EINVAL;
+       }
+
+       *skbp = skb;
+       *replyp = reply;
+       return 0;
+}
+
+/*
+ * Send taskstats data in @skb to listener with nl_pid @pid
+ */
+static int send_reply(struct sk_buff *skb, pid_t pid)
+{
+       struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
+       void *reply = genlmsg_data(genlhdr);
+       int rc;
+
+       rc = genlmsg_end(skb, reply);
+       if (rc < 0) {
+               nlmsg_free(skb);
+               return rc;
+       }
+
+       return genlmsg_unicast(skb, pid);
+}
+
+/*
+ * Send taskstats data in @skb to listeners registered for @cpu's exit data
+ */
+static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
+{
+       struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
+       struct listener_list *listeners;
+       struct listener *s, *tmp;
+       struct sk_buff *skb_next, *skb_cur = skb;
+       void *reply = genlmsg_data(genlhdr);
+       int rc, delcount = 0;
+
+       rc = genlmsg_end(skb, reply);
+       if (rc < 0) {
+               nlmsg_free(skb);
+               return;
+       }
+
+       rc = 0;
+       listeners = &per_cpu(listener_array, cpu);
+       down_read(&listeners->sem);
+       list_for_each_entry(s, &listeners->list, list) {
+               skb_next = NULL;
+               if (!list_is_last(&s->list, &listeners->list)) {
+                       skb_next = skb_clone(skb_cur, GFP_KERNEL);
+                       if (!skb_next)
+                               break;
+               }
+               rc = genlmsg_unicast(skb_cur, s->pid);
+               if (rc == -ECONNREFUSED) {
+                       s->valid = 0;
+                       delcount++;
+               }
+               skb_cur = skb_next;
+       }
+       up_read(&listeners->sem);
+
+       if (skb_cur)
+               nlmsg_free(skb_cur);
+
+       if (!delcount)
+               return;
+
+       /* Delete invalidated entries */
+       down_write(&listeners->sem);
+       list_for_each_entry_safe(s, tmp, &listeners->list, list) {
+               if (!s->valid) {
+                       list_del(&s->list);
+                       kfree(s);
+               }
+       }
+       up_write(&listeners->sem);
+}
+
+static int fill_pid(pid_t pid, struct task_struct *pidtsk,
+               struct taskstats *stats)
+{
+       int rc = 0;
+       struct task_struct *tsk = pidtsk;
+
+       if (!pidtsk) {
+               read_lock(&tasklist_lock);
+               tsk = find_task_by_pid(pid);
+               if (!tsk) {
+                       read_unlock(&tasklist_lock);
+                       return -ESRCH;
+               }
+               get_task_struct(tsk);
+               read_unlock(&tasklist_lock);
+       } else
+               get_task_struct(tsk);
+
+       /*
+        * Each accounting subsystem adds calls to its functions to
+        * fill in relevant parts of struct taskstsats as follows
+        *
+        *      per-task-foo(stats, tsk);
+        */
+
+       delayacct_add_tsk(stats, tsk);
+       stats->version = TASKSTATS_VERSION;
+
+       /* Define err: label here if needed */
+       put_task_struct(tsk);
+       return rc;
+
+}
+
+static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk,
+               struct taskstats *stats)
+{
+       struct task_struct *tsk, *first;
+       unsigned long flags;
+
+       /*
+        * Add additional stats from live tasks except zombie thread group
+        * leaders who are already counted with the dead tasks
+        */
+       first = tgidtsk;
+       if (!first) {
+               read_lock(&tasklist_lock);
+               first = find_task_by_pid(tgid);
+               if (!first) {
+                       read_unlock(&tasklist_lock);
+                       return -ESRCH;
+               }
+               get_task_struct(first);
+               read_unlock(&tasklist_lock);
+       } else
+               get_task_struct(first);
+
+
+       tsk = first;
+       read_lock(&tasklist_lock);
+       /* Start with stats from dead tasks */
+       if (first->signal) {
+               spin_lock_irqsave(&first->signal->stats_lock, flags);
+               if (first->signal->stats)
+                       memcpy(stats, first->signal->stats, sizeof(*stats));
+               spin_unlock_irqrestore(&first->signal->stats_lock, flags);
+       }
+
+       do {
+               if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk))
+                       continue;
+               /*
+                * Accounting subsystem can call its functions here to
+                * fill in relevant parts of struct taskstsats as follows
+                *
+                *      per-task-foo(stats, tsk);
+                */
+               delayacct_add_tsk(stats, tsk);
+
+       } while_each_thread(first, tsk);
+       read_unlock(&tasklist_lock);
+       stats->version = TASKSTATS_VERSION;
+
+       /*
+        * Accounting subsytems can also add calls here to modify
+        * fields of taskstats.
+        */
+       put_task_struct(first);
+       return 0;
+}
+
+
+static void fill_tgid_exit(struct task_struct *tsk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&tsk->signal->stats_lock, flags);
+       if (!tsk->signal->stats)
+               goto ret;
+
+       /*
+        * Each accounting subsystem calls its functions here to
+        * accumalate its per-task stats for tsk, into the per-tgid structure
+        *
+        *      per-task-foo(tsk->signal->stats, tsk);
+        */
+       delayacct_add_tsk(tsk->signal->stats, tsk);
+ret:
+       spin_unlock_irqrestore(&tsk->signal->stats_lock, flags);
+       return;
+}
+
+static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
+{
+       struct listener_list *listeners;
+       struct listener *s, *tmp;
+       unsigned int cpu;
+       cpumask_t mask = *maskp;
+
+       if (!cpus_subset(mask, cpu_possible_map))
+               return -EINVAL;
+
+       if (isadd == REGISTER) {
+               for_each_cpu_mask(cpu, mask) {
+                       s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
+                                        cpu_to_node(cpu));
+                       if (!s)
+                               goto cleanup;
+                       s->pid = pid;
+                       INIT_LIST_HEAD(&s->list);
+                       s->valid = 1;
+
+                       listeners = &per_cpu(listener_array, cpu);
+                       down_write(&listeners->sem);
+                       list_add(&s->list, &listeners->list);
+                       up_write(&listeners->sem);
+               }
+               return 0;
+       }
+
+       /* Deregister or cleanup */
+cleanup:
+       for_each_cpu_mask(cpu, mask) {
+               listeners = &per_cpu(listener_array, cpu);
+               down_write(&listeners->sem);
+               list_for_each_entry_safe(s, tmp, &listeners->list, list) {
+                       if (s->pid == pid) {
+                               list_del(&s->list);
+                               kfree(s);
+                               break;
+                       }
+               }
+               up_write(&listeners->sem);
+       }
+       return 0;
+}
+
+static int parse(struct nlattr *na, cpumask_t *mask)
+{
+       char *data;
+       int len;
+       int ret;
+
+       if (na == NULL)
+               return 1;
+       len = nla_len(na);
+       if (len > TASKSTATS_CPUMASK_MAXLEN)
+               return -E2BIG;
+       if (len < 1)
+               return -EINVAL;
+       data = kmalloc(len, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       nla_strlcpy(data, na, len);
+       ret = cpulist_parse(data, *mask);
+       kfree(data);
+       return ret;
+}
+
+static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+       int rc = 0;
+       struct sk_buff *rep_skb;
+       struct taskstats stats;
+       void *reply;
+       size_t size;
+       struct nlattr *na;
+       cpumask_t mask;
+
+       rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask);
+       if (rc < 0)
+               return rc;
+       if (rc == 0)
+               return add_del_listener(info->snd_pid, &mask, REGISTER);
+
+       rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], &mask);
+       if (rc < 0)
+               return rc;
+       if (rc == 0)
+               return add_del_listener(info->snd_pid, &mask, DEREGISTER);
+
+       /*
+        * Size includes space for nested attributes
+        */
+       size = nla_total_size(sizeof(u32)) +
+               nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
+
+       memset(&stats, 0, sizeof(stats));
+       rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
+       if (rc < 0)
+               return rc;
+
+       if (info->attrs[TASKSTATS_CMD_ATTR_PID]) {
+               u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]);
+               rc = fill_pid(pid, NULL, &stats);
+               if (rc < 0)
+                       goto err;
+
+               na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID);
+               NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, pid);
+               NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
+                               stats);
+       } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) {
+               u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]);
+               rc = fill_tgid(tgid, NULL, &stats);
+               if (rc < 0)
+                       goto err;
+
+               na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID);
+               NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, tgid);
+               NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
+                               stats);
+       } else {
+               rc = -EINVAL;
+               goto err;
+       }
+
+       nla_nest_end(rep_skb, na);
+
+       return send_reply(rep_skb, info->snd_pid);
+
+nla_put_failure:
+       return genlmsg_cancel(rep_skb, reply);
+err:
+       nlmsg_free(rep_skb);
+       return rc;
+}
+
+void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu)
+{
+       struct listener_list *listeners;
+       struct taskstats *tmp;
+       /*
+        * This is the cpu on which the task is exiting currently and will
+        * be the one for which the exit event is sent, even if the cpu
+        * on which this function is running changes later.
+        */
+       *mycpu = raw_smp_processor_id();
+
+       *ptidstats = NULL;
+       tmp = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL);
+       if (!tmp)
+               return;
+
+       listeners = &per_cpu(listener_array, *mycpu);
+       down_read(&listeners->sem);
+       if (!list_empty(&listeners->list)) {
+               *ptidstats = tmp;
+               tmp = NULL;
+       }
+       up_read(&listeners->sem);
+       kfree(tmp);
+}
+
+/* Send pid data out on exit */
+void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats,
+                       int group_dead, unsigned int mycpu)
+{
+       int rc;
+       struct sk_buff *rep_skb;
+       void *reply;
+       size_t size;
+       int is_thread_group;
+       struct nlattr *na;
+       unsigned long flags;
+
+       if (!family_registered || !tidstats)
+               return;
+
+       spin_lock_irqsave(&tsk->signal->stats_lock, flags);
+       is_thread_group = tsk->signal->stats ? 1 : 0;
+       spin_unlock_irqrestore(&tsk->signal->stats_lock, flags);
+
+       rc = 0;
+       /*
+        * Size includes space for nested attributes
+        */
+       size = nla_total_size(sizeof(u32)) +
+               nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
+
+       if (is_thread_group)
+               size = 2 * size;        /* PID + STATS + TGID + STATS */
+
+       rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size);
+       if (rc < 0)
+               goto ret;
+
+       rc = fill_pid(tsk->pid, tsk, tidstats);
+       if (rc < 0)
+               goto err_skb;
+
+       na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID);
+       NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, (u32)tsk->pid);
+       NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
+                       *tidstats);
+       nla_nest_end(rep_skb, na);
+
+       if (!is_thread_group)
+               goto send;
+
+       /*
+        * tsk has/had a thread group so fill the tsk->signal->stats structure
+        * Doesn't matter if tsk is the leader or the last group member leaving
+        */
+
+       fill_tgid_exit(tsk);
+       if (!group_dead)
+               goto send;
+
+       na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID);
+       NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid);
+       /* No locking needed for tsk->signal->stats since group is dead */
+       NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS,
+                       *tsk->signal->stats);
+       nla_nest_end(rep_skb, na);
+
+send:
+       send_cpu_listeners(rep_skb, mycpu);
+       return;
+
+nla_put_failure:
+       genlmsg_cancel(rep_skb, reply);
+       goto ret;
+err_skb:
+       nlmsg_free(rep_skb);
+ret:
+       return;
+}
+
+static struct genl_ops taskstats_ops = {
+       .cmd            = TASKSTATS_CMD_GET,
+       .doit           = taskstats_user_cmd,
+       .policy         = taskstats_cmd_get_policy,
+};
+
+/* Needed early in initialization */
+void __init taskstats_init_early(void)
+{
+       unsigned int i;
+
+       taskstats_cache = kmem_cache_create("taskstats_cache",
+                                               sizeof(struct taskstats),
+                                               0, SLAB_PANIC, NULL, NULL);
+       for_each_possible_cpu(i) {
+               INIT_LIST_HEAD(&(per_cpu(listener_array, i).list));
+               init_rwsem(&(per_cpu(listener_array, i).sem));
+       }
+}
+
+static int __init taskstats_init(void)
+{
+       int rc;
+
+       rc = genl_register_family(&family);
+       if (rc)
+               return rc;
+
+       rc = genl_register_ops(&family, &taskstats_ops);
+       if (rc < 0)
+               goto err;
+
+       family_registered = 1;
+       return 0;
+err:
+       genl_unregister_family(&family);
+       return rc;
+}
+
+/*
+ * late initcall ensures initialization of statistics collection
+ * mechanisms precedes initialization of the taskstats interface
+ */
+late_initcall(taskstats_init);
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
new file mode 100644 (file)
index 0000000..e1dfd8e
--- /dev/null
@@ -0,0 +1 @@
+obj-y += clocksource.o jiffies.o
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
new file mode 100644 (file)
index 0000000..74eca59
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * linux/kernel/time/clocksource.c
+ *
+ * This file contains the functions which manage clocksource drivers.
+ *
+ * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO WishList:
+ *   o Allow clocksource drivers to be unregistered
+ *   o get rid of clocksource_jiffies extern
+ */
+
+#include <linux/clocksource.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+/* XXX - Would like a better way for initializing curr_clocksource */
+extern struct clocksource clocksource_jiffies;
+
+/*[Clocksource internal variables]---------
+ * curr_clocksource:
+ *     currently selected clocksource. Initialized to clocksource_jiffies.
+ * next_clocksource:
+ *     pending next selected clocksource.
+ * clocksource_list:
+ *     linked list with the registered clocksources
+ * clocksource_lock:
+ *     protects manipulations to curr_clocksource and next_clocksource
+ *     and the clocksource_list
+ * override_name:
+ *     Name of the user-specified clocksource.
+ */
+static struct clocksource *curr_clocksource = &clocksource_jiffies;
+static struct clocksource *next_clocksource;
+static LIST_HEAD(clocksource_list);
+static DEFINE_SPINLOCK(clocksource_lock);
+static char override_name[32];
+static int finished_booting;
+
+/* clocksource_done_booting - Called near the end of bootup
+ *
+ * Hack to avoid lots of clocksource churn at boot time
+ */
+static int __init clocksource_done_booting(void)
+{
+       finished_booting = 1;
+       return 0;
+}
+
+late_initcall(clocksource_done_booting);
+
+/**
+ * clocksource_get_next - Returns the selected clocksource
+ *
+ */
+struct clocksource *clocksource_get_next(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocksource_lock, flags);
+       if (next_clocksource && finished_booting) {
+               curr_clocksource = next_clocksource;
+               next_clocksource = NULL;
+       }
+       spin_unlock_irqrestore(&clocksource_lock, flags);
+
+       return curr_clocksource;
+}
+
+/**
+ * select_clocksource - Finds the best registered clocksource.
+ *
+ * Private function. Must hold clocksource_lock when called.
+ *
+ * Looks through the list of registered clocksources, returning
+ * the one with the highest rating value. If there is a clocksource
+ * name that matches the override string, it returns that clocksource.
+ */
+static struct clocksource *select_clocksource(void)
+{
+       struct clocksource *best = NULL;
+       struct list_head *tmp;
+
+       list_for_each(tmp, &clocksource_list) {
+               struct clocksource *src;
+
+               src = list_entry(tmp, struct clocksource, list);
+               if (!best)
+                       best = src;
+
+               /* check for override: */
+               if (strlen(src->name) == strlen(override_name) &&
+                   !strcmp(src->name, override_name)) {
+                       best = src;
+                       break;
+               }
+               /* pick the highest rating: */
+               if (src->rating > best->rating)
+                       best = src;
+       }
+
+       return best;
+}
+
+/**
+ * is_registered_source - Checks if clocksource is registered
+ * @c:         pointer to a clocksource
+ *
+ * Private helper function. Must hold clocksource_lock when called.
+ *
+ * Returns one if the clocksource is already registered, zero otherwise.
+ */
+static int is_registered_source(struct clocksource *c)
+{
+       int len = strlen(c->name);
+       struct list_head *tmp;
+
+       list_for_each(tmp, &clocksource_list) {
+               struct clocksource *src;
+
+               src = list_entry(tmp, struct clocksource, list);
+               if (strlen(src->name) == len && !strcmp(src->name, c->name))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * clocksource_register - Used to install new clocksources
+ * @t:         clocksource to be registered
+ *
+ * Returns -EBUSY if registration fails, zero otherwise.
+ */
+int clocksource_register(struct clocksource *c)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocksource_lock, flags);
+       /* check if clocksource is already registered */
+       if (is_registered_source(c)) {
+               printk("register_clocksource: Cannot register %s. "
+                       "Already registered!", c->name);
+               ret = -EBUSY;
+       } else {
+               /* register it */
+               list_add(&c->list, &clocksource_list);
+               /* scan the registered clocksources, and pick the best one */
+               next_clocksource = select_clocksource();
+       }
+       spin_unlock_irqrestore(&clocksource_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(clocksource_register);
+
+/**
+ * clocksource_reselect - Rescan list for next clocksource
+ *
+ * A quick helper function to be used if a clocksource changes its
+ * rating. Forces the clocksource list to be re-scanned for the best
+ * clocksource.
+ */
+void clocksource_reselect(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocksource_lock, flags);
+       next_clocksource = select_clocksource();
+       spin_unlock_irqrestore(&clocksource_lock, flags);
+}
+EXPORT_SYMBOL(clocksource_reselect);
+
+/**
+ * sysfs_show_current_clocksources - sysfs interface for current clocksource
+ * @dev:       unused
+ * @buf:       char buffer to be filled with clocksource list
+ *
+ * Provides sysfs interface for listing current clocksource.
+ */
+static ssize_t
+sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
+{
+       char *curr = buf;
+
+       spin_lock_irq(&clocksource_lock);
+       curr += sprintf(curr, "%s ", curr_clocksource->name);
+       spin_unlock_irq(&clocksource_lock);
+
+       curr += sprintf(curr, "\n");
+
+       return curr - buf;
+}
+
+/**
+ * sysfs_override_clocksource - interface for manually overriding clocksource
+ * @dev:       unused
+ * @buf:       name of override clocksource
+ * @count:     length of buffer
+ *
+ * Takes input from sysfs interface for manually overriding the default
+ * clocksource selction.
+ */
+static ssize_t sysfs_override_clocksource(struct sys_device *dev,
+                                         const char *buf, size_t count)
+{
+       size_t ret = count;
+       /* strings from sysfs write are not 0 terminated! */
+       if (count >= sizeof(override_name))
+               return -EINVAL;
+
+       /* strip of \n: */
+       if (buf[count-1] == '\n')
+               count--;
+       if (count < 1)
+               return -EINVAL;
+
+       spin_lock_irq(&clocksource_lock);
+
+       /* copy the name given: */
+       memcpy(override_name, buf, count);
+       override_name[count] = 0;
+
+       /* try to select it: */
+       next_clocksource = select_clocksource();
+
+       spin_unlock_irq(&clocksource_lock);
+
+       return ret;
+}
+
+/**
+ * sysfs_show_available_clocksources - sysfs interface for listing clocksource
+ * @dev:       unused
+ * @buf:       char buffer to be filled with clocksource list
+ *
+ * Provides sysfs interface for listing registered clocksources
+ */
+static ssize_t
+sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
+{
+       struct list_head *tmp;
+       char *curr = buf;
+
+       spin_lock_irq(&clocksource_lock);
+       list_for_each(tmp, &clocksource_list) {
+               struct clocksource *src;
+
+               src = list_entry(tmp, struct clocksource, list);
+               curr += sprintf(curr, "%s ", src->name);
+       }
+       spin_unlock_irq(&clocksource_lock);
+
+       curr += sprintf(curr, "\n");
+
+       return curr - buf;
+}
+
+/*
+ * Sysfs setup bits:
+ */
+static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources,
+                       sysfs_override_clocksource);
+
+static SYSDEV_ATTR(available_clocksource, 0600,
+                       sysfs_show_available_clocksources, NULL);
+
+static struct sysdev_class clocksource_sysclass = {
+       set_kset_name("clocksource"),
+};
+
+static struct sys_device device_clocksource = {
+       .id     = 0,
+       .cls    = &clocksource_sysclass,
+};
+
+static int __init init_clocksource_sysfs(void)
+{
+       int error = sysdev_class_register(&clocksource_sysclass);
+
+       if (!error)
+               error = sysdev_register(&device_clocksource);
+       if (!error)
+               error = sysdev_create_file(
+                               &device_clocksource,
+                               &attr_current_clocksource);
+       if (!error)
+               error = sysdev_create_file(
+                               &device_clocksource,
+                               &attr_available_clocksource);
+       return error;
+}
+
+device_initcall(init_clocksource_sysfs);
+
+/**
+ * boot_override_clocksource - boot clock override
+ * @str:       override name
+ *
+ * Takes a clocksource= boot argument and uses it
+ * as the clocksource override name.
+ */
+static int __init boot_override_clocksource(char* str)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&clocksource_lock, flags);
+       if (str)
+               strlcpy(override_name, str, sizeof(override_name));
+       spin_unlock_irqrestore(&clocksource_lock, flags);
+       return 1;
+}
+
+__setup("clocksource=", boot_override_clocksource);
+
+/**
+ * boot_override_clock - Compatibility layer for deprecated boot option
+ * @str:       override name
+ *
+ * DEPRECATED! Takes a clock= boot argument and uses it
+ * as the clocksource override name
+ */
+static int __init boot_override_clock(char* str)
+{
+       if (!strcmp(str, "pmtmr")) {
+               printk("Warning: clock=pmtmr is deprecated. "
+                       "Use clocksource=acpi_pm.\n");
+               return boot_override_clocksource("acpi_pm");
+       }
+       printk("Warning! clock= boot option is deprecated. "
+               "Use clocksource=xyz\n");
+       return boot_override_clocksource(str);
+}
+
+__setup("clock=", boot_override_clock);
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
new file mode 100644 (file)
index 0000000..126bb30
--- /dev/null
@@ -0,0 +1,73 @@
+/***********************************************************************
+* linux/kernel/time/jiffies.c
+*
+* This file contains the jiffies based clocksource.
+*
+* Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+************************************************************************/
+#include <linux/clocksource.h>
+#include <linux/jiffies.h>
+#include <linux/init.h>
+
+/* The Jiffies based clocksource is the lowest common
+ * denominator clock source which should function on
+ * all systems. It has the same coarse resolution as
+ * the timer interrupt frequency HZ and it suffers
+ * inaccuracies caused by missed or lost timer
+ * interrupts and the inability for the timer
+ * interrupt hardware to accuratly tick at the
+ * requested HZ value. It is also not reccomended
+ * for "tick-less" systems.
+ */
+#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ))
+
+/* Since jiffies uses a simple NSEC_PER_JIFFY multiplier
+ * conversion, the .shift value could be zero. However
+ * this would make NTP adjustments impossible as they are
+ * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to
+ * shift both the nominator and denominator the same
+ * amount, and give ntp adjustments in units of 1/2^8
+ *
+ * The value 8 is somewhat carefully chosen, as anything
+ * larger can result in overflows. NSEC_PER_JIFFY grows as
+ * HZ shrinks, so values greater then 8 overflow 32bits when
+ * HZ=100.
+ */
+#define JIFFIES_SHIFT  8
+
+static cycle_t jiffies_read(void)
+{
+       return (cycle_t) jiffies;
+}
+
+struct clocksource clocksource_jiffies = {
+       .name           = "jiffies",
+       .rating         = 0, /* lowest rating*/
+       .read           = jiffies_read,
+       .mask           = 0xffffffff, /*32bits*/
+       .mult           = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
+       .shift          = JIFFIES_SHIFT,
+       .is_continuous  = 0, /* tick based, not free running */
+};
+
+static int __init init_jiffies_clocksource(void)
+{
+       return clocksource_register(&clocksource_jiffies);
+}
+
+module_init(init_jiffies_clocksource);
diff --git a/kernel/unwind.c b/kernel/unwind.c
new file mode 100644 (file)
index 0000000..47281af
--- /dev/null
@@ -0,0 +1,920 @@
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *     Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ *
+ * A simple API for unwinding kernel stacks.  This is used for
+ * debugging and error reporting purposes.  The kernel doesn't need
+ * full-blown stack unwinding with all the bells and whistles, so there
+ * is not much point in implementing the full Dwarf2 unwind API.
+ */
+
+#include <linux/unwind.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/stop_machine.h>
+#include <asm/sections.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+
+extern char __start_unwind[], __end_unwind[];
+
+#define MAX_STACK_DEPTH 8
+
+#define EXTRA_INFO(f) { \
+               BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
+                                 % FIELD_SIZEOF(struct unwind_frame_info, f)) \
+               + offsetof(struct unwind_frame_info, f) \
+                 / FIELD_SIZEOF(struct unwind_frame_info, f), \
+               FIELD_SIZEOF(struct unwind_frame_info, f) \
+       }
+#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
+
+static const struct {
+       unsigned offs:BITS_PER_LONG / 2;
+       unsigned width:BITS_PER_LONG / 2;
+} reg_info[] = {
+       UNW_REGISTER_INFO
+};
+
+#undef PTREGS_INFO
+#undef EXTRA_INFO
+
+#ifndef REG_INVALID
+#define REG_INVALID(r) (reg_info[r].width == 0)
+#endif
+
+#define DW_CFA_nop                          0x00
+#define DW_CFA_set_loc                      0x01
+#define DW_CFA_advance_loc1                 0x02
+#define DW_CFA_advance_loc2                 0x03
+#define DW_CFA_advance_loc4                 0x04
+#define DW_CFA_offset_extended              0x05
+#define DW_CFA_restore_extended             0x06
+#define DW_CFA_undefined                    0x07
+#define DW_CFA_same_value                   0x08
+#define DW_CFA_register                     0x09
+#define DW_CFA_remember_state               0x0a
+#define DW_CFA_restore_state                0x0b
+#define DW_CFA_def_cfa                      0x0c
+#define DW_CFA_def_cfa_register             0x0d
+#define DW_CFA_def_cfa_offset               0x0e
+#define DW_CFA_def_cfa_expression           0x0f
+#define DW_CFA_expression                   0x10
+#define DW_CFA_offset_extended_sf           0x11
+#define DW_CFA_def_cfa_sf                   0x12
+#define DW_CFA_def_cfa_offset_sf            0x13
+#define DW_CFA_val_offset                   0x14
+#define DW_CFA_val_offset_sf                0x15
+#define DW_CFA_val_expression               0x16
+#define DW_CFA_lo_user                      0x1c
+#define DW_CFA_GNU_window_save              0x2d
+#define DW_CFA_GNU_args_size                0x2e
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+#define DW_CFA_hi_user                      0x3f
+
+#define DW_EH_PE_FORM     0x07
+#define DW_EH_PE_native   0x00
+#define DW_EH_PE_leb128   0x01
+#define DW_EH_PE_data2    0x02
+#define DW_EH_PE_data4    0x03
+#define DW_EH_PE_data8    0x04
+#define DW_EH_PE_signed   0x08
+#define DW_EH_PE_ADJUST   0x70
+#define DW_EH_PE_abs      0x00
+#define DW_EH_PE_pcrel    0x10
+#define DW_EH_PE_textrel  0x20
+#define DW_EH_PE_datarel  0x30
+#define DW_EH_PE_funcrel  0x40
+#define DW_EH_PE_aligned  0x50
+#define DW_EH_PE_indirect 0x80
+#define DW_EH_PE_omit     0xff
+
+typedef unsigned long uleb128_t;
+typedef   signed long sleb128_t;
+
+static struct unwind_table {
+       struct {
+               unsigned long pc;
+               unsigned long range;
+       } core, init;
+       const void *address;
+       unsigned long size;
+       struct unwind_table *link;
+       const char *name;
+} root_table;
+
+struct unwind_item {
+       enum item_location {
+               Nowhere,
+               Memory,
+               Register,
+               Value
+       } where;
+       uleb128_t value;
+};
+
+struct unwind_state {
+       uleb128_t loc, org;
+       const u8 *cieStart, *cieEnd;
+       uleb128_t codeAlign;
+       sleb128_t dataAlign;
+       struct cfa {
+               uleb128_t reg, offs;
+       } cfa;
+       struct unwind_item regs[ARRAY_SIZE(reg_info)];
+       unsigned stackDepth:8;
+       unsigned version:8;
+       const u8 *label;
+       const u8 *stack[MAX_STACK_DEPTH];
+};
+
+static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
+
+static struct unwind_table *find_table(unsigned long pc)
+{
+       struct unwind_table *table;
+
+       for (table = &root_table; table; table = table->link)
+               if ((pc >= table->core.pc
+                    && pc < table->core.pc + table->core.range)
+                   || (pc >= table->init.pc
+                       && pc < table->init.pc + table->init.range))
+                       break;
+
+       return table;
+}
+
+static void init_unwind_table(struct unwind_table *table,
+                              const char *name,
+                              const void *core_start,
+                              unsigned long core_size,
+                              const void *init_start,
+                              unsigned long init_size,
+                              const void *table_start,
+                              unsigned long table_size)
+{
+       table->core.pc = (unsigned long)core_start;
+       table->core.range = core_size;
+       table->init.pc = (unsigned long)init_start;
+       table->init.range = init_size;
+       table->address = table_start;
+       table->size = table_size;
+       table->link = NULL;
+       table->name = name;
+}
+
+void __init unwind_init(void)
+{
+       init_unwind_table(&root_table, "kernel",
+                         _text, _end - _text,
+                         NULL, 0,
+                         __start_unwind, __end_unwind - __start_unwind);
+}
+
+#ifdef CONFIG_MODULES
+
+static struct unwind_table *last_table;
+
+/* Must be called with module_mutex held. */
+void *unwind_add_table(struct module *module,
+                       const void *table_start,
+                       unsigned long table_size)
+{
+       struct unwind_table *table;
+
+       if (table_size <= 0)
+               return NULL;
+
+       table = kmalloc(sizeof(*table), GFP_KERNEL);
+       if (!table)
+               return NULL;
+
+       init_unwind_table(table, module->name,
+                         module->module_core, module->core_size,
+                         module->module_init, module->init_size,
+                         table_start, table_size);
+
+       if (last_table)
+               last_table->link = table;
+       else
+               root_table.link = table;
+       last_table = table;
+
+       return table;
+}
+
+struct unlink_table_info
+{
+       struct unwind_table *table;
+       int init_only;
+};
+
+static int unlink_table(void *arg)
+{
+       struct unlink_table_info *info = arg;
+       struct unwind_table *table = info->table, *prev;
+
+       for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
+               ;
+
+       if (prev->link) {
+               if (info->init_only) {
+                       table->init.pc = 0;
+                       table->init.range = 0;
+                       info->table = NULL;
+               } else {
+                       prev->link = table->link;
+                       if (!prev->link)
+                               last_table = prev;
+               }
+       } else
+               info->table = NULL;
+
+       return 0;
+}
+
+/* Must be called with module_mutex held. */
+void unwind_remove_table(void *handle, int init_only)
+{
+       struct unwind_table *table = handle;
+       struct unlink_table_info info;
+
+       if (!table || table == &root_table)
+               return;
+
+       if (init_only && table == last_table) {
+               table->init.pc = 0;
+               table->init.range = 0;
+               return;
+       }
+
+       info.table = table;
+       info.init_only = init_only;
+       stop_machine_run(unlink_table, &info, NR_CPUS);
+
+       if (info.table)
+               kfree(table);
+}
+
+#endif /* CONFIG_MODULES */
+
+static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
+{
+       const u8 *cur = *pcur;
+       uleb128_t value;
+       unsigned shift;
+
+       for (shift = 0, value = 0; cur < end; shift += 7) {
+               if (shift + 7 > 8 * sizeof(value)
+                   && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+                       cur = end + 1;
+                       break;
+               }
+               value |= (uleb128_t)(*cur & 0x7f) << shift;
+               if (!(*cur++ & 0x80))
+                       break;
+       }
+       *pcur = cur;
+
+       return value;
+}
+
+static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
+{
+       const u8 *cur = *pcur;
+       sleb128_t value;
+       unsigned shift;
+
+       for (shift = 0, value = 0; cur < end; shift += 7) {
+               if (shift + 7 > 8 * sizeof(value)
+                   && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+                       cur = end + 1;
+                       break;
+               }
+               value |= (sleb128_t)(*cur & 0x7f) << shift;
+               if (!(*cur & 0x80)) {
+                       value |= -(*cur++ & 0x40) << shift;
+                       break;
+               }
+       }
+       *pcur = cur;
+
+       return value;
+}
+
+static unsigned long read_pointer(const u8 **pLoc,
+                                  const void *end,
+                                  signed ptrType)
+{
+       unsigned long value = 0;
+       union {
+               const u8 *p8;
+               const u16 *p16u;
+               const s16 *p16s;
+               const u32 *p32u;
+               const s32 *p32s;
+               const unsigned long *pul;
+       } ptr;
+
+       if (ptrType < 0 || ptrType == DW_EH_PE_omit)
+               return 0;
+       ptr.p8 = *pLoc;
+       switch(ptrType & DW_EH_PE_FORM) {
+       case DW_EH_PE_data2:
+               if (end < (const void *)(ptr.p16u + 1))
+                       return 0;
+               if(ptrType & DW_EH_PE_signed)
+                       value = get_unaligned(ptr.p16s++);
+               else
+                       value = get_unaligned(ptr.p16u++);
+               break;
+       case DW_EH_PE_data4:
+#ifdef CONFIG_64BIT
+               if (end < (const void *)(ptr.p32u + 1))
+                       return 0;
+               if(ptrType & DW_EH_PE_signed)
+                       value = get_unaligned(ptr.p32s++);
+               else
+                       value = get_unaligned(ptr.p32u++);
+               break;
+       case DW_EH_PE_data8:
+               BUILD_BUG_ON(sizeof(u64) != sizeof(value));
+#else
+               BUILD_BUG_ON(sizeof(u32) != sizeof(value));
+#endif
+       case DW_EH_PE_native:
+               if (end < (const void *)(ptr.pul + 1))
+                       return 0;
+               value = get_unaligned(ptr.pul++);
+               break;
+       case DW_EH_PE_leb128:
+               BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
+               value = ptrType & DW_EH_PE_signed
+                       ? get_sleb128(&ptr.p8, end)
+                       : get_uleb128(&ptr.p8, end);
+               if ((const void *)ptr.p8 > end)
+                       return 0;
+               break;
+       default:
+               return 0;
+       }
+       switch(ptrType & DW_EH_PE_ADJUST) {
+       case DW_EH_PE_abs:
+               break;
+       case DW_EH_PE_pcrel:
+               value += (unsigned long)*pLoc;
+               break;
+       default:
+               return 0;
+       }
+       if ((ptrType & DW_EH_PE_indirect)
+           && __get_user(value, (unsigned long *)value))
+               return 0;
+       *pLoc = ptr.p8;
+
+       return value;
+}
+
+static signed fde_pointer_type(const u32 *cie)
+{
+       const u8 *ptr = (const u8 *)(cie + 2);
+       unsigned version = *ptr;
+
+       if (version != 1)
+               return -1; /* unsupported */
+       if (*++ptr) {
+               const char *aug;
+               const u8 *end = (const u8 *)(cie + 1) + *cie;
+               uleb128_t len;
+
+               /* check if augmentation size is first (and thus present) */
+               if (*ptr != 'z')
+                       return -1;
+               /* check if augmentation string is nul-terminated */
+               if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
+                       return -1;
+               ++ptr; /* skip terminator */
+               get_uleb128(&ptr, end); /* skip code alignment */
+               get_sleb128(&ptr, end); /* skip data alignment */
+               /* skip return address column */
+               version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
+               len = get_uleb128(&ptr, end); /* augmentation length */
+               if (ptr + len < ptr || ptr + len > end)
+                       return -1;
+               end = ptr + len;
+               while (*++aug) {
+                       if (ptr >= end)
+                               return -1;
+                       switch(*aug) {
+                       case 'L':
+                               ++ptr;
+                               break;
+                       case 'P': {
+                                       signed ptrType = *ptr++;
+
+                                       if (!read_pointer(&ptr, end, ptrType) || ptr > end)
+                                               return -1;
+                               }
+                               break;
+                       case 'R':
+                               return *ptr;
+                       default:
+                               return -1;
+                       }
+               }
+       }
+       return DW_EH_PE_native|DW_EH_PE_abs;
+}
+
+static int advance_loc(unsigned long delta, struct unwind_state *state)
+{
+       state->loc += delta * state->codeAlign;
+
+       return delta > 0;
+}
+
+static void set_rule(uleb128_t reg,
+                     enum item_location where,
+                     uleb128_t value,
+                     struct unwind_state *state)
+{
+       if (reg < ARRAY_SIZE(state->regs)) {
+               state->regs[reg].where = where;
+               state->regs[reg].value = value;
+       }
+}
+
+static int processCFI(const u8 *start,
+                      const u8 *end,
+                      unsigned long targetLoc,
+                      signed ptrType,
+                      struct unwind_state *state)
+{
+       union {
+               const u8 *p8;
+               const u16 *p16;
+               const u32 *p32;
+       } ptr;
+       int result = 1;
+
+       if (start != state->cieStart) {
+               state->loc = state->org;
+               result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
+               if (targetLoc == 0 && state->label == NULL)
+                       return result;
+       }
+       for (ptr.p8 = start; result && ptr.p8 < end; ) {
+               switch(*ptr.p8 >> 6) {
+                       uleb128_t value;
+
+               case 0:
+                       switch(*ptr.p8++) {
+                       case DW_CFA_nop:
+                               break;
+                       case DW_CFA_set_loc:
+                               if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
+                                       result = 0;
+                               break;
+                       case DW_CFA_advance_loc1:
+                               result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
+                               break;
+                       case DW_CFA_advance_loc2:
+                               result = ptr.p8 <= end + 2
+                                        && advance_loc(*ptr.p16++, state);
+                               break;
+                       case DW_CFA_advance_loc4:
+                               result = ptr.p8 <= end + 4
+                                        && advance_loc(*ptr.p32++, state);
+                               break;
+                       case DW_CFA_offset_extended:
+                               value = get_uleb128(&ptr.p8, end);
+                               set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
+                               break;
+                       case DW_CFA_val_offset:
+                               value = get_uleb128(&ptr.p8, end);
+                               set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
+                               break;
+                       case DW_CFA_offset_extended_sf:
+                               value = get_uleb128(&ptr.p8, end);
+                               set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
+                               break;
+                       case DW_CFA_val_offset_sf:
+                               value = get_uleb128(&ptr.p8, end);
+                               set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
+                               break;
+                       case DW_CFA_restore_extended:
+                       case DW_CFA_undefined:
+                       case DW_CFA_same_value:
+                               set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
+                               break;
+                       case DW_CFA_register:
+                               value = get_uleb128(&ptr.p8, end);
+                               set_rule(value,
+                                        Register,
+                                        get_uleb128(&ptr.p8, end), state);
+                               break;
+                       case DW_CFA_remember_state:
+                               if (ptr.p8 == state->label) {
+                                       state->label = NULL;
+                                       return 1;
+                               }
+                               if (state->stackDepth >= MAX_STACK_DEPTH)
+                                       return 0;
+                               state->stack[state->stackDepth++] = ptr.p8;
+                               break;
+                       case DW_CFA_restore_state:
+                               if (state->stackDepth) {
+                                       const uleb128_t loc = state->loc;
+                                       const u8 *label = state->label;
+
+                                       state->label = state->stack[state->stackDepth - 1];
+                                       memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
+                                       memset(state->regs, 0, sizeof(state->regs));
+                                       state->stackDepth = 0;
+                                       result = processCFI(start, end, 0, ptrType, state);
+                                       state->loc = loc;
+                                       state->label = label;
+                               } else
+                                       return 0;
+                               break;
+                       case DW_CFA_def_cfa:
+                               state->cfa.reg = get_uleb128(&ptr.p8, end);
+                               /*nobreak*/
+                       case DW_CFA_def_cfa_offset:
+                               state->cfa.offs = get_uleb128(&ptr.p8, end);
+                               break;
+                       case DW_CFA_def_cfa_sf:
+                               state->cfa.reg = get_uleb128(&ptr.p8, end);
+                               /*nobreak*/
+                       case DW_CFA_def_cfa_offset_sf:
+                               state->cfa.offs = get_sleb128(&ptr.p8, end)
+                                                 * state->dataAlign;
+                               break;
+                       case DW_CFA_def_cfa_register:
+                               state->cfa.reg = get_uleb128(&ptr.p8, end);
+                               break;
+                       /*todo case DW_CFA_def_cfa_expression: */
+                       /*todo case DW_CFA_expression: */
+                       /*todo case DW_CFA_val_expression: */
+                       case DW_CFA_GNU_args_size:
+                               get_uleb128(&ptr.p8, end);
+                               break;
+                       case DW_CFA_GNU_negative_offset_extended:
+                               value = get_uleb128(&ptr.p8, end);
+                               set_rule(value,
+                                        Memory,
+                                        (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
+                               break;
+                       case DW_CFA_GNU_window_save:
+                       default:
+                               result = 0;
+                               break;
+                       }
+                       break;
+               case 1:
+                       result = advance_loc(*ptr.p8++ & 0x3f, state);
+                       break;
+               case 2:
+                       value = *ptr.p8++ & 0x3f;
+                       set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
+                       break;
+               case 3:
+                       set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
+                       break;
+               }
+               if (ptr.p8 > end)
+                       result = 0;
+               if (result && targetLoc != 0 && targetLoc < state->loc)
+                       return 1;
+       }
+
+       return result
+          && ptr.p8 == end
+          && (targetLoc == 0
+           || (/*todo While in theory this should apply, gcc in practice omits
+                 everything past the function prolog, and hence the location
+                 never reaches the end of the function.
+               targetLoc < state->loc &&*/ state->label == NULL));
+}
+
+/* Unwind to previous to frame.  Returns 0 if successful, negative
+ * number in case of an error. */
+int unwind(struct unwind_frame_info *frame)
+{
+#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
+       const u32 *fde = NULL, *cie = NULL;
+       const u8 *ptr = NULL, *end = NULL;
+       unsigned long startLoc = 0, endLoc = 0, cfa;
+       unsigned i;
+       signed ptrType = -1;
+       uleb128_t retAddrReg = 0;
+       struct unwind_table *table;
+       struct unwind_state state;
+
+       if (UNW_PC(frame) == 0)
+               return -EINVAL;
+       if ((table = find_table(UNW_PC(frame))) != NULL
+           && !(table->size & (sizeof(*fde) - 1))) {
+               unsigned long tableSize = table->size;
+
+               for (fde = table->address;
+                    tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
+                    tableSize -= sizeof(*fde) + *fde,
+                    fde += 1 + *fde / sizeof(*fde)) {
+                       if (!*fde || (*fde & (sizeof(*fde) - 1)))
+                               break;
+                       if (!fde[1])
+                               continue; /* this is a CIE */
+                       if ((fde[1] & (sizeof(*fde) - 1))
+                           || fde[1] > (unsigned long)(fde + 1)
+                                       - (unsigned long)table->address)
+                               continue; /* this is not a valid FDE */
+                       cie = fde + 1 - fde[1] / sizeof(*fde);
+                       if (*cie <= sizeof(*cie) + 4
+                           || *cie >= fde[1] - sizeof(*fde)
+                           || (*cie & (sizeof(*cie) - 1))
+                           || cie[1]
+                           || (ptrType = fde_pointer_type(cie)) < 0) {
+                               cie = NULL; /* this is not a (valid) CIE */
+                               continue;
+                       }
+                       ptr = (const u8 *)(fde + 2);
+                       startLoc = read_pointer(&ptr,
+                                               (const u8 *)(fde + 1) + *fde,
+                                               ptrType);
+                       endLoc = startLoc
+                                + read_pointer(&ptr,
+                                               (const u8 *)(fde + 1) + *fde,
+                                               ptrType & DW_EH_PE_indirect
+                                               ? ptrType
+                                               : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
+                       if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
+                               break;
+                       cie = NULL;
+               }
+       }
+       if (cie != NULL) {
+               memset(&state, 0, sizeof(state));
+               state.cieEnd = ptr; /* keep here temporarily */
+               ptr = (const u8 *)(cie + 2);
+               end = (const u8 *)(cie + 1) + *cie;
+               if ((state.version = *ptr) != 1)
+                       cie = NULL; /* unsupported version */
+               else if (*++ptr) {
+                       /* check if augmentation size is first (and thus present) */
+                       if (*ptr == 'z') {
+                               /* check for ignorable (or already handled)
+                                * nul-terminated augmentation string */
+                               while (++ptr < end && *ptr)
+                                       if (strchr("LPR", *ptr) == NULL)
+                                               break;
+                       }
+                       if (ptr >= end || *ptr)
+                               cie = NULL;
+               }
+               ++ptr;
+       }
+       if (cie != NULL) {
+               /* get code aligment factor */
+               state.codeAlign = get_uleb128(&ptr, end);
+               /* get data aligment factor */
+               state.dataAlign = get_sleb128(&ptr, end);
+               if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
+                       cie = NULL;
+               else {
+                       retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
+                       /* skip augmentation */
+                       if (((const char *)(cie + 2))[1] == 'z')
+                               ptr += get_uleb128(&ptr, end);
+                       if (ptr > end
+                          || retAddrReg >= ARRAY_SIZE(reg_info)
+                          || REG_INVALID(retAddrReg)
+                          || reg_info[retAddrReg].width != sizeof(unsigned long))
+                               cie = NULL;
+               }
+       }
+       if (cie != NULL) {
+               state.cieStart = ptr;
+               ptr = state.cieEnd;
+               state.cieEnd = end;
+               end = (const u8 *)(fde + 1) + *fde;
+               /* skip augmentation */
+               if (((const char *)(cie + 2))[1] == 'z') {
+                       uleb128_t augSize = get_uleb128(&ptr, end);
+
+                       if ((ptr += augSize) > end)
+                               fde = NULL;
+               }
+       }
+       if (cie == NULL || fde == NULL) {
+#ifdef CONFIG_FRAME_POINTER
+               unsigned long top, bottom;
+#endif
+
+#ifdef CONFIG_FRAME_POINTER
+               top = STACK_TOP(frame->task);
+               bottom = STACK_BOTTOM(frame->task);
+# if FRAME_RETADDR_OFFSET < 0
+               if (UNW_SP(frame) < top
+                   && UNW_FP(frame) <= UNW_SP(frame)
+                   && bottom < UNW_FP(frame)
+# else
+               if (UNW_SP(frame) > top
+                   && UNW_FP(frame) >= UNW_SP(frame)
+                   && bottom > UNW_FP(frame)
+# endif
+                  && !((UNW_SP(frame) | UNW_FP(frame))
+                       & (sizeof(unsigned long) - 1))) {
+                       unsigned long link;
+
+                       if (!__get_user(link,
+                                       (unsigned long *)(UNW_FP(frame)
+                                                         + FRAME_LINK_OFFSET))
+# if FRAME_RETADDR_OFFSET < 0
+                          && link > bottom && link < UNW_FP(frame)
+# else
+                          && link > UNW_FP(frame) && link < bottom
+# endif
+                          && !(link & (sizeof(link) - 1))
+                          && !__get_user(UNW_PC(frame),
+                                         (unsigned long *)(UNW_FP(frame)
+                                                           + FRAME_RETADDR_OFFSET))) {
+                               UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
+# if FRAME_RETADDR_OFFSET < 0
+                                       -
+# else
+                                       +
+# endif
+                                         sizeof(UNW_PC(frame));
+                               UNW_FP(frame) = link;
+                               return 0;
+                       }
+               }
+#endif
+               return -ENXIO;
+       }
+       state.org = startLoc;
+       memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
+       /* process instructions */
+       if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
+          || state.loc > endLoc
+          || state.regs[retAddrReg].where == Nowhere
+          || state.cfa.reg >= ARRAY_SIZE(reg_info)
+          || reg_info[state.cfa.reg].width != sizeof(unsigned long)
+          || state.cfa.offs % sizeof(unsigned long))
+               return -EIO;
+       /* update frame */
+       cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
+       startLoc = min((unsigned long)UNW_SP(frame), cfa);
+       endLoc = max((unsigned long)UNW_SP(frame), cfa);
+       if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
+               startLoc = min(STACK_LIMIT(cfa), cfa);
+               endLoc = max(STACK_LIMIT(cfa), cfa);
+       }
+#ifndef CONFIG_64BIT
+# define CASES CASE(8); CASE(16); CASE(32)
+#else
+# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
+#endif
+       for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+               if (REG_INVALID(i)) {
+                       if (state.regs[i].where == Nowhere)
+                               continue;
+                       return -EIO;
+               }
+               switch(state.regs[i].where) {
+               default:
+                       break;
+               case Register:
+                       if (state.regs[i].value >= ARRAY_SIZE(reg_info)
+                          || REG_INVALID(state.regs[i].value)
+                          || reg_info[i].width > reg_info[state.regs[i].value].width)
+                               return -EIO;
+                       switch(reg_info[state.regs[i].value].width) {
+#define CASE(n) \
+                       case sizeof(u##n): \
+                               state.regs[i].value = FRAME_REG(state.regs[i].value, \
+                                                               const u##n); \
+                               break
+                       CASES;
+#undef CASE
+                       default:
+                               return -EIO;
+                       }
+                       break;
+               }
+       }
+       for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+               if (REG_INVALID(i))
+                       continue;
+               switch(state.regs[i].where) {
+               case Nowhere:
+                       if (reg_info[i].width != sizeof(UNW_SP(frame))
+                          || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
+                             != &UNW_SP(frame))
+                               continue;
+                       UNW_SP(frame) = cfa;
+                       break;
+               case Register:
+                       switch(reg_info[i].width) {
+#define CASE(n) case sizeof(u##n): \
+                               FRAME_REG(i, u##n) = state.regs[i].value; \
+                               break
+                       CASES;
+#undef CASE
+                       default:
+                               return -EIO;
+                       }
+                       break;
+               case Value:
+                       if (reg_info[i].width != sizeof(unsigned long))
+                               return -EIO;
+                       FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
+                                                           * state.dataAlign;
+                       break;
+               case Memory: {
+                               unsigned long addr = cfa + state.regs[i].value
+                                                          * state.dataAlign;
+
+                               if ((state.regs[i].value * state.dataAlign)
+                                   % sizeof(unsigned long)
+                                   || addr < startLoc
+                                   || addr + sizeof(unsigned long) < addr
+                                   || addr + sizeof(unsigned long) > endLoc)
+                                       return -EIO;
+                               switch(reg_info[i].width) {
+#define CASE(n)     case sizeof(u##n): \
+                                       __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
+                                       break
+                               CASES;
+#undef CASE
+                               default:
+                                       return -EIO;
+                               }
+                       }
+                       break;
+               }
+       }
+
+       return 0;
+#undef CASES
+#undef FRAME_REG
+}
+EXPORT_SYMBOL(unwind);
+
+int unwind_init_frame_info(struct unwind_frame_info *info,
+                           struct task_struct *tsk,
+                           /*const*/ struct pt_regs *regs)
+{
+       info->task = tsk;
+       arch_unw_init_frame_info(info, regs);
+
+       return 0;
+}
+EXPORT_SYMBOL(unwind_init_frame_info);
+
+/*
+ * Prepare to unwind a blocked task.
+ */
+int unwind_init_blocked(struct unwind_frame_info *info,
+                        struct task_struct *tsk)
+{
+       info->task = tsk;
+       arch_unw_init_blocked(info);
+
+       return 0;
+}
+EXPORT_SYMBOL(unwind_init_blocked);
+
+/*
+ * Prepare to unwind the currently running thread.
+ */
+int unwind_init_running(struct unwind_frame_info *info,
+                        asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                   void *arg),
+                        void *arg)
+{
+       info->task = current;
+
+       return arch_unwind_init_running(info, callback, arg);
+}
+EXPORT_SYMBOL(unwind_init_running);
+
+/*
+ * Unwind until the return pointer is in user-land (or until an error
+ * occurs).  Returns 0 if successful, negative number in case of
+ * error.
+ */
+int unwind_to_user(struct unwind_frame_info *info)
+{
+       while (!arch_unw_user_mode(info)) {
+               int err = unwind(info);
+
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(unwind_to_user);
diff --git a/kernel/utrace.c b/kernel/utrace.c
new file mode 100644 (file)
index 0000000..52d9b00
--- /dev/null
@@ -0,0 +1,1598 @@
+#include <linux/utrace.h>
+#include <linux/tracehook.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/tracehook.h>
+
+
+static kmem_cache_t *utrace_cachep;
+static kmem_cache_t *utrace_engine_cachep;
+
+static int __init
+utrace_init(void)
+{
+       utrace_cachep =
+               kmem_cache_create("utrace_cache",
+                                 sizeof(struct utrace), 0,
+                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       utrace_engine_cachep =
+               kmem_cache_create("utrace_engine_cache",
+                                 sizeof(struct utrace_attached_engine), 0,
+                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       return 0;
+}
+subsys_initcall(utrace_init);
+
+
+/*
+ * Make sure target->utrace is allocated, and return with it locked on
+ * success.  This function mediates startup races.  The creating parent
+ * task has priority, and other callers will delay here to let its call
+ * succeed and take the new utrace lock first.
+ */
+static struct utrace *
+utrace_first_engine(struct task_struct *target,
+                   struct utrace_attached_engine *engine)
+{
+       struct utrace *utrace, *ret;
+
+       /*
+        * If this is a newborn thread and we are not the creator,
+        * we have to wait for it.  The creator gets the first chance
+        * to attach.  The PF_STARTING flag is cleared after its
+        * report_clone hook has had a chance to run.
+        */
+       if ((target->flags & PF_STARTING)
+           && (current->utrace == NULL
+               || current->utrace->u.live.cloning != target)) {
+               yield();
+               return (signal_pending(current)
+                       ? ERR_PTR(-ERESTARTNOINTR) : NULL);
+       }
+
+       utrace = kmem_cache_alloc(utrace_cachep, SLAB_KERNEL);
+       if (unlikely(utrace == NULL))
+               return ERR_PTR(-ENOMEM);
+
+       utrace->u.live.cloning = NULL;
+       utrace->u.live.signal = NULL;
+       INIT_LIST_HEAD(&utrace->engines);
+       list_add(&engine->entry, &utrace->engines);
+       spin_lock_init(&utrace->lock);
+
+       ret = utrace;
+       utrace_lock(utrace);
+       task_lock(target);
+       if (likely(target->utrace == NULL)) {
+               rcu_assign_pointer(target->utrace, utrace);
+               /*
+                * The task_lock protects us against another thread doing
+                * the same thing.  We might still be racing against
+                * tracehook_release_task.  It's called with ->exit_state
+                * set to EXIT_DEAD and then checks ->utrace with an
+                * smp_mb() in between.  If EXIT_DEAD is set, then
+                * release_task might have checked ->utrace already and saw
+                * it NULL; we can't attach.  If we see EXIT_DEAD not yet
+                * set after our barrier, then we know release_task will
+                * see our target->utrace pointer.
+                */
+               smp_mb();
+               if (target->exit_state == EXIT_DEAD) {
+                       /*
+                        * The target has already been through release_task.
+                        */
+                       target->utrace = NULL;
+                       goto cannot_attach;
+               }
+               task_unlock(target);
+
+               /*
+                * If the thread is already dead when we attach, then its
+                * parent was notified already and we shouldn't repeat the
+                * notification later after a detach or NOREAP flag change.
+                */
+               if (target->exit_state)
+                       utrace->u.exit.notified = 1;
+       }
+       else {
+               /*
+                * Another engine attached first, so there is a struct already.
+                * A null return says to restart looking for the existing one.
+                */
+       cannot_attach:
+               ret = NULL;
+               task_unlock(target);
+               utrace_unlock(utrace);
+               kmem_cache_free(utrace_cachep, utrace);
+       }
+
+       return ret;
+}
+
+static void
+utrace_free(struct rcu_head *rhead)
+{
+       struct utrace *utrace = container_of(rhead, struct utrace, u.dead);
+       kmem_cache_free(utrace_cachep, utrace);
+}
+
+static void
+rcu_utrace_free(struct utrace *utrace)
+{
+       INIT_RCU_HEAD(&utrace->u.dead);
+       call_rcu(&utrace->u.dead, utrace_free);
+}
+
+static void
+utrace_engine_free(struct rcu_head *rhead)
+{
+       struct utrace_attached_engine *engine =
+               container_of(rhead, struct utrace_attached_engine, rhead);
+       kmem_cache_free(utrace_engine_cachep, engine);
+}
+
+/*
+ * Called with utrace locked and the target quiescent (maybe current).
+ * If this was the last engine, utrace is left locked and not freed,
+ * but is removed from the task.
+ */
+static void
+remove_engine(struct utrace_attached_engine *engine,
+             struct task_struct *tsk, struct utrace *utrace)
+{
+       list_del_rcu(&engine->entry);
+       if (list_empty(&utrace->engines)) {
+               task_lock(tsk);
+               if (likely(tsk->utrace != NULL)) {
+                       rcu_assign_pointer(tsk->utrace, NULL);
+                       tsk->utrace_flags = 0;
+               }
+               task_unlock(tsk);
+       }
+       call_rcu(&engine->rhead, utrace_engine_free);
+}
+
+/*
+ * This is pointed to by the utrace struct, but it's really a private
+ * structure between utrace_get_signal and utrace_inject_signal.
+ */
+struct utrace_signal
+{
+       siginfo_t *const info;
+       struct k_sigaction *return_ka;
+       int signr;
+};
+
+/*
+ * Called with utrace locked, after remove_engine may have run.
+ * Passed the flags from all remaining engines, i.e. zero if none left.
+ * Install the flags in tsk->utrace_flags and return with utrace unlocked.
+ * If no engines are left, utrace is freed and we return NULL.
+ */
+static struct utrace *
+check_dead_utrace(struct task_struct *tsk, struct utrace *utrace,
+                unsigned long flags)
+{
+       if (flags) {
+               tsk->utrace_flags = flags;
+               utrace_unlock(utrace);
+               return utrace;
+       }
+
+       if (utrace->u.live.signal && utrace->u.live.signal->signr != 0) {
+               utrace_unlock(utrace);
+               return utrace;
+       }
+
+       utrace_unlock(utrace);
+       rcu_utrace_free(utrace);
+       return NULL;
+}
+
+
+
+/*
+ * Get the target thread to quiesce.  Return nonzero if it's already quiescent.
+ * Return zero if it will report a QUIESCE event soon.
+ * If interrupt is nonzero, wake it like a signal would so it quiesces ASAP.
+ * If interrupt is zero, just make sure it quiesces before going to user mode.
+ */
+static int
+quiesce(struct task_struct *target, int interrupt)
+{
+       int quiescent;
+
+       target->utrace_flags |= UTRACE_ACTION_QUIESCE;
+       read_barrier_depends();
+
+       quiescent = (target->exit_state
+                    || target->state & (TASK_TRACED | TASK_STOPPED));
+
+       if (!quiescent) {
+               spin_lock_irq(&target->sighand->siglock);
+               quiescent = (unlikely(target->exit_state)
+                            || unlikely(target->state
+                                        & (TASK_TRACED | TASK_STOPPED)));
+               if (!quiescent) {
+                       if (interrupt)
+                               signal_wake_up(target, 0);
+                       else {
+                               set_tsk_thread_flag(target, TIF_SIGPENDING);
+                               kick_process(target);
+                       }
+               }
+               spin_unlock_irq(&target->sighand->siglock);
+       }
+
+       return quiescent;
+}
+
+
+static struct utrace_attached_engine *
+matching_engine(struct utrace *utrace, int flags,
+               const struct utrace_engine_ops *ops, unsigned long data)
+{
+       struct utrace_attached_engine *engine;
+       list_for_each_entry_rcu(engine, &utrace->engines, entry) {
+               if ((flags & UTRACE_ATTACH_MATCH_OPS)
+                   && engine->ops != ops)
+                       continue;
+               if ((flags & UTRACE_ATTACH_MATCH_DATA)
+                   && engine->data != data)
+                       continue;
+               if (flags & UTRACE_ATTACH_EXCLUSIVE)
+                       engine = ERR_PTR(-EEXIST);
+               return engine;
+       }
+       return NULL;
+}
+
+/*
+  option to stop it?
+  option to match existing on ops, ops+data, return it; nocreate:lookup only
+ */
+struct utrace_attached_engine *
+utrace_attach(struct task_struct *target, int flags,
+            const struct utrace_engine_ops *ops, unsigned long data)
+{
+       struct utrace *utrace;
+       struct utrace_attached_engine *engine;
+
+restart:
+       rcu_read_lock();
+       utrace = rcu_dereference(target->utrace);
+       smp_rmb();
+       if (utrace == NULL) {
+               rcu_read_unlock();
+
+               if (!(flags & UTRACE_ATTACH_CREATE)) {
+                       return ERR_PTR(-ENOENT);
+               }
+
+               engine = kmem_cache_alloc(utrace_engine_cachep, SLAB_KERNEL);
+               if (unlikely(engine == NULL))
+                       return ERR_PTR(-ENOMEM);
+               engine->flags = 0;
+
+       first:
+               utrace = utrace_first_engine(target, engine);
+               if (IS_ERR(utrace)) {
+                       kmem_cache_free(utrace_engine_cachep, engine);
+                       return ERR_PTR(PTR_ERR(utrace));
+               }
+               if (unlikely(utrace == NULL)) /* Race condition.  */
+                       goto restart;
+       }
+       else if (unlikely(target->exit_state == EXIT_DEAD)) {
+               /*
+                * The target has already been reaped.
+                */
+               rcu_read_unlock();
+               return ERR_PTR(-ESRCH);
+       }
+       else {
+               if (!(flags & UTRACE_ATTACH_CREATE)) {
+                       engine = matching_engine(utrace, flags, ops, data);
+                       rcu_read_unlock();
+                       return engine;
+               }
+
+               engine = kmem_cache_alloc(utrace_engine_cachep, SLAB_KERNEL);
+               if (unlikely(engine == NULL))
+                       return ERR_PTR(-ENOMEM);
+               engine->flags = ops->report_reap ? UTRACE_EVENT(REAP) : 0;
+
+               rcu_read_lock();
+               utrace = rcu_dereference(target->utrace);
+               if (unlikely(utrace == NULL)) { /* Race with detach.  */
+                       rcu_read_unlock();
+                       goto first;
+               }
+
+               utrace_lock(utrace);
+               if (flags & UTRACE_ATTACH_EXCLUSIVE) {
+                       struct utrace_attached_engine *old;
+                       old = matching_engine(utrace, flags, ops, data);
+                       if (old != NULL) {
+                               utrace_unlock(utrace);
+                               rcu_read_unlock();
+                               kmem_cache_free(utrace_engine_cachep, engine);
+                               return ERR_PTR(-EEXIST);
+                       }
+               }
+
+               if (unlikely(rcu_dereference(target->utrace) != utrace)) {
+                       /*
+                        * We lost a race with other CPUs doing a sequence
+                        * of detach and attach before we got in.
+                        */
+                       utrace_unlock(utrace);
+                       rcu_read_unlock();
+                       kmem_cache_free(utrace_engine_cachep, engine);
+                       goto restart;
+               }
+               list_add_tail_rcu(&engine->entry, &utrace->engines);
+       }
+
+       engine->ops = ops;
+       engine->data = data;
+
+       utrace_unlock(utrace);
+
+       return engine;
+}
+EXPORT_SYMBOL_GPL(utrace_attach);
+
+/*
+ * When an engine is detached, the target thread may still see it and make
+ * callbacks until it quiesces.  We reset its event flags to just QUIESCE
+ * and install a special ops vector whose callback is dead_engine_delete.
+ * When the target thread quiesces, it can safely free the engine itself.
+ */
+static u32
+dead_engine_delete(struct utrace_attached_engine *engine,
+                  struct task_struct *tsk)
+{
+       return UTRACE_ACTION_DETACH;
+}
+
+static const struct utrace_engine_ops dead_engine_ops =
+{
+       .report_quiesce = &dead_engine_delete
+};
+
+
+/*
+ * If tracing was preventing a SIGCHLD or self-reaping
+ * and is no longer, do that report or reaping right now.
+ */
+static void
+check_noreap(struct task_struct *target, struct utrace *utrace,
+            u32 old_action, u32 action)
+{
+       if ((action | ~old_action) & UTRACE_ACTION_NOREAP)
+               return;
+
+       if (utrace && xchg(&utrace->u.exit.notified, 1))
+               return;
+
+       if (target->exit_signal == -1)
+               release_task(target);
+       else if (thread_group_empty(target)) {
+               read_lock(&tasklist_lock);
+               do_notify_parent(target, target->exit_signal);
+               read_unlock(&tasklist_lock);
+       }
+}
+
+/*
+ * We may have been the one keeping the target thread quiescent.
+ * Check if it should wake up now.
+ * Called with utrace locked, and unlocks it on return.
+ * If we were keeping it stopped, resume it.
+ * If we were keeping its zombie from reporting/self-reap, do it now.
+ */
+static void
+wake_quiescent(unsigned long old_flags,
+              struct utrace *utrace, struct task_struct *target)
+{
+       unsigned long flags;
+       struct utrace_attached_engine *engine;
+
+       if (target->exit_state) {
+               /*
+                * Update the set of events of interest from the union
+                * of the interests of the remaining tracing engines.
+                */
+               flags = 0;
+               list_for_each_entry(engine, &utrace->engines, entry)
+                       flags |= engine->flags | UTRACE_EVENT(REAP);
+               utrace = check_dead_utrace(target, utrace, flags);
+
+               check_noreap(target, utrace, old_flags, flags);
+               return;
+       }
+
+       /*
+        * Update the set of events of interest from the union
+        * of the interests of the remaining tracing engines.
+        */
+       flags = 0;
+       list_for_each_entry(engine, &utrace->engines, entry)
+               flags |= engine->flags | UTRACE_EVENT(REAP);
+       utrace = check_dead_utrace(target, utrace, flags);
+
+       if (flags & UTRACE_ACTION_QUIESCE)
+               return;
+
+       read_lock(&tasklist_lock);
+       if (!target->exit_state) {
+               /*
+                * The target is not dead and should not be in tracing stop
+                * any more.  Wake it unless it's in job control stop.
+                */
+               spin_lock_irq(&target->sighand->siglock);
+               if (target->signal->flags & SIGNAL_STOP_STOPPED) {
+                       int stop_count = target->signal->group_stop_count;
+                       target->state = TASK_STOPPED;
+                       spin_unlock_irq(&target->sighand->siglock);
+
+                       /*
+                        * If tracing was preventing a CLD_STOPPED report
+                        * and is no longer, do that report right now.
+                        */
+                       if (stop_count == 0
+                           && 0
+                           /*&& (events &~ interest) & UTRACE_INHIBIT_CLDSTOP*/
+                               )
+                               do_notify_parent_cldstop(target, CLD_STOPPED);
+               }
+               else {
+                       /*
+                        * Wake the task up.
+                        */
+                       recalc_sigpending_tsk(target);
+                       wake_up_state(target, TASK_STOPPED | TASK_TRACED);
+                       spin_unlock_irq(&target->sighand->siglock);
+               }
+       }
+       read_unlock(&tasklist_lock);
+}
+
+void
+utrace_detach(struct task_struct *target,
+             struct utrace_attached_engine *engine)
+{
+       struct utrace *utrace;
+       unsigned long flags;
+
+       rcu_read_lock();
+       utrace = rcu_dereference(target->utrace);
+       smp_rmb();
+       if (unlikely(target->exit_state == EXIT_DEAD)) {
+               /*
+                * Called after utrace_release_task might have started.
+                * A call to this engine's report_reap callback might
+                * already be in progress or engine might even have been
+                * freed already.
+                */
+               rcu_read_unlock();
+               return;
+       }
+       utrace_lock(utrace);
+       rcu_read_unlock();
+
+       flags = engine->flags;
+       engine->flags = UTRACE_EVENT(QUIESCE) | UTRACE_ACTION_QUIESCE;
+       rcu_assign_pointer(engine->ops, &dead_engine_ops);
+
+       if (quiesce(target, 1)) {
+               remove_engine(engine, target, utrace);
+               wake_quiescent(flags, utrace, target);
+       }
+       else
+               utrace_unlock(utrace);
+}
+EXPORT_SYMBOL_GPL(utrace_detach);
+
+
+/*
+ * Called with utrace->lock held.
+ * Notify and clean up all engines, then free utrace.
+ */
+static void
+utrace_reap(struct task_struct *target, struct utrace *utrace)
+{
+       struct utrace_attached_engine *engine, *next;
+       const struct utrace_engine_ops *ops;
+
+restart:
+       list_for_each_entry_safe(engine, next, &utrace->engines, entry) {
+               list_del_rcu(&engine->entry);
+
+               /*
+                * Now nothing else refers to this engine.
+                */
+               if (engine->flags & UTRACE_EVENT(REAP)) {
+                       ops = rcu_dereference(engine->ops);
+                       if (ops != &dead_engine_ops) {
+                               utrace_unlock(utrace);
+                               (*ops->report_reap)(engine, target);
+                               call_rcu(&engine->rhead, utrace_engine_free);
+                               utrace_lock(utrace);
+                               goto restart;
+                       }
+               }
+               call_rcu(&engine->rhead, utrace_engine_free);
+       }
+       utrace_unlock(utrace);
+
+       rcu_utrace_free(utrace);
+}
+
+/*
+ * Called by release_task.  After this, target->utrace must be cleared.
+ */
+void
+utrace_release_task(struct task_struct *target)
+{
+       struct utrace *utrace;
+
+       task_lock(target);
+       utrace = target->utrace;
+       rcu_assign_pointer(target->utrace, NULL);
+       task_unlock(target);
+
+       if (unlikely(utrace == NULL))
+               return;
+
+       utrace_lock(utrace);
+
+       if (!utrace->u.exit.notified
+           && (target->utrace_flags & (UTRACE_EVENT(DEATH)
+                                       | UTRACE_EVENT(QUIESCE)))) {
+               /*
+                * The target will do some final callbacks but hasn't
+                * finished them yet.  We know because it clears these
+                * event bits after it's done.  Instead of cleaning up here
+                * and requiring utrace_report_death to cope with it, we
+                * delay the REAP report and the teardown until after the
+                * target finishes its death reports.
+                */
+               utrace->u.exit.reap = 1;
+               utrace_unlock(utrace);
+       }
+       else
+               utrace_reap(target, utrace); /* Unlocks and frees.  */
+}
+
+
+void
+utrace_set_flags(struct task_struct *target,
+                struct utrace_attached_engine *engine,
+                unsigned long flags)
+{
+       struct utrace *utrace;
+       int report = 0;
+       unsigned long old_flags, old_utrace_flags;
+
+#ifdef ARCH_HAS_SINGLE_STEP
+       if (! ARCH_HAS_SINGLE_STEP)
+#endif
+               WARN_ON(flags & UTRACE_ACTION_SINGLESTEP);
+#ifdef ARCH_HAS_BLOCK_STEP
+       if (! ARCH_HAS_BLOCK_STEP)
+#endif
+               WARN_ON(flags & UTRACE_ACTION_BLOCKSTEP);
+
+       rcu_read_lock();
+       utrace = rcu_dereference(target->utrace);
+       smp_rmb();
+       if (unlikely(target->exit_state == EXIT_DEAD)) {
+               /*
+                * Race with reaping.
+                */
+               rcu_read_unlock();
+               return;
+       }
+
+       utrace_lock(utrace);
+       rcu_read_unlock();
+
+       old_utrace_flags = target->utrace_flags;
+       old_flags = engine->flags;
+       engine->flags = flags;
+       target->utrace_flags |= flags;
+
+       if ((old_flags ^ flags) & UTRACE_ACTION_QUIESCE) {
+               if (flags & UTRACE_ACTION_QUIESCE) {
+                       report = (quiesce(target, 1)
+                                 && (flags & UTRACE_EVENT(QUIESCE)));
+                       utrace_unlock(utrace);
+               }
+               else
+                       wake_quiescent(old_flags, utrace, target);
+       }
+       else {
+               /*
+                * If we're asking for single-stepping or syscall tracing,
+                * we need to pass through utrace_quiescent before resuming
+                * in user mode to get those effects, even if the target is
+                * not going to be quiescent right now.
+                */
+               if (!(target->utrace_flags & UTRACE_ACTION_QUIESCE)
+                   && ((flags &~ old_utrace_flags)
+                       & (UTRACE_ACTION_SINGLESTEP | UTRACE_ACTION_BLOCKSTEP
+                          | UTRACE_EVENT_SYSCALL)))
+                       quiesce(target, 0);
+               utrace_unlock(utrace);
+       }
+
+       if (report)          /* Already quiescent, won't report itself.  */
+               (*engine->ops->report_quiesce)(engine, target);
+}
+EXPORT_SYMBOL_GPL(utrace_set_flags);
+\f
+/*
+ * While running an engine callback, no locks are held.
+ * If a callback updates its engine's action state, then
+ * we need to take the utrace lock to install the flags update.
+ */
+static inline u32
+update_action(struct task_struct *tsk, struct utrace *utrace,
+             struct utrace_attached_engine *engine,
+             u32 ret)
+{
+       if (ret & UTRACE_ACTION_DETACH)
+               rcu_assign_pointer(engine->ops, &dead_engine_ops);
+       else if ((ret & UTRACE_ACTION_NEWSTATE)
+                && ((ret ^ engine->flags) & UTRACE_ACTION_STATE_MASK)) {
+#ifdef ARCH_HAS_SINGLE_STEP
+               if (! ARCH_HAS_SINGLE_STEP)
+#endif
+                       WARN_ON(ret & UTRACE_ACTION_SINGLESTEP);
+#ifdef ARCH_HAS_BLOCK_STEP
+               if (! ARCH_HAS_BLOCK_STEP)
+#endif
+                       WARN_ON(ret & UTRACE_ACTION_BLOCKSTEP);
+               utrace_lock(utrace);
+               /*
+                * If we're changing something other than just QUIESCE,
+                * make sure we pass through utrace_quiescent before
+                * resuming even if we aren't going to stay quiescent.
+                * That's where we get the correct union of all engines'
+                * flags after they've finished changing, and apply changes.
+                */
+               if (((ret ^ engine->flags) & (UTRACE_ACTION_STATE_MASK
+                                             & ~UTRACE_ACTION_QUIESCE)))
+                       tsk->utrace_flags |= UTRACE_ACTION_QUIESCE;
+               engine->flags &= ~UTRACE_ACTION_STATE_MASK;
+               engine->flags |= ret & UTRACE_ACTION_STATE_MASK;
+               tsk->utrace_flags |= engine->flags;
+               utrace_unlock(utrace);
+       }
+       else
+               ret |= engine->flags & UTRACE_ACTION_STATE_MASK;
+       return ret;
+}
+
+#define REPORT(callback, ...) do { \
+       u32 ret = (*rcu_dereference(engine->ops)->callback) \
+               (engine, tsk, ##__VA_ARGS__); \
+       action = update_action(tsk, utrace, engine, ret); \
+       } while (0)
+
+
+/*
+ * Called with utrace->lock held, returns with it released.
+ */
+static u32
+remove_detached(struct task_struct *tsk, struct utrace *utrace,
+               struct utrace **utracep, u32 action)
+{
+       struct utrace_attached_engine *engine, *next;
+       unsigned long flags;
+
+       flags = 0;
+       list_for_each_entry_safe(engine, next, &utrace->engines, entry) {
+               if (engine->ops == &dead_engine_ops)
+                       remove_engine(engine, tsk, utrace);
+               else
+                       flags |= engine->flags | UTRACE_EVENT(REAP);
+       }
+       utrace = check_dead_utrace(tsk, utrace, flags);
+       if (utracep)
+               *utracep = utrace;
+
+       flags &= UTRACE_ACTION_STATE_MASK;
+       return flags | (action & UTRACE_ACTION_OP_MASK);
+}
+
+/*
+ * Called after an event report loop.  Remove any engines marked for detach.
+ */
+static inline u32
+check_detach(struct task_struct *tsk, u32 action)
+{
+       if (action & UTRACE_ACTION_DETACH) {
+               utrace_lock(tsk->utrace);
+               action = remove_detached(tsk, tsk->utrace, NULL, action);
+       }
+       return action;
+}
+
+static inline void
+check_quiescent(struct task_struct *tsk, u32 action)
+{
+       if (action & UTRACE_ACTION_STATE_MASK)
+               utrace_quiescent(tsk);
+}
+
+/*
+ * Called iff UTRACE_EVENT(CLONE) flag is set.
+ * This notification call blocks the wake_up_new_task call on the child.
+ * So we must not quiesce here.  tracehook_report_clone_complete will do
+ * a quiescence check momentarily.
+ */
+void
+utrace_report_clone(unsigned long clone_flags, struct task_struct *child)
+{
+       struct task_struct *tsk = current;
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       unsigned long action;
+
+       utrace->u.live.cloning = child;
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(CLONE))
+                       REPORT(report_clone, clone_flags, child);
+               if (action & UTRACE_ACTION_HIDE)
+                       break;
+       }
+
+       utrace->u.live.cloning = NULL;
+
+       check_detach(tsk, action);
+}
+
+static unsigned long
+report_quiescent(struct task_struct *tsk, struct utrace *utrace, u32 action)
+{
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(QUIESCE))
+                       REPORT(report_quiesce);
+               action |= engine->flags & UTRACE_ACTION_STATE_MASK;
+       }
+
+       return check_detach(tsk, action);
+}
+
+/*
+ * Called iff UTRACE_EVENT(JCTL) flag is set.
+ */
+int
+utrace_report_jctl(int what)
+{
+       struct task_struct *tsk = current;
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       unsigned long action;
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(JCTL))
+                       REPORT(report_jctl, what);
+               if (action & UTRACE_ACTION_HIDE)
+                       break;
+       }
+
+       /*
+        * We are becoming quiescent, so report it now.
+        * We don't block in utrace_quiescent because we are stopping anyway.
+        * We know that upon resuming we'll go through tracehook_induce_signal,
+        * which will keep us quiescent or set us up to resume with tracing.
+        */
+       action = report_quiescent(tsk, utrace, action);
+
+       if (what == CLD_STOPPED && tsk->state != TASK_STOPPED) {
+               /*
+                * The event report hooks could have blocked, though
+                * it should have been briefly.  Make sure we're in
+                * TASK_STOPPED state again to block properly, unless
+                * we've just come back out of job control stop.
+                */
+               spin_lock_irq(&tsk->sighand->siglock);
+               if (tsk->signal->flags & SIGNAL_STOP_STOPPED)
+                       set_current_state(TASK_STOPPED);
+               spin_unlock_irq(&tsk->sighand->siglock);
+       }
+
+       return action & UTRACE_JCTL_NOSIGCHLD;
+}
+
+
+/*
+ * Called if UTRACE_EVENT(QUIESCE) or UTRACE_ACTION_QUIESCE flag is set.
+ * Also called after other event reports.
+ * It is a good time to block.
+ */
+void
+utrace_quiescent(struct task_struct *tsk)
+{
+       struct utrace *utrace = tsk->utrace;
+       unsigned long action;
+
+restart:
+       /* XXX must change for sharing */
+
+       action = report_quiescent(tsk, utrace, UTRACE_ACTION_RESUME);
+
+       /*
+        * If some engines want us quiescent, we block here.
+        */
+       if (action & UTRACE_ACTION_QUIESCE) {
+               spin_lock_irq(&tsk->sighand->siglock);
+               /*
+                * If wake_quiescent is trying to wake us up now, it will
+                * have cleared the QUIESCE flag before trying to take the
+                * siglock.  Now we have the siglock, so either it has
+                * already cleared the flag, or it will wake us up after we
+                * release the siglock it's waiting for.
+                * Never stop when there is a SIGKILL bringing us down.
+                */
+               if ((tsk->utrace_flags & UTRACE_ACTION_QUIESCE)
+                   /*&& !(tsk->signal->flags & SIGNAL_GROUP_SIGKILL)*/) {
+                       set_current_state(TASK_TRACED);
+                       /*
+                        * If there is a group stop in progress,
+                        * we must participate in the bookkeeping.
+                        */
+                       if (tsk->signal->group_stop_count > 0)
+                               --tsk->signal->group_stop_count;
+                       spin_unlock_irq(&tsk->sighand->siglock);
+                       schedule();
+               }
+               else
+                       spin_unlock_irq(&tsk->sighand->siglock);
+
+               /*
+                * We've woken up.  One engine could be waking us up while
+                * another has asked us to quiesce.  So check afresh.  We
+                * could have been detached while quiescent.  Now we are no
+                * longer quiescent, so don't need to do any RCU locking.
+                * But we do need to check our utrace pointer anew.
+                */
+               utrace = tsk->utrace;
+               if (tsk->utrace_flags
+                   & (UTRACE_EVENT(QUIESCE) | UTRACE_ACTION_STATE_MASK))
+                       goto restart;
+       }
+       else if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) {
+               /*
+                * Our flags are out of date.
+                * Update the set of events of interest from the union
+                * of the interests of the remaining tracing engines.
+                */
+               struct utrace_attached_engine *engine;
+               unsigned long flags = 0;
+               utrace = rcu_dereference(tsk->utrace);
+               utrace_lock(utrace);
+               list_for_each_entry(engine, &utrace->engines, entry)
+                       flags |= engine->flags | UTRACE_EVENT(REAP);
+               tsk->utrace_flags = flags;
+               utrace_unlock(utrace);
+       }
+
+       /*
+        * We're resuming.  Update the machine layer tracing state and then go.
+        */
+#ifdef ARCH_HAS_SINGLE_STEP
+       if (action & UTRACE_ACTION_SINGLESTEP)
+               tracehook_enable_single_step(tsk);
+       else
+               tracehook_disable_single_step(tsk);
+#endif
+#ifdef ARCH_HAS_BLOCK_STEP
+       if ((action & (UTRACE_ACTION_BLOCKSTEP|UTRACE_ACTION_SINGLESTEP))
+           == UTRACE_ACTION_BLOCKSTEP)
+               tracehook_enable_block_step(tsk);
+       else
+               tracehook_disable_block_step(tsk);
+#endif
+       if (tsk->utrace_flags & UTRACE_EVENT_SYSCALL)
+               tracehook_enable_syscall_trace(tsk);
+       else
+               tracehook_disable_syscall_trace(tsk);
+}
+
+
+/*
+ * Called iff UTRACE_EVENT(EXIT) flag is set.
+ */
+void
+utrace_report_exit(long *exit_code)
+{
+       struct task_struct *tsk = current;
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       unsigned long action;
+       long orig_code = *exit_code;
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(EXIT))
+                       REPORT(report_exit, orig_code, exit_code);
+       }
+       action = check_detach(tsk, action);
+       check_quiescent(tsk, action);
+}
+
+/*
+ * Called iff UTRACE_EVENT(DEATH) flag is set.
+ *
+ * It is always possible that we are racing with utrace_release_task here,
+ * if UTRACE_ACTION_NOREAP is not set, or in the case of non-leader exec
+ * where the old leader will get released regardless of NOREAP.  For this
+ * reason, utrace_release_task checks for the event bits that get us here,
+ * and delays its cleanup for us to do.
+ */
+void
+utrace_report_death(struct task_struct *tsk, struct utrace *utrace)
+{
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       u32 action, oaction;
+
+       BUG_ON(!tsk->exit_state);
+
+       oaction = tsk->utrace_flags;
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(DEATH))
+                       REPORT(report_death);
+               if (engine->flags & UTRACE_EVENT(QUIESCE))
+                       REPORT(report_quiesce);
+       }
+       /*
+        * Unconditionally lock and recompute the flags.
+        * This may notice that there are no engines left and
+        * free the utrace struct.
+        */
+       utrace_lock(utrace);
+       if (utrace->u.exit.reap) {
+               /*
+                * utrace_release_task was already called in parallel.
+                * We must complete its work now.
+                */
+       reap:
+               utrace_reap(tsk, utrace);
+       }
+       else {
+               action = remove_detached(tsk, utrace, &utrace, action);
+
+               if (utrace != NULL) {
+                       utrace_lock(utrace);
+                       if (utrace->u.exit.reap)
+                               goto reap;
+
+                       /*
+                        * Clear event bits we can't see any more.  This
+                        * tells utrace_release_task we have already
+                        * finished, if it comes along later.
+                        */
+                       tsk->utrace_flags &= (UTRACE_EVENT(REAP)
+                                             | UTRACE_ACTION_NOREAP);
+
+                       utrace_unlock(utrace);
+               }
+
+               check_noreap(tsk, utrace, oaction, action);
+       }
+}
+
+/*
+ * Called iff UTRACE_EVENT(VFORK_DONE) flag is set.
+ */
+void
+utrace_report_vfork_done(pid_t child_pid)
+{
+       struct task_struct *tsk = current;
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       unsigned long action;
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(VFORK_DONE))
+                       REPORT(report_vfork_done, child_pid);
+               if (action & UTRACE_ACTION_HIDE)
+                       break;
+       }
+       action = check_detach(tsk, action);
+       check_quiescent(tsk, action);
+}
+
+/*
+ * Called iff UTRACE_EVENT(EXEC) flag is set.
+ */
+void
+utrace_report_exec(struct linux_binprm *bprm, struct pt_regs *regs)
+{
+       struct task_struct *tsk = current;
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       unsigned long action;
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & UTRACE_EVENT(EXEC))
+                       REPORT(report_exec, bprm, regs);
+               if (action & UTRACE_ACTION_HIDE)
+                       break;
+       }
+       action = check_detach(tsk, action);
+       check_quiescent(tsk, action);
+}
+
+/*
+ * Called iff UTRACE_EVENT(SYSCALL_{ENTRY,EXIT}) flag is set.
+ */
+void
+utrace_report_syscall(struct pt_regs *regs, int is_exit)
+{
+       struct task_struct *tsk = current;
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       unsigned long action, ev;
+
+/*
+  XXX pass syscall # to engine hook directly, let it return inhibit-action
+  to reset to -1
+       long syscall = tracehook_syscall_number(regs, is_exit);
+*/
+
+       ev = is_exit ? UTRACE_EVENT(SYSCALL_EXIT) : UTRACE_EVENT(SYSCALL_ENTRY);
+
+       /* XXX must change for sharing */
+       action = UTRACE_ACTION_RESUME;
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if (engine->flags & ev) {
+                       if (is_exit)
+                               REPORT(report_syscall_exit, regs);
+                       else
+                               REPORT(report_syscall_entry, regs);
+               }
+               if (action & UTRACE_ACTION_HIDE)
+                       break;
+       }
+       action = check_detach(tsk, action);
+       check_quiescent(tsk, action);
+}
+
+// XXX copied from signal.c
+#ifdef SIGEMT
+#define M_SIGEMT       M(SIGEMT)
+#else
+#define M_SIGEMT       0
+#endif
+
+#if SIGRTMIN > BITS_PER_LONG
+#define M(sig) (1ULL << ((sig)-1))
+#else
+#define M(sig) (1UL << ((sig)-1))
+#endif
+#define T(sig, mask) (M(sig) & (mask))
+
+#define SIG_KERNEL_ONLY_MASK (\
+       M(SIGKILL)   |  M(SIGSTOP)                                   )
+
+#define SIG_KERNEL_STOP_MASK (\
+       M(SIGSTOP)   |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   )
+
+#define SIG_KERNEL_COREDUMP_MASK (\
+        M(SIGQUIT)   |  M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   | \
+        M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGBUS)    |  M(SIGSYS)    | \
+        M(SIGXCPU)   |  M(SIGXFSZ)   |  M_SIGEMT                     )
+
+#define SIG_KERNEL_IGNORE_MASK (\
+        M(SIGCONT)   |  M(SIGCHLD)   |  M(SIGWINCH)  |  M(SIGURG)    )
+
+#define sig_kernel_only(sig) \
+               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_ONLY_MASK))
+#define sig_kernel_coredump(sig) \
+               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_COREDUMP_MASK))
+#define sig_kernel_ignore(sig) \
+               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_IGNORE_MASK))
+#define sig_kernel_stop(sig) \
+               (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_STOP_MASK))
+
+
+/*
+ * Call each interested tracing engine's report_signal callback.
+ */
+static u32
+report_signal(struct task_struct *tsk, struct pt_regs *regs,
+             struct utrace *utrace, u32 action,
+             unsigned long flags1, unsigned long flags2, siginfo_t *info,
+             const struct k_sigaction *ka, struct k_sigaction *return_ka)
+{
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+
+       /* XXX must change for sharing */
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               if ((engine->flags & flags1) && (engine->flags & flags2)) {
+                       u32 disp = action & UTRACE_ACTION_OP_MASK;
+                       action &= ~UTRACE_ACTION_OP_MASK;
+                       REPORT(report_signal, regs, disp, info, ka, return_ka);
+                       if ((action & UTRACE_ACTION_OP_MASK) == 0)
+                               action |= disp;
+                       if (action & UTRACE_ACTION_HIDE)
+                               break;
+               }
+       }
+
+       return action;
+}
+
+void
+utrace_signal_handler_singlestep(struct task_struct *tsk, struct pt_regs *regs)
+{
+       u32 action;
+       action = report_signal(tsk, regs, tsk->utrace, UTRACE_SIGNAL_HANDLER,
+                              UTRACE_EVENT_SIGNAL_ALL,
+                              UTRACE_ACTION_SINGLESTEP|UTRACE_ACTION_BLOCKSTEP,
+                              NULL, NULL, NULL);
+       action = check_detach(tsk, action);
+       check_quiescent(tsk, action);
+}
+
+
+/*
+ * This is the hook from the signals code, called with the siglock held.
+ * Here is the ideal place to quiesce.  We also dequeue and intercept signals.
+ */
+int
+utrace_get_signal(struct task_struct *tsk, struct pt_regs *regs,
+                 siginfo_t *info, struct k_sigaction *return_ka)
+{
+       struct utrace *utrace = tsk->utrace;
+       struct utrace_signal signal = { info, return_ka, 0 };
+       struct k_sigaction *ka;
+       unsigned long action, event;
+
+#if 0                          /* XXX */
+       if (tsk->signal->flags & SIGNAL_GROUP_SIGKILL)
+               return 0;
+#endif
+
+       /*
+        * If we should quiesce, now is the time.
+        * First stash a pointer to the state on our stack,
+        * so that utrace_inject_signal can tell us what to do.
+        */
+       if (utrace->u.live.signal == NULL)
+               utrace->u.live.signal = &signal;
+
+       if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) {
+               spin_unlock_irq(&tsk->sighand->siglock);
+               utrace_quiescent(tsk);
+               if (signal.signr == 0)
+                       /*
+                        * This return value says to reacquire the siglock
+                        * and check again.  This will check for a pending
+                        * group stop and process it before coming back here.
+                        */
+                       return -1;
+               spin_lock_irq(&tsk->sighand->siglock);
+       }
+
+       /*
+        * If a signal was injected previously, it could not use our
+        * stack space directly.  It had to allocate a data structure,
+        * which we can now copy out of and free.
+        */
+       if (utrace->u.live.signal != &signal) {
+               signal.signr = utrace->u.live.signal->signr;
+               copy_siginfo(info, utrace->u.live.signal->info);
+               if (utrace->u.live.signal->return_ka)
+                       *return_ka = *utrace->u.live.signal->return_ka;
+               else
+                       signal.return_ka = NULL;
+               kfree(utrace->u.live.signal);
+       }
+       utrace->u.live.signal = NULL;
+
+       /*
+        * If a signal was injected, everything is in place now.  Go do it.
+        */
+       if (signal.signr != 0) {
+               if (signal.return_ka == NULL) {
+                       ka = &tsk->sighand->action[signal.signr - 1];
+                       if (ka->sa.sa_flags & SA_ONESHOT)
+                               ka->sa.sa_handler = SIG_DFL;
+                       *return_ka = *ka;
+               }
+               else
+                       BUG_ON(signal.return_ka != return_ka);
+               return signal.signr;
+       }
+
+       /*
+        * If noone is interested in intercepting signals, let the caller
+        * just dequeue them normally.
+        */
+       if ((tsk->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0)
+               return 0;
+
+       /*
+        * Steal the next signal so we can let tracing engines examine it.
+        * From the signal number and sigaction, determine what normal
+        * delivery would do.  If no engine perturbs it, we'll do that
+        * by returning the signal number after setting *return_ka.
+        */
+       signal.signr = dequeue_signal(tsk, &tsk->blocked, info);
+       if (signal.signr == 0)
+               return 0;
+
+       BUG_ON(signal.signr != info->si_signo);
+
+       ka = &tsk->sighand->action[signal.signr - 1];
+       *return_ka = *ka;
+
+       if (signal.signr == SIGKILL)
+               return signal.signr;
+
+       if (ka->sa.sa_handler == SIG_IGN) {
+               event = UTRACE_EVENT(SIGNAL_IGN);
+               action = UTRACE_SIGNAL_IGN;
+       }
+       else if (ka->sa.sa_handler != SIG_DFL) {
+               event = UTRACE_EVENT(SIGNAL);
+               action = UTRACE_ACTION_RESUME;
+       }
+       else if (sig_kernel_coredump(signal.signr)) {
+               event = UTRACE_EVENT(SIGNAL_CORE);
+               action = UTRACE_SIGNAL_CORE;
+       }
+       else if (sig_kernel_ignore(signal.signr)) {
+               event = UTRACE_EVENT(SIGNAL_IGN);
+               action = UTRACE_SIGNAL_IGN;
+       }
+       else if (sig_kernel_stop(signal.signr)) {
+               event = UTRACE_EVENT(SIGNAL_STOP);
+               action = (signal.signr == SIGSTOP
+                         ? UTRACE_SIGNAL_STOP : UTRACE_SIGNAL_TSTP);
+       }
+       else {
+               event = UTRACE_EVENT(SIGNAL_TERM);
+               action = UTRACE_SIGNAL_TERM;
+       }
+
+       if (tsk->utrace_flags & event) {
+               /*
+                * We have some interested engines, so tell them about the
+                * signal and let them change its disposition.
+                */
+
+               spin_unlock_irq(&tsk->sighand->siglock);
+
+               action = report_signal(tsk, regs, utrace, action, event, event,
+                                      info, ka, return_ka);
+               action &= UTRACE_ACTION_OP_MASK;
+
+               if (action & UTRACE_SIGNAL_HOLD) {
+                       struct sigqueue *q = sigqueue_alloc();
+                       if (likely(q != NULL)) {
+                               q->flags = 0;
+                               copy_siginfo(&q->info, info);
+                       }
+                       action &= ~UTRACE_SIGNAL_HOLD;
+                       spin_lock_irq(&tsk->sighand->siglock);
+                       sigaddset(&tsk->pending.signal, info->si_signo);
+                       if (likely(q != NULL))
+                               list_add(&q->list, &tsk->pending.list);
+               }
+               else
+                       spin_lock_irq(&tsk->sighand->siglock);
+
+               recalc_sigpending_tsk(tsk);
+       }
+
+       if (tsk->utrace != utrace)
+               rcu_utrace_free(utrace);
+
+       /*
+        * We express the chosen action to the signals code in terms
+        * of a representative signal whose default action does it.
+        */
+       switch (action) {
+       case UTRACE_SIGNAL_IGN:
+               /*
+                * We've eaten the signal.  That's all we do.
+                * Tell the caller to restart.
+                */
+               spin_unlock_irq(&tsk->sighand->siglock);
+               return -1;
+
+       case UTRACE_ACTION_RESUME:
+       case UTRACE_SIGNAL_DELIVER:
+               /*
+                * The handler will run.  We do the SA_ONESHOT work here
+                * since the normal path will only touch *return_ka now.
+                */
+               if (return_ka->sa.sa_flags & SA_ONESHOT)
+                       ka->sa.sa_handler = SIG_DFL;
+               break;
+
+       case UTRACE_SIGNAL_TSTP:
+               signal.signr = SIGTSTP;
+               tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+               return_ka->sa.sa_handler = SIG_DFL;
+               break;
+
+       case UTRACE_SIGNAL_STOP:
+               signal.signr = SIGSTOP;
+               tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+               return_ka->sa.sa_handler = SIG_DFL;
+               break;
+
+       case UTRACE_SIGNAL_TERM:
+               signal.signr = SIGTERM;
+               return_ka->sa.sa_handler = SIG_DFL;
+               break;
+
+       case UTRACE_SIGNAL_CORE:
+               signal.signr = SIGQUIT;
+               return_ka->sa.sa_handler = SIG_DFL;
+               break;
+
+       default:
+               BUG();
+       }
+
+       return signal.signr;
+}
+
+
+/*
+ * Cause a specified signal delivery in the target thread,
+ * which must be quiescent.  The action has UTRACE_SIGNAL_* bits
+ * as returned from a report_signal callback.  If ka is non-null,
+ * it gives the sigaction to follow for UTRACE_SIGNAL_DELIVER;
+ * otherwise, the installed sigaction at the time of delivery is used.
+ */
+int
+utrace_inject_signal(struct task_struct *target,
+                   struct utrace_attached_engine *engine,
+                   u32 action, siginfo_t *info,
+                   const struct k_sigaction *ka)
+{
+       struct utrace *utrace;
+       struct utrace_signal *signal;
+       int ret;
+
+       if (info->si_signo == 0 || !valid_signal(info->si_signo))
+               return -EINVAL;
+
+       rcu_read_lock();
+       utrace = rcu_dereference(target->utrace);
+       if (utrace == NULL) {
+               rcu_read_unlock();
+               return -ESRCH;
+       }
+       utrace_lock(utrace);
+       rcu_read_unlock();
+
+       ret = 0;
+       signal = utrace->u.live.signal;
+       if (signal == NULL) {
+               ret = -ENOSYS;  /* XXX */
+       }
+       else if (signal->signr != 0)
+               ret = -EAGAIN;
+       else {
+               if (info != signal->info)
+                       copy_siginfo(signal->info, info);
+
+               switch (action) {
+               default:
+                       ret = -EINVAL;
+                       break;
+
+               case UTRACE_SIGNAL_IGN:
+                       break;
+
+               case UTRACE_ACTION_RESUME:
+               case UTRACE_SIGNAL_DELIVER:
+                       /*
+                        * The handler will run.  We do the SA_ONESHOT work
+                        * here since the normal path will not touch the
+                        * real sigaction when using an injected signal.
+                        */
+                       if (ka == NULL)
+                               signal->return_ka = NULL;
+                       else if (ka != signal->return_ka)
+                               *signal->return_ka = *ka;
+                       if (ka && ka->sa.sa_flags & SA_ONESHOT) {
+                               struct k_sigaction *a;
+                               a = &target->sighand->action[info->si_signo-1];
+                               spin_lock_irq(&target->sighand->siglock);
+                               a->sa.sa_handler = SIG_DFL;
+                               spin_unlock_irq(&target->sighand->siglock);
+                       }
+                       signal->signr = info->si_signo;
+                       break;
+
+               case UTRACE_SIGNAL_TSTP:
+                       signal->signr = SIGTSTP;
+                       spin_lock_irq(&target->sighand->siglock);
+                       target->signal->flags |= SIGNAL_STOP_DEQUEUED;
+                       spin_unlock_irq(&target->sighand->siglock);
+                       signal->return_ka->sa.sa_handler = SIG_DFL;
+                       break;
+
+               case UTRACE_SIGNAL_STOP:
+                       signal->signr = SIGSTOP;
+                       spin_lock_irq(&target->sighand->siglock);
+                       target->signal->flags |= SIGNAL_STOP_DEQUEUED;
+                       spin_unlock_irq(&target->sighand->siglock);
+                       signal->return_ka->sa.sa_handler = SIG_DFL;
+                       break;
+
+               case UTRACE_SIGNAL_TERM:
+                       signal->signr = SIGTERM;
+                       signal->return_ka->sa.sa_handler = SIG_DFL;
+                       break;
+
+               case UTRACE_SIGNAL_CORE:
+                       signal->signr = SIGQUIT;
+                       signal->return_ka->sa.sa_handler = SIG_DFL;
+                       break;
+               }
+       }
+
+       utrace_unlock(utrace);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(utrace_inject_signal);
+
+
+const struct utrace_regset *
+utrace_regset(struct task_struct *target,
+             struct utrace_attached_engine *engine,
+             const struct utrace_regset_view *view, int which)
+{
+       if (unlikely((unsigned) which >= view->n))
+               return NULL;
+
+       if (target != current)
+               wait_task_inactive(target);
+
+       return &view->regsets[which];
+}
+EXPORT_SYMBOL_GPL(utrace_regset);
+
+
+/*
+ * Return the task_struct for the task using ptrace on this one, or NULL.
+ * Must be called with rcu_read_lock held to keep the returned struct alive.
+ *
+ * At exec time, this may be called with task_lock(p) still held from when
+ * tracehook_unsafe_exec was just called.  In that case it must give
+ * results consistent with those unsafe_exec results, i.e. non-NULL if
+ * any LSM_UNSAFE_PTRACE_* bits were set.
+ *
+ * The value is also used to display after "TracerPid:" in /proc/PID/status,
+ * where it is called with only rcu_read_lock held.
+ */
+struct task_struct *
+utrace_tracer_task(struct task_struct *target)
+{
+       struct utrace *utrace;
+       struct task_struct *tracer = NULL;
+
+       utrace = rcu_dereference(target->utrace);
+       if (utrace != NULL) {
+               struct list_head *pos, *next;
+               struct utrace_attached_engine *engine;
+               const struct utrace_engine_ops *ops;
+               list_for_each_safe_rcu(pos, next, &utrace->engines) {
+                       engine = list_entry(pos, struct utrace_attached_engine,
+                                           entry);
+                       ops = rcu_dereference(engine->ops);
+                       if (ops->tracer_task) {
+                               tracer = (*ops->tracer_task)(engine, target);
+                               if (tracer != NULL)
+                                       break;
+                       }
+               }
+       }
+
+       return tracer;
+}
+
+int
+utrace_allow_access_process_vm(struct task_struct *target)
+{
+       struct utrace *utrace;
+       int ret = 0;
+
+       rcu_read_lock();
+       utrace = rcu_dereference(target->utrace);
+       if (utrace != NULL) {
+               struct list_head *pos, *next;
+               struct utrace_attached_engine *engine;
+               const struct utrace_engine_ops *ops;
+               list_for_each_safe_rcu(pos, next, &utrace->engines) {
+                       engine = list_entry(pos, struct utrace_attached_engine,
+                                           entry);
+                       ops = rcu_dereference(engine->ops);
+                       if (ops->allow_access_process_vm) {
+                               ret = (*ops->allow_access_process_vm)(engine,
+                                                                     target,
+                                                                     current);
+                               if (ret)
+                                       break;
+                       }
+               }
+       }
+       rcu_read_unlock();
+
+       return ret;
+}
+
+/*
+ * Called on the current task to return LSM_UNSAFE_* bits implied by tracing.
+ * Called with task_lock held.
+ */
+int
+utrace_unsafe_exec(struct task_struct *tsk)
+{
+       struct utrace *utrace = tsk->utrace;
+       struct list_head *pos, *next;
+       struct utrace_attached_engine *engine;
+       const struct utrace_engine_ops *ops;
+       int unsafe = 0;
+
+       /* XXX must change for sharing */
+       list_for_each_safe_rcu(pos, next, &utrace->engines) {
+               engine = list_entry(pos, struct utrace_attached_engine, entry);
+               ops = rcu_dereference(engine->ops);
+               if (ops->unsafe_exec)
+                       unsafe |= (*ops->unsafe_exec)(engine, tsk);
+       }
+
+       return unsafe;
+}
diff --git a/lib/audit.c b/lib/audit.c
new file mode 100644 (file)
index 0000000..3b1289f
--- /dev/null
@@ -0,0 +1,55 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+       switch(syscall) {
+       case __NR_open:
+               return 2;
+#ifdef __NR_openat
+       case __NR_openat:
+               return 3;
+#endif
+#ifdef __NR_socketcall
+       case __NR_socketcall:
+               return 4;
+#endif
+       case __NR_execve:
+               return 5;
+       default:
+               return 0;
+       }
+}
+
+static int __init audit_classes_init(void)
+{
+       audit_register_class(AUDIT_CLASS_WRITE, write_class);
+       audit_register_class(AUDIT_CLASS_READ, read_class);
+       audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+       audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+       return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/lib/debug_locks.c b/lib/debug_locks.c
new file mode 100644 (file)
index 0000000..0ef01d1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * lib/debug_locks.c
+ *
+ * Generic place for common debugging facilities for various locks:
+ * spinlocks, rwlocks, mutexes and rwsems.
+ *
+ * Started by Ingo Molnar:
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ */
+#include <linux/rwsem.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/debug_locks.h>
+
+/*
+ * We want to turn all lock-debugging facilities on/off at once,
+ * via a global flag. The reason is that once a single bug has been
+ * detected and reported, there might be cascade of followup bugs
+ * that would just muddy the log. So we report the first one and
+ * shut up after that.
+ */
+int debug_locks = 1;
+
+/*
+ * The locking-testsuite uses <debug_locks_silent> to get a
+ * 'silent failure': nothing is printed to the console when
+ * a locking bug is detected.
+ */
+int debug_locks_silent;
+
+/*
+ * Generic 'turn off all lock debugging' function:
+ */
+int debug_locks_off(void)
+{
+       if (xchg(&debug_locks, 0)) {
+               if (!debug_locks_silent) {
+                       console_verbose();
+                       return 1;
+               }
+       }
+       return 0;
+}
diff --git a/lib/list_debug.c b/lib/list_debug.c
new file mode 100644 (file)
index 0000000..1aae85c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2006, Red Hat, Inc., Dave Jones
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the linked list implementations for
+ * DEBUG_LIST.
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+
+void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       if (unlikely(next->prev != prev)) {
+               printk(KERN_ERR "list_add corruption. next->prev should be %p, but was %p\n",
+                       prev, next->prev);
+               BUG();
+       }
+       if (unlikely(prev->next != next)) {
+               printk(KERN_ERR "list_add corruption. prev->next should be %p, but was %p\n",
+                       next, prev->next);
+               BUG();
+       }
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+EXPORT_SYMBOL(__list_add);
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+EXPORT_SYMBOL(list_add);
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+void list_del(struct list_head *entry)
+{
+       if (unlikely(entry->prev->next != entry)) {
+               printk(KERN_ERR "list_del corruption. prev->next should be %p, but was %p\n",
+                       entry, entry->prev->next);
+               BUG();
+       }
+       if (unlikely(entry->next->prev != entry)) {
+               printk(KERN_ERR "list_del corruption. next->prev should be %p, but was %p\n",
+                       entry, entry->next->prev);
+               BUG();
+       }
+       __list_del(entry->prev, entry->next);
+       entry->next = LIST_POISON1;
+       entry->prev = LIST_POISON2;
+}
+EXPORT_SYMBOL(list_del);
+
diff --git a/lib/locking-selftest-hardirq.h b/lib/locking-selftest-hardirq.h
new file mode 100644 (file)
index 0000000..10d4a15
--- /dev/null
@@ -0,0 +1,9 @@
+#undef IRQ_DISABLE
+#undef IRQ_ENABLE
+#undef IRQ_ENTER
+#undef IRQ_EXIT
+
+#define IRQ_ENABLE             HARDIRQ_ENABLE
+#define IRQ_DISABLE            HARDIRQ_DISABLE
+#define IRQ_ENTER              HARDIRQ_ENTER
+#define IRQ_EXIT               HARDIRQ_EXIT
diff --git a/lib/locking-selftest-mutex.h b/lib/locking-selftest-mutex.h
new file mode 100644 (file)
index 0000000..68601b6
--- /dev/null
@@ -0,0 +1,11 @@
+#undef LOCK
+#define LOCK           ML
+
+#undef UNLOCK
+#define UNLOCK         MU
+
+#undef RLOCK
+#undef WLOCK
+
+#undef INIT
+#define INIT           MI
diff --git a/lib/locking-selftest-rlock-hardirq.h b/lib/locking-selftest-rlock-hardirq.h
new file mode 100644 (file)
index 0000000..9f517eb
--- /dev/null
@@ -0,0 +1,2 @@
+#include "locking-selftest-rlock.h"
+#include "locking-selftest-hardirq.h"
diff --git a/lib/locking-selftest-rlock-softirq.h b/lib/locking-selftest-rlock-softirq.h
new file mode 100644 (file)
index 0000000..981455d
--- /dev/null
@@ -0,0 +1,2 @@
+#include "locking-selftest-rlock.h"
+#include "locking-selftest-softirq.h"
diff --git a/lib/locking-selftest-rlock.h b/lib/locking-selftest-rlock.h
new file mode 100644 (file)
index 0000000..6789044
--- /dev/null
@@ -0,0 +1,14 @@
+#undef LOCK
+#define LOCK           RL
+
+#undef UNLOCK
+#define UNLOCK         RU
+
+#undef RLOCK
+#define RLOCK          RL
+
+#undef WLOCK
+#define WLOCK          WL
+
+#undef INIT
+#define INIT           RWI
diff --git a/lib/locking-selftest-rsem.h b/lib/locking-selftest-rsem.h
new file mode 100644 (file)
index 0000000..62da886
--- /dev/null
@@ -0,0 +1,14 @@
+#undef LOCK
+#define LOCK           RSL
+
+#undef UNLOCK
+#define UNLOCK         RSU
+
+#undef RLOCK
+#define RLOCK          RSL
+
+#undef WLOCK
+#define WLOCK          WSL
+
+#undef INIT
+#define INIT           RWSI
diff --git a/lib/locking-selftest-softirq.h b/lib/locking-selftest-softirq.h
new file mode 100644 (file)
index 0000000..a83de2a
--- /dev/null
@@ -0,0 +1,9 @@
+#undef IRQ_DISABLE
+#undef IRQ_ENABLE
+#undef IRQ_ENTER
+#undef IRQ_EXIT
+
+#define IRQ_DISABLE            SOFTIRQ_DISABLE
+#define IRQ_ENABLE             SOFTIRQ_ENABLE
+#define IRQ_ENTER              SOFTIRQ_ENTER
+#define IRQ_EXIT               SOFTIRQ_EXIT
diff --git a/lib/locking-selftest-spin-hardirq.h b/lib/locking-selftest-spin-hardirq.h
new file mode 100644 (file)
index 0000000..693198d
--- /dev/null
@@ -0,0 +1,2 @@
+#include "locking-selftest-spin.h"
+#include "locking-selftest-hardirq.h"
diff --git a/lib/locking-selftest-spin-softirq.h b/lib/locking-selftest-spin-softirq.h
new file mode 100644 (file)
index 0000000..c472e2a
--- /dev/null
@@ -0,0 +1,2 @@
+#include "locking-selftest-spin.h"
+#include "locking-selftest-softirq.h"
diff --git a/lib/locking-selftest-spin.h b/lib/locking-selftest-spin.h
new file mode 100644 (file)
index 0000000..ccd1b4b
--- /dev/null
@@ -0,0 +1,11 @@
+#undef LOCK
+#define LOCK           L
+
+#undef UNLOCK
+#define UNLOCK         U
+
+#undef RLOCK
+#undef WLOCK
+
+#undef INIT
+#define INIT           SI
diff --git a/lib/locking-selftest-wlock-hardirq.h b/lib/locking-selftest-wlock-hardirq.h
new file mode 100644 (file)
index 0000000..2dd2e51
--- /dev/null
@@ -0,0 +1,2 @@
+#include "locking-selftest-wlock.h"
+#include "locking-selftest-hardirq.h"
diff --git a/lib/locking-selftest-wlock-softirq.h b/lib/locking-selftest-wlock-softirq.h
new file mode 100644 (file)
index 0000000..cb80d1c
--- /dev/null
@@ -0,0 +1,2 @@
+#include "locking-selftest-wlock.h"
+#include "locking-selftest-softirq.h"
diff --git a/lib/locking-selftest-wlock.h b/lib/locking-selftest-wlock.h
new file mode 100644 (file)
index 0000000..0815322
--- /dev/null
@@ -0,0 +1,14 @@
+#undef LOCK
+#define LOCK           WL
+
+#undef UNLOCK
+#define UNLOCK         WU
+
+#undef RLOCK
+#define RLOCK          RL
+
+#undef WLOCK
+#define WLOCK          WL
+
+#undef INIT
+#define INIT           RWI
diff --git a/lib/locking-selftest-wsem.h b/lib/locking-selftest-wsem.h
new file mode 100644 (file)
index 0000000..b88c5f2
--- /dev/null
@@ -0,0 +1,14 @@
+#undef LOCK
+#define LOCK           WSL
+
+#undef UNLOCK
+#define UNLOCK         WSU
+
+#undef RLOCK
+#define RLOCK          RSL
+
+#undef WLOCK
+#define WLOCK          WSL
+
+#undef INIT
+#define INIT           RWSI
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
new file mode 100644 (file)
index 0000000..7945787
--- /dev/null
@@ -0,0 +1,1216 @@
+/*
+ * lib/locking-selftest.c
+ *
+ * Testsuite for various locking APIs: spinlocks, rwlocks,
+ * mutexes and rw-semaphores.
+ *
+ * It is checking both false positives and false negatives.
+ *
+ * Started by Ingo Molnar:
+ *
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ */
+#include <linux/rwsem.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/lockdep.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include <linux/interrupt.h>
+#include <linux/debug_locks.h>
+#include <linux/irqflags.h>
+
+/*
+ * Change this to 1 if you want to see the failure printouts:
+ */
+static unsigned int debug_locks_verbose;
+
+static int __init setup_debug_locks_verbose(char *str)
+{
+       get_option(&str, &debug_locks_verbose);
+
+       return 1;
+}
+
+__setup("debug_locks_verbose=", setup_debug_locks_verbose);
+
+#define FAILURE                0
+#define SUCCESS                1
+
+#define LOCKTYPE_SPIN  0x1
+#define LOCKTYPE_RWLOCK        0x2
+#define LOCKTYPE_MUTEX 0x4
+#define LOCKTYPE_RWSEM 0x8
+
+/*
+ * Normal standalone locks, for the circular and irq-context
+ * dependency tests:
+ */
+static DEFINE_SPINLOCK(lock_A);
+static DEFINE_SPINLOCK(lock_B);
+static DEFINE_SPINLOCK(lock_C);
+static DEFINE_SPINLOCK(lock_D);
+
+static DEFINE_RWLOCK(rwlock_A);
+static DEFINE_RWLOCK(rwlock_B);
+static DEFINE_RWLOCK(rwlock_C);
+static DEFINE_RWLOCK(rwlock_D);
+
+static DEFINE_MUTEX(mutex_A);
+static DEFINE_MUTEX(mutex_B);
+static DEFINE_MUTEX(mutex_C);
+static DEFINE_MUTEX(mutex_D);
+
+static DECLARE_RWSEM(rwsem_A);
+static DECLARE_RWSEM(rwsem_B);
+static DECLARE_RWSEM(rwsem_C);
+static DECLARE_RWSEM(rwsem_D);
+
+/*
+ * Locks that we initialize dynamically as well so that
+ * e.g. X1 and X2 becomes two instances of the same class,
+ * but X* and Y* are different classes. We do this so that
+ * we do not trigger a real lockup:
+ */
+static DEFINE_SPINLOCK(lock_X1);
+static DEFINE_SPINLOCK(lock_X2);
+static DEFINE_SPINLOCK(lock_Y1);
+static DEFINE_SPINLOCK(lock_Y2);
+static DEFINE_SPINLOCK(lock_Z1);
+static DEFINE_SPINLOCK(lock_Z2);
+
+static DEFINE_RWLOCK(rwlock_X1);
+static DEFINE_RWLOCK(rwlock_X2);
+static DEFINE_RWLOCK(rwlock_Y1);
+static DEFINE_RWLOCK(rwlock_Y2);
+static DEFINE_RWLOCK(rwlock_Z1);
+static DEFINE_RWLOCK(rwlock_Z2);
+
+static DEFINE_MUTEX(mutex_X1);
+static DEFINE_MUTEX(mutex_X2);
+static DEFINE_MUTEX(mutex_Y1);
+static DEFINE_MUTEX(mutex_Y2);
+static DEFINE_MUTEX(mutex_Z1);
+static DEFINE_MUTEX(mutex_Z2);
+
+static DECLARE_RWSEM(rwsem_X1);
+static DECLARE_RWSEM(rwsem_X2);
+static DECLARE_RWSEM(rwsem_Y1);
+static DECLARE_RWSEM(rwsem_Y2);
+static DECLARE_RWSEM(rwsem_Z1);
+static DECLARE_RWSEM(rwsem_Z2);
+
+/*
+ * non-inlined runtime initializers, to let separate locks share
+ * the same lock-class:
+ */
+#define INIT_CLASS_FUNC(class)                                 \
+static noinline void                                   \
+init_class_##class(spinlock_t *lock, rwlock_t *rwlock, struct mutex *mutex, \
+                struct rw_semaphore *rwsem)            \
+{                                                      \
+       spin_lock_init(lock);                           \
+       rwlock_init(rwlock);                            \
+       mutex_init(mutex);                              \
+       init_rwsem(rwsem);                              \
+}
+
+INIT_CLASS_FUNC(X)
+INIT_CLASS_FUNC(Y)
+INIT_CLASS_FUNC(Z)
+
+static void init_shared_classes(void)
+{
+       init_class_X(&lock_X1, &rwlock_X1, &mutex_X1, &rwsem_X1);
+       init_class_X(&lock_X2, &rwlock_X2, &mutex_X2, &rwsem_X2);
+
+       init_class_Y(&lock_Y1, &rwlock_Y1, &mutex_Y1, &rwsem_Y1);
+       init_class_Y(&lock_Y2, &rwlock_Y2, &mutex_Y2, &rwsem_Y2);
+
+       init_class_Z(&lock_Z1, &rwlock_Z1, &mutex_Z1, &rwsem_Z1);
+       init_class_Z(&lock_Z2, &rwlock_Z2, &mutex_Z2, &rwsem_Z2);
+}
+
+/*
+ * For spinlocks and rwlocks we also do hardirq-safe / softirq-safe tests.
+ * The following functions use a lock from a simulated hardirq/softirq
+ * context, causing the locks to be marked as hardirq-safe/softirq-safe:
+ */
+
+#define HARDIRQ_DISABLE                local_irq_disable
+#define HARDIRQ_ENABLE         local_irq_enable
+
+#define HARDIRQ_ENTER()                                \
+       local_irq_disable();                    \
+       irq_enter();                            \
+       WARN_ON(!in_irq());
+
+#define HARDIRQ_EXIT()                         \
+       __irq_exit();                           \
+       local_irq_enable();
+
+#define SOFTIRQ_DISABLE                local_bh_disable
+#define SOFTIRQ_ENABLE         local_bh_enable
+
+#define SOFTIRQ_ENTER()                                \
+               local_bh_disable();             \
+               local_irq_disable();            \
+               trace_softirq_enter();          \
+               WARN_ON(!in_softirq());
+
+#define SOFTIRQ_EXIT()                         \
+               trace_softirq_exit();           \
+               local_irq_enable();             \
+               local_bh_enable();
+
+/*
+ * Shortcuts for lock/unlock API variants, to keep
+ * the testcases compact:
+ */
+#define L(x)                   spin_lock(&lock_##x)
+#define U(x)                   spin_unlock(&lock_##x)
+#define LU(x)                  L(x); U(x)
+#define SI(x)                  spin_lock_init(&lock_##x)
+
+#define WL(x)                  write_lock(&rwlock_##x)
+#define WU(x)                  write_unlock(&rwlock_##x)
+#define WLU(x)                 WL(x); WU(x)
+
+#define RL(x)                  read_lock(&rwlock_##x)
+#define RU(x)                  read_unlock(&rwlock_##x)
+#define RLU(x)                 RL(x); RU(x)
+#define RWI(x)                 rwlock_init(&rwlock_##x)
+
+#define ML(x)                  mutex_lock(&mutex_##x)
+#define MU(x)                  mutex_unlock(&mutex_##x)
+#define MI(x)                  mutex_init(&mutex_##x)
+
+#define WSL(x)                 down_write(&rwsem_##x)
+#define WSU(x)                 up_write(&rwsem_##x)
+
+#define RSL(x)                 down_read(&rwsem_##x)
+#define RSU(x)                 up_read(&rwsem_##x)
+#define RWSI(x)                        init_rwsem(&rwsem_##x)
+
+#define LOCK_UNLOCK_2(x,y)     LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x)
+
+/*
+ * Generate different permutations of the same testcase, using
+ * the same basic lock-dependency/state events:
+ */
+
+#define GENERATE_TESTCASE(name)                        \
+                                               \
+static void name(void) { E(); }
+
+#define GENERATE_PERMUTATIONS_2_EVENTS(name)   \
+                                               \
+static void name##_12(void) { E1(); E2(); }    \
+static void name##_21(void) { E2(); E1(); }
+
+#define GENERATE_PERMUTATIONS_3_EVENTS(name)           \
+                                                       \
+static void name##_123(void) { E1(); E2(); E3(); }     \
+static void name##_132(void) { E1(); E3(); E2(); }     \
+static void name##_213(void) { E2(); E1(); E3(); }     \
+static void name##_231(void) { E2(); E3(); E1(); }     \
+static void name##_312(void) { E3(); E1(); E2(); }     \
+static void name##_321(void) { E3(); E2(); E1(); }
+
+/*
+ * AA deadlock:
+ */
+
+#define E()                                    \
+                                               \
+       LOCK(X1);                               \
+       LOCK(X2); /* this one should fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(AA_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(AA_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(AA_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(AA_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(AA_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(AA_rsem)
+
+#undef E
+
+/*
+ * Special-case for read-locking, they are
+ * allowed to recurse on the same lock class:
+ */
+static void rlock_AA1(void)
+{
+       RL(X1);
+       RL(X1); // this one should NOT fail
+}
+
+static void rlock_AA1B(void)
+{
+       RL(X1);
+       RL(X2); // this one should NOT fail
+}
+
+static void rsem_AA1(void)
+{
+       RSL(X1);
+       RSL(X1); // this one should fail
+}
+
+static void rsem_AA1B(void)
+{
+       RSL(X1);
+       RSL(X2); // this one should fail
+}
+/*
+ * The mixing of read and write locks is not allowed:
+ */
+static void rlock_AA2(void)
+{
+       RL(X1);
+       WL(X2); // this one should fail
+}
+
+static void rsem_AA2(void)
+{
+       RSL(X1);
+       WSL(X2); // this one should fail
+}
+
+static void rlock_AA3(void)
+{
+       WL(X1);
+       RL(X2); // this one should fail
+}
+
+static void rsem_AA3(void)
+{
+       WSL(X1);
+       RSL(X2); // this one should fail
+}
+
+/*
+ * ABBA deadlock:
+ */
+
+#define E()                                    \
+                                               \
+       LOCK_UNLOCK_2(A, B);                    \
+       LOCK_UNLOCK_2(B, A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(ABBA_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(ABBA_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(ABBA_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(ABBA_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(ABBA_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(ABBA_rsem)
+
+#undef E
+
+/*
+ * AB BC CA deadlock:
+ */
+
+#define E()                                    \
+                                               \
+       LOCK_UNLOCK_2(A, B);                    \
+       LOCK_UNLOCK_2(B, C);                    \
+       LOCK_UNLOCK_2(C, A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(ABBCCA_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(ABBCCA_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(ABBCCA_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(ABBCCA_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(ABBCCA_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(ABBCCA_rsem)
+
+#undef E
+
+/*
+ * AB CA BC deadlock:
+ */
+
+#define E()                                    \
+                                               \
+       LOCK_UNLOCK_2(A, B);                    \
+       LOCK_UNLOCK_2(C, A);                    \
+       LOCK_UNLOCK_2(B, C); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(ABCABC_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(ABCABC_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(ABCABC_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(ABCABC_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(ABCABC_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(ABCABC_rsem)
+
+#undef E
+
+/*
+ * AB BC CD DA deadlock:
+ */
+
+#define E()                                    \
+                                               \
+       LOCK_UNLOCK_2(A, B);                    \
+       LOCK_UNLOCK_2(B, C);                    \
+       LOCK_UNLOCK_2(C, D);                    \
+       LOCK_UNLOCK_2(D, A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(ABBCCDDA_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(ABBCCDDA_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(ABBCCDDA_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(ABBCCDDA_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(ABBCCDDA_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(ABBCCDDA_rsem)
+
+#undef E
+
+/*
+ * AB CD BD DA deadlock:
+ */
+#define E()                                    \
+                                               \
+       LOCK_UNLOCK_2(A, B);                    \
+       LOCK_UNLOCK_2(C, D);                    \
+       LOCK_UNLOCK_2(B, D);                    \
+       LOCK_UNLOCK_2(D, A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(ABCDBDDA_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(ABCDBDDA_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(ABCDBDDA_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(ABCDBDDA_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(ABCDBDDA_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(ABCDBDDA_rsem)
+
+#undef E
+
+/*
+ * AB CD BC DA deadlock:
+ */
+#define E()                                    \
+                                               \
+       LOCK_UNLOCK_2(A, B);                    \
+       LOCK_UNLOCK_2(C, D);                    \
+       LOCK_UNLOCK_2(B, C);                    \
+       LOCK_UNLOCK_2(D, A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(ABCDBCDA_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(ABCDBCDA_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(ABCDBCDA_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(ABCDBCDA_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(ABCDBCDA_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(ABCDBCDA_rsem)
+
+#undef E
+
+/*
+ * Double unlock:
+ */
+#define E()                                    \
+                                               \
+       LOCK(A);                                \
+       UNLOCK(A);                              \
+       UNLOCK(A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(double_unlock_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(double_unlock_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(double_unlock_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(double_unlock_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(double_unlock_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(double_unlock_rsem)
+
+#undef E
+
+/*
+ * Bad unlock ordering:
+ */
+#define E()                                    \
+                                               \
+       LOCK(A);                                \
+       LOCK(B);                                \
+       UNLOCK(A); /* fail */                   \
+       UNLOCK(B);
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(bad_unlock_order_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(bad_unlock_order_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(bad_unlock_order_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(bad_unlock_order_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(bad_unlock_order_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(bad_unlock_order_rsem)
+
+#undef E
+
+/*
+ * initializing a held lock:
+ */
+#define E()                                    \
+                                               \
+       LOCK(A);                                \
+       INIT(A); /* fail */
+
+/*
+ * 6 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_TESTCASE(init_held_spin)
+#include "locking-selftest-wlock.h"
+GENERATE_TESTCASE(init_held_wlock)
+#include "locking-selftest-rlock.h"
+GENERATE_TESTCASE(init_held_rlock)
+#include "locking-selftest-mutex.h"
+GENERATE_TESTCASE(init_held_mutex)
+#include "locking-selftest-wsem.h"
+GENERATE_TESTCASE(init_held_wsem)
+#include "locking-selftest-rsem.h"
+GENERATE_TESTCASE(init_held_rsem)
+
+#undef E
+
+/*
+ * locking an irq-safe lock with irqs enabled:
+ */
+#define E1()                           \
+                                       \
+       IRQ_ENTER();                    \
+       LOCK(A);                        \
+       UNLOCK(A);                      \
+       IRQ_EXIT();
+
+#define E2()                           \
+                                       \
+       LOCK(A);                        \
+       UNLOCK(A);
+
+/*
+ * Generate 24 testcases:
+ */
+#include "locking-selftest-spin-hardirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin)
+
+#include "locking-selftest-rlock-hardirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_rlock)
+
+#include "locking-selftest-wlock-hardirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_wlock)
+
+#include "locking-selftest-spin-softirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_spin)
+
+#include "locking-selftest-rlock-softirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_rlock)
+
+#include "locking-selftest-wlock-softirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_wlock)
+
+#undef E1
+#undef E2
+
+/*
+ * Enabling hardirqs with a softirq-safe lock held:
+ */
+#define E1()                           \
+                                       \
+       SOFTIRQ_ENTER();                \
+       LOCK(A);                        \
+       UNLOCK(A);                      \
+       SOFTIRQ_EXIT();
+
+#define E2()                           \
+                                       \
+       HARDIRQ_DISABLE();              \
+       LOCK(A);                        \
+       HARDIRQ_ENABLE();               \
+       UNLOCK(A);
+
+/*
+ * Generate 12 testcases:
+ */
+#include "locking-selftest-spin.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_spin)
+
+#include "locking-selftest-wlock.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_wlock)
+
+#include "locking-selftest-rlock.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock)
+
+#undef E1
+#undef E2
+
+/*
+ * Enabling irqs with an irq-safe lock held:
+ */
+#define E1()                           \
+                                       \
+       IRQ_ENTER();                    \
+       LOCK(A);                        \
+       UNLOCK(A);                      \
+       IRQ_EXIT();
+
+#define E2()                           \
+                                       \
+       IRQ_DISABLE();                  \
+       LOCK(A);                        \
+       IRQ_ENABLE();                   \
+       UNLOCK(A);
+
+/*
+ * Generate 24 testcases:
+ */
+#include "locking-selftest-spin-hardirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin)
+
+#include "locking-selftest-rlock-hardirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock)
+
+#include "locking-selftest-wlock-hardirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_wlock)
+
+#include "locking-selftest-spin-softirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_spin)
+
+#include "locking-selftest-rlock-softirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock)
+
+#include "locking-selftest-wlock-softirq.h"
+GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock)
+
+#undef E1
+#undef E2
+
+/*
+ * Acquiring a irq-unsafe lock while holding an irq-safe-lock:
+ */
+#define E1()                           \
+                                       \
+       LOCK(A);                        \
+       LOCK(B);                        \
+       UNLOCK(B);                      \
+       UNLOCK(A);                      \
+
+#define E2()                           \
+                                       \
+       LOCK(B);                        \
+       UNLOCK(B);
+
+#define E3()                           \
+                                       \
+       IRQ_ENTER();                    \
+       LOCK(A);                        \
+       UNLOCK(A);                      \
+       IRQ_EXIT();
+
+/*
+ * Generate 36 testcases:
+ */
+#include "locking-selftest-spin-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin)
+
+#include "locking-selftest-rlock-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock)
+
+#include "locking-selftest-wlock-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_wlock)
+
+#include "locking-selftest-spin-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_spin)
+
+#include "locking-selftest-rlock-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock)
+
+#include "locking-selftest-wlock-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * If a lock turns into softirq-safe, but earlier it took
+ * a softirq-unsafe lock:
+ */
+
+#define E1()                           \
+       IRQ_DISABLE();                  \
+       LOCK(A);                        \
+       LOCK(B);                        \
+       UNLOCK(B);                      \
+       UNLOCK(A);                      \
+       IRQ_ENABLE();
+
+#define E2()                           \
+       LOCK(B);                        \
+       UNLOCK(B);
+
+#define E3()                           \
+       IRQ_ENTER();                    \
+       LOCK(A);                        \
+       UNLOCK(A);                      \
+       IRQ_EXIT();
+
+/*
+ * Generate 36 testcases:
+ */
+#include "locking-selftest-spin-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin)
+
+#include "locking-selftest-rlock-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock)
+
+#include "locking-selftest-wlock-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_wlock)
+
+#include "locking-selftest-spin-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_spin)
+
+#include "locking-selftest-rlock-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock)
+
+#include "locking-selftest-wlock-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_wlock)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * read-lock / write-lock irq inversion.
+ *
+ * Deadlock scenario:
+ *
+ * CPU#1 is at #1, i.e. it has write-locked A, but has not
+ * taken B yet.
+ *
+ * CPU#2 is at #2, i.e. it has locked B.
+ *
+ * Hardirq hits CPU#2 at point #2 and is trying to read-lock A.
+ *
+ * The deadlock occurs because CPU#1 will spin on B, and CPU#2
+ * will spin on A.
+ */
+
+#define E1()                           \
+                                       \
+       IRQ_DISABLE();                  \
+       WL(A);                          \
+       LOCK(B);                        \
+       UNLOCK(B);                      \
+       WU(A);                          \
+       IRQ_ENABLE();
+
+#define E2()                           \
+                                       \
+       LOCK(B);                        \
+       UNLOCK(B);
+
+#define E3()                           \
+                                       \
+       IRQ_ENTER();                    \
+       RL(A);                          \
+       RU(A);                          \
+       IRQ_EXIT();
+
+/*
+ * Generate 36 testcases:
+ */
+#include "locking-selftest-spin-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_spin)
+
+#include "locking-selftest-rlock-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_rlock)
+
+#include "locking-selftest-wlock-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_wlock)
+
+#include "locking-selftest-spin-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_spin)
+
+#include "locking-selftest-rlock-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_rlock)
+
+#include "locking-selftest-wlock-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_wlock)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * read-lock / write-lock recursion that is actually safe.
+ */
+
+#define E1()                           \
+                                       \
+       IRQ_DISABLE();                  \
+       WL(A);                          \
+       WU(A);                          \
+       IRQ_ENABLE();
+
+#define E2()                           \
+                                       \
+       RL(A);                          \
+       RU(A);                          \
+
+#define E3()                           \
+                                       \
+       IRQ_ENTER();                    \
+       RL(A);                          \
+       L(B);                           \
+       U(B);                           \
+       RU(A);                          \
+       IRQ_EXIT();
+
+/*
+ * Generate 12 testcases:
+ */
+#include "locking-selftest-hardirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_hard)
+
+#include "locking-selftest-softirq.h"
+GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * read-lock / write-lock recursion that is unsafe.
+ */
+
+#define E1()                           \
+                                       \
+       IRQ_DISABLE();                  \
+       L(B);                           \
+       WL(A);                          \
+       WU(A);                          \
+       U(B);                           \
+       IRQ_ENABLE();
+
+#define E2()                           \
+                                       \
+       RL(A);                          \
+       RU(A);                          \
+
+#define E3()                           \
+                                       \
+       IRQ_ENTER();                    \
+       L(B);                           \
+       U(B);                           \
+       IRQ_EXIT();
+
+/*
+ * Generate 12 testcases:
+ */
+#include "locking-selftest-hardirq.h"
+// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_hard)
+
+#include "locking-selftest-softirq.h"
+// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_soft)
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define I_SPINLOCK(x) lockdep_reset_lock(&lock_##x.dep_map)
+# define I_RWLOCK(x)   lockdep_reset_lock(&rwlock_##x.dep_map)
+# define I_MUTEX(x)    lockdep_reset_lock(&mutex_##x.dep_map)
+# define I_RWSEM(x)    lockdep_reset_lock(&rwsem_##x.dep_map)
+#else
+# define I_SPINLOCK(x)
+# define I_RWLOCK(x)
+# define I_MUTEX(x)
+# define I_RWSEM(x)
+#endif
+
+#define I1(x)                                  \
+       do {                                    \
+               I_SPINLOCK(x);                  \
+               I_RWLOCK(x);                    \
+               I_MUTEX(x);                     \
+               I_RWSEM(x);                     \
+       } while (0)
+
+#define I2(x)                                  \
+       do {                                    \
+               spin_lock_init(&lock_##x);      \
+               rwlock_init(&rwlock_##x);       \
+               mutex_init(&mutex_##x);         \
+               init_rwsem(&rwsem_##x);         \
+       } while (0)
+
+static void reset_locks(void)
+{
+       local_irq_disable();
+       I1(A); I1(B); I1(C); I1(D);
+       I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2);
+       lockdep_reset();
+       I2(A); I2(B); I2(C); I2(D);
+       init_shared_classes();
+       local_irq_enable();
+}
+
+#undef I
+
+static int testcase_total;
+static int testcase_successes;
+static int expected_testcase_failures;
+static int unexpected_testcase_failures;
+
+static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
+{
+       unsigned long saved_preempt_count = preempt_count();
+       int expected_failure = 0;
+
+       WARN_ON(irqs_disabled());
+
+       testcase_fn();
+       /*
+        * Filter out expected failures:
+        */
+#ifndef CONFIG_PROVE_LOCKING
+       if ((lockclass_mask & LOCKTYPE_SPIN) && debug_locks != expected)
+               expected_failure = 1;
+       if ((lockclass_mask & LOCKTYPE_RWLOCK) && debug_locks != expected)
+               expected_failure = 1;
+       if ((lockclass_mask & LOCKTYPE_MUTEX) && debug_locks != expected)
+               expected_failure = 1;
+       if ((lockclass_mask & LOCKTYPE_RWSEM) && debug_locks != expected)
+               expected_failure = 1;
+#endif
+       if (debug_locks != expected) {
+               if (expected_failure) {
+                       expected_testcase_failures++;
+                       printk("failed|");
+               } else {
+                       unexpected_testcase_failures++;
+                       printk("FAILED|");
+               }
+       } else {
+               testcase_successes++;
+               printk("  ok  |");
+       }
+       testcase_total++;
+
+       if (debug_locks_verbose)
+               printk(" lockclass mask: %x, debug_locks: %d, expected: %d\n",
+                       lockclass_mask, debug_locks, expected);
+       /*
+        * Some tests (e.g. double-unlock) might corrupt the preemption
+        * count, so restore it:
+        */
+       preempt_count() = saved_preempt_count;
+#ifdef CONFIG_TRACE_IRQFLAGS
+       if (softirq_count())
+               current->softirqs_enabled = 0;
+       else
+               current->softirqs_enabled = 1;
+#endif
+
+       reset_locks();
+}
+
+static inline void print_testname(const char *testname)
+{
+       printk("%33s:", testname);
+}
+
+#define DO_TESTCASE_1(desc, name, nr)                          \
+       print_testname(desc"/"#nr);                             \
+       dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK);          \
+       printk("\n");
+
+#define DO_TESTCASE_1B(desc, name, nr)                         \
+       print_testname(desc"/"#nr);                             \
+       dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK);          \
+       printk("\n");
+
+#define DO_TESTCASE_3(desc, name, nr)                          \
+       print_testname(desc"/"#nr);                             \
+       dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN);       \
+       dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK);    \
+       dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK);    \
+       printk("\n");
+
+#define DO_TESTCASE_3RW(desc, name, nr)                                \
+       print_testname(desc"/"#nr);                             \
+       dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN|LOCKTYPE_RWLOCK);\
+       dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK);    \
+       dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK);    \
+       printk("\n");
+
+#define DO_TESTCASE_6(desc, name)                              \
+       print_testname(desc);                                   \
+       dotest(name##_spin, FAILURE, LOCKTYPE_SPIN);            \
+       dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK);         \
+       dotest(name##_rlock, FAILURE, LOCKTYPE_RWLOCK);         \
+       dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX);          \
+       dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM);           \
+       dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM);           \
+       printk("\n");
+
+#define DO_TESTCASE_6_SUCCESS(desc, name)                      \
+       print_testname(desc);                                   \
+       dotest(name##_spin, SUCCESS, LOCKTYPE_SPIN);            \
+       dotest(name##_wlock, SUCCESS, LOCKTYPE_RWLOCK);         \
+       dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK);         \
+       dotest(name##_mutex, SUCCESS, LOCKTYPE_MUTEX);          \
+       dotest(name##_wsem, SUCCESS, LOCKTYPE_RWSEM);           \
+       dotest(name##_rsem, SUCCESS, LOCKTYPE_RWSEM);           \
+       printk("\n");
+
+/*
+ * 'read' variant: rlocks must not trigger.
+ */
+#define DO_TESTCASE_6R(desc, name)                             \
+       print_testname(desc);                                   \
+       dotest(name##_spin, FAILURE, LOCKTYPE_SPIN);            \
+       dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK);         \
+       dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK);         \
+       dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX);          \
+       dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM);           \
+       dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM);           \
+       printk("\n");
+
+#define DO_TESTCASE_2I(desc, name, nr)                         \
+       DO_TESTCASE_1("hard-"desc, name##_hard, nr);            \
+       DO_TESTCASE_1("soft-"desc, name##_soft, nr);
+
+#define DO_TESTCASE_2IB(desc, name, nr)                                \
+       DO_TESTCASE_1B("hard-"desc, name##_hard, nr);           \
+       DO_TESTCASE_1B("soft-"desc, name##_soft, nr);
+
+#define DO_TESTCASE_6I(desc, name, nr)                         \
+       DO_TESTCASE_3("hard-"desc, name##_hard, nr);            \
+       DO_TESTCASE_3("soft-"desc, name##_soft, nr);
+
+#define DO_TESTCASE_6IRW(desc, name, nr)                       \
+       DO_TESTCASE_3RW("hard-"desc, name##_hard, nr);          \
+       DO_TESTCASE_3RW("soft-"desc, name##_soft, nr);
+
+#define DO_TESTCASE_2x3(desc, name)                            \
+       DO_TESTCASE_3(desc, name, 12);                          \
+       DO_TESTCASE_3(desc, name, 21);
+
+#define DO_TESTCASE_2x6(desc, name)                            \
+       DO_TESTCASE_6I(desc, name, 12);                         \
+       DO_TESTCASE_6I(desc, name, 21);
+
+#define DO_TESTCASE_6x2(desc, name)                            \
+       DO_TESTCASE_2I(desc, name, 123);                        \
+       DO_TESTCASE_2I(desc, name, 132);                        \
+       DO_TESTCASE_2I(desc, name, 213);                        \
+       DO_TESTCASE_2I(desc, name, 231);                        \
+       DO_TESTCASE_2I(desc, name, 312);                        \
+       DO_TESTCASE_2I(desc, name, 321);
+
+#define DO_TESTCASE_6x2B(desc, name)                           \
+       DO_TESTCASE_2IB(desc, name, 123);                       \
+       DO_TESTCASE_2IB(desc, name, 132);                       \
+       DO_TESTCASE_2IB(desc, name, 213);                       \
+       DO_TESTCASE_2IB(desc, name, 231);                       \
+       DO_TESTCASE_2IB(desc, name, 312);                       \
+       DO_TESTCASE_2IB(desc, name, 321);
+
+#define DO_TESTCASE_6x6(desc, name)                            \
+       DO_TESTCASE_6I(desc, name, 123);                        \
+       DO_TESTCASE_6I(desc, name, 132);                        \
+       DO_TESTCASE_6I(desc, name, 213);                        \
+       DO_TESTCASE_6I(desc, name, 231);                        \
+       DO_TESTCASE_6I(desc, name, 312);                        \
+       DO_TESTCASE_6I(desc, name, 321);
+
+#define DO_TESTCASE_6x6RW(desc, name)                          \
+       DO_TESTCASE_6IRW(desc, name, 123);                      \
+       DO_TESTCASE_6IRW(desc, name, 132);                      \
+       DO_TESTCASE_6IRW(desc, name, 213);                      \
+       DO_TESTCASE_6IRW(desc, name, 231);                      \
+       DO_TESTCASE_6IRW(desc, name, 312);                      \
+       DO_TESTCASE_6IRW(desc, name, 321);
+
+
+void locking_selftest(void)
+{
+       /*
+        * Got a locking failure before the selftest ran?
+        */
+       if (!debug_locks) {
+               printk("----------------------------------\n");
+               printk("| Locking API testsuite disabled |\n");
+               printk("----------------------------------\n");
+               return;
+       }
+
+       /*
+        * Run the testsuite:
+        */
+       printk("------------------------\n");
+       printk("| Locking API testsuite:\n");
+       printk("----------------------------------------------------------------------------\n");
+       printk("                                 | spin |wlock |rlock |mutex | wsem | rsem |\n");
+       printk("  --------------------------------------------------------------------------\n");
+
+       init_shared_classes();
+       debug_locks_silent = !debug_locks_verbose;
+
+       DO_TESTCASE_6R("A-A deadlock", AA);
+       DO_TESTCASE_6R("A-B-B-A deadlock", ABBA);
+       DO_TESTCASE_6R("A-B-B-C-C-A deadlock", ABBCCA);
+       DO_TESTCASE_6R("A-B-C-A-B-C deadlock", ABCABC);
+       DO_TESTCASE_6R("A-B-B-C-C-D-D-A deadlock", ABBCCDDA);
+       DO_TESTCASE_6R("A-B-C-D-B-D-D-A deadlock", ABCDBDDA);
+       DO_TESTCASE_6R("A-B-C-D-B-C-D-A deadlock", ABCDBCDA);
+       DO_TESTCASE_6("double unlock", double_unlock);
+       DO_TESTCASE_6("initialize held", init_held);
+       DO_TESTCASE_6_SUCCESS("bad unlock order", bad_unlock_order);
+
+       printk("  --------------------------------------------------------------------------\n");
+       print_testname("recursive read-lock");
+       printk("             |");
+       dotest(rlock_AA1, SUCCESS, LOCKTYPE_RWLOCK);
+       printk("             |");
+       dotest(rsem_AA1, FAILURE, LOCKTYPE_RWSEM);
+       printk("\n");
+
+       print_testname("recursive read-lock #2");
+       printk("             |");
+       dotest(rlock_AA1B, SUCCESS, LOCKTYPE_RWLOCK);
+       printk("             |");
+       dotest(rsem_AA1B, FAILURE, LOCKTYPE_RWSEM);
+       printk("\n");
+
+       print_testname("mixed read-write-lock");
+       printk("             |");
+       dotest(rlock_AA2, FAILURE, LOCKTYPE_RWLOCK);
+       printk("             |");
+       dotest(rsem_AA2, FAILURE, LOCKTYPE_RWSEM);
+       printk("\n");
+
+       print_testname("mixed write-read-lock");
+       printk("             |");
+       dotest(rlock_AA3, FAILURE, LOCKTYPE_RWLOCK);
+       printk("             |");
+       dotest(rsem_AA3, FAILURE, LOCKTYPE_RWSEM);
+       printk("\n");
+
+       printk("  --------------------------------------------------------------------------\n");
+
+       /*
+        * irq-context testcases:
+        */
+       DO_TESTCASE_2x6("irqs-on + irq-safe-A", irqsafe1);
+       DO_TESTCASE_2x3("sirq-safe-A => hirqs-on", irqsafe2A);
+       DO_TESTCASE_2x6("safe-A + irqs-on", irqsafe2B);
+       DO_TESTCASE_6x6("safe-A + unsafe-B #1", irqsafe3);
+       DO_TESTCASE_6x6("safe-A + unsafe-B #2", irqsafe4);
+       DO_TESTCASE_6x6RW("irq lock-inversion", irq_inversion);
+
+       DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion);
+//     DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2);
+
+       if (unexpected_testcase_failures) {
+               printk("-----------------------------------------------------------------\n");
+               debug_locks = 0;
+               printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n",
+                       unexpected_testcase_failures, testcase_total);
+               printk("-----------------------------------------------------------------\n");
+       } else if (expected_testcase_failures && testcase_successes) {
+               printk("--------------------------------------------------------\n");
+               printk("%3d out of %3d testcases failed, as expected. |\n",
+                       expected_testcase_failures, testcase_total);
+               printk("----------------------------------------------------\n");
+               debug_locks = 1;
+       } else if (expected_testcase_failures && !testcase_successes) {
+               printk("--------------------------------------------------------\n");
+               printk("All %3d testcases failed, as expected. |\n",
+                       expected_testcase_failures);
+               printk("----------------------------------------\n");
+               debug_locks = 1;
+       } else {
+               printk("-------------------------------------------------------\n");
+               printk("Good, all %3d testcases passed! |\n",
+                       testcase_successes);
+               printk("---------------------------------\n");
+               debug_locks = 1;
+       }
+       debug_locks_silent = 0;
+}
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
new file mode 100644 (file)
index 0000000..8504490
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Fast batching percpu counters.
+ */
+
+#include <linux/percpu_counter.h>
+#include <linux/module.h>
+
+void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
+{
+       long count;
+       s32 *pcount;
+       int cpu = get_cpu();
+
+       pcount = per_cpu_ptr(fbc->counters, cpu);
+       count = *pcount + amount;
+       if (count >= FBC_BATCH || count <= -FBC_BATCH) {
+               spin_lock(&fbc->lock);
+               fbc->count += count;
+               *pcount = 0;
+               spin_unlock(&fbc->lock);
+       } else {
+               *pcount = count;
+       }
+       put_cpu();
+}
+EXPORT_SYMBOL(percpu_counter_mod);
+
+/*
+ * Add up all the per-cpu counts, return the result.  This is a more accurate
+ * but much slower version of percpu_counter_read_positive()
+ */
+s64 percpu_counter_sum(struct percpu_counter *fbc)
+{
+       s64 ret;
+       int cpu;
+
+       spin_lock(&fbc->lock);
+       ret = fbc->count;
+       for_each_possible_cpu(cpu) {
+               s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
+               ret += *pcount;
+       }
+       spin_unlock(&fbc->lock);
+       return ret < 0 ? 0 : ret;
+}
+EXPORT_SYMBOL(percpu_counter_sum);
diff --git a/lib/plist.c b/lib/plist.c
new file mode 100644 (file)
index 0000000..3074a02
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * lib/plist.c
+ *
+ * Descending-priority-sorted double-linked list
+ *
+ * (C) 2002-2003 Intel Corp
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
+ *
+ * 2001-2005 (c) MontaVista Software, Inc.
+ * Daniel Walker <dwalker@mvista.com>
+ *
+ * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Simplifications of the original code by
+ * Oleg Nesterov <oleg@tv-sign.ru>
+ *
+ * Licensed under the FSF's GNU Public License v2 or later.
+ *
+ * Based on simple lists (include/linux/list.h).
+ *
+ * This file contains the add / del functions which are considered to
+ * be too large to inline. See include/linux/plist.h for further
+ * information.
+ */
+
+#include <linux/plist.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_DEBUG_PI_LIST
+
+static void plist_check_prev_next(struct list_head *t, struct list_head *p,
+                                 struct list_head *n)
+{
+       if (n->prev != p || p->next != n) {
+               printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev);
+               printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev);
+               printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev);
+               WARN_ON(1);
+       }
+}
+
+static void plist_check_list(struct list_head *top)
+{
+       struct list_head *prev = top, *next = top->next;
+
+       plist_check_prev_next(top, prev, next);
+       while (next != top) {
+               prev = next;
+               next = prev->next;
+               plist_check_prev_next(top, prev, next);
+       }
+}
+
+static void plist_check_head(struct plist_head *head)
+{
+       WARN_ON(!head->lock);
+       if (head->lock)
+               WARN_ON_SMP(!spin_is_locked(head->lock));
+       plist_check_list(&head->prio_list);
+       plist_check_list(&head->node_list);
+}
+
+#else
+# define plist_check_head(h)   do { } while (0)
+#endif
+
+/**
+ * plist_add - add @node to @head
+ *
+ * @node:      &struct plist_node pointer
+ * @head:      &struct plist_head pointer
+ */
+void plist_add(struct plist_node *node, struct plist_head *head)
+{
+       struct plist_node *iter;
+
+       plist_check_head(head);
+       WARN_ON(!plist_node_empty(node));
+
+       list_for_each_entry(iter, &head->prio_list, plist.prio_list) {
+               if (node->prio < iter->prio)
+                       goto lt_prio;
+               else if (node->prio == iter->prio) {
+                       iter = list_entry(iter->plist.prio_list.next,
+                                       struct plist_node, plist.prio_list);
+                       goto eq_prio;
+               }
+       }
+
+lt_prio:
+       list_add_tail(&node->plist.prio_list, &iter->plist.prio_list);
+eq_prio:
+       list_add_tail(&node->plist.node_list, &iter->plist.node_list);
+
+       plist_check_head(head);
+}
+
+/**
+ * plist_del - Remove a @node from plist.
+ *
+ * @node:      &struct plist_node pointer - entry to be removed
+ * @head:      &struct plist_head pointer - list head
+ */
+void plist_del(struct plist_node *node, struct plist_head *head)
+{
+       plist_check_head(head);
+
+       if (!list_empty(&node->plist.prio_list)) {
+               struct plist_node *next = plist_first(&node->plist);
+
+               list_move_tail(&next->plist.prio_list, &node->plist.prio_list);
+               list_del_init(&node->plist.prio_list);
+       }
+
+       list_del_init(&node->plist.node_list);
+
+       plist_check_head(head);
+}
diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h
new file mode 100644 (file)
index 0000000..df8a6c9
--- /dev/null
@@ -0,0 +1,107 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN,        /* i: waiting for length/lit code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+        NAME -> COMMENT -> HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+    Read deflate blocks:
+            TYPE -> STORED or TABLE or LEN or CHECK
+            STORED -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN
+    Read deflate codes:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 7K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+ /*   gz_headerp head; */           /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const *lencode;    /* starting table for length/literal codes */
+    code const *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+};
diff --git a/mm/vmstat.c b/mm/vmstat.c
new file mode 100644 (file)
index 0000000..321668a
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ *  linux/mm/vmstat.c
+ *
+ *  Manages VM statistics
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  zoned VM statistics
+ *  Copyright (C) 2006 Silicon Graphics, Inc.,
+ *             Christoph Lameter <christoph@lameter.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/cpu.h>
+
+void __get_zone_counts(unsigned long *active, unsigned long *inactive,
+                       unsigned long *free, struct pglist_data *pgdat)
+{
+       struct zone *zones = pgdat->node_zones;
+       int i;
+
+       *active = 0;
+       *inactive = 0;
+       *free = 0;
+       for (i = 0; i < MAX_NR_ZONES; i++) {
+               *active += zones[i].nr_active;
+               *inactive += zones[i].nr_inactive;
+               *free += zones[i].free_pages;
+       }
+}
+
+void get_zone_counts(unsigned long *active,
+               unsigned long *inactive, unsigned long *free)
+{
+       struct pglist_data *pgdat;
+
+       *active = 0;
+       *inactive = 0;
+       *free = 0;
+       for_each_online_pgdat(pgdat) {
+               unsigned long l, m, n;
+               __get_zone_counts(&l, &m, &n, pgdat);
+               *active += l;
+               *inactive += m;
+               *free += n;
+       }
+}
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
+EXPORT_PER_CPU_SYMBOL(vm_event_states);
+
+static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask)
+{
+       int cpu = 0;
+       int i;
+
+       memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));
+
+       cpu = first_cpu(*cpumask);
+       while (cpu < NR_CPUS) {
+               struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
+
+               cpu = next_cpu(cpu, *cpumask);
+
+               if (cpu < NR_CPUS)
+                       prefetch(&per_cpu(vm_event_states, cpu));
+
+
+               for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+                       ret[i] += this->event[i];
+       }
+}
+
+/*
+ * Accumulate the vm event counters across all CPUs.
+ * The result is unavoidably approximate - it can change
+ * during and after execution of this function.
+*/
+void all_vm_events(unsigned long *ret)
+{
+       sum_vm_events(ret, &cpu_online_map);
+}
+EXPORT_SYMBOL_GPL(all_vm_events);
+
+#ifdef CONFIG_HOTPLUG
+/*
+ * Fold the foreign cpu events into our own.
+ *
+ * This is adding to the events on one processor
+ * but keeps the global counts constant.
+ */
+void vm_events_fold_cpu(int cpu)
+{
+       struct vm_event_state *fold_state = &per_cpu(vm_event_states, cpu);
+       int i;
+
+       for (i = 0; i < NR_VM_EVENT_ITEMS; i++) {
+               count_vm_events(i, fold_state->event[i]);
+               fold_state->event[i] = 0;
+       }
+}
+#endif /* CONFIG_HOTPLUG */
+
+#endif /* CONFIG_VM_EVENT_COUNTERS */
+
+/*
+ * Manage combined zone based / global counters
+ *
+ * vm_stat contains the global counters
+ */
+atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+EXPORT_SYMBOL(vm_stat);
+
+#ifdef CONFIG_SMP
+
+static int calculate_threshold(struct zone *zone)
+{
+       int threshold;
+       int mem;        /* memory in 128 MB units */
+
+       /*
+        * The threshold scales with the number of processors and the amount
+        * of memory per zone. More memory means that we can defer updates for
+        * longer, more processors could lead to more contention.
+        * fls() is used to have a cheap way of logarithmic scaling.
+        *
+        * Some sample thresholds:
+        *
+        * Threshold    Processors      (fls)   Zonesize        fls(mem+1)
+        * ------------------------------------------------------------------
+        * 8            1               1       0.9-1 GB        4
+        * 16           2               2       0.9-1 GB        4
+        * 20           2               2       1-2 GB          5
+        * 24           2               2       2-4 GB          6
+        * 28           2               2       4-8 GB          7
+        * 32           2               2       8-16 GB         8
+        * 4            2               2       <128M           1
+        * 30           4               3       2-4 GB          5
+        * 48           4               3       8-16 GB         8
+        * 32           8               4       1-2 GB          4
+        * 32           8               4       0.9-1GB         4
+        * 10           16              5       <128M           1
+        * 40           16              5       900M            4
+        * 70           64              7       2-4 GB          5
+        * 84           64              7       4-8 GB          6
+        * 108          512             9       4-8 GB          6
+        * 125          1024            10      8-16 GB         8
+        * 125          1024            10      16-32 GB        9
+        */
+
+       mem = zone->present_pages >> (27 - PAGE_SHIFT);
+
+       threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem));
+
+       /*
+        * Maximum threshold is 125
+        */
+       threshold = min(125, threshold);
+
+       return threshold;
+}
+
+/*
+ * Refresh the thresholds for each zone.
+ */
+static void refresh_zone_stat_thresholds(void)
+{
+       struct zone *zone;
+       int cpu;
+       int threshold;
+
+       for_each_zone(zone) {
+
+               if (!zone->present_pages)
+                       continue;
+
+               threshold = calculate_threshold(zone);
+
+               for_each_online_cpu(cpu)
+                       zone_pcp(zone, cpu)->stat_threshold = threshold;
+       }
+}
+
+/*
+ * For use when we know that interrupts are disabled.
+ */
+void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
+                               int delta)
+{
+       struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+       s8 *p = pcp->vm_stat_diff + item;
+       long x;
+
+       x = delta + *p;
+
+       if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) {
+               zone_page_state_add(x, zone, item);
+               x = 0;
+       }
+       *p = x;
+}
+EXPORT_SYMBOL(__mod_zone_page_state);
+
+/*
+ * For an unknown interrupt state
+ */
+void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
+                                       int delta)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __mod_zone_page_state(zone, item, delta);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(mod_zone_page_state);
+
+/*
+ * Optimized increment and decrement functions.
+ *
+ * These are only for a single page and therefore can take a struct page *
+ * argument instead of struct zone *. This allows the inclusion of the code
+ * generated for page_zone(page) into the optimized functions.
+ *
+ * No overflow check is necessary and therefore the differential can be
+ * incremented or decremented in place which may allow the compilers to
+ * generate better code.
+ * The increment or decrement is known and therefore one boundary check can
+ * be omitted.
+ *
+ * NOTE: These functions are very performance sensitive. Change only
+ * with care.
+ *
+ * Some processors have inc/dec instructions that are atomic vs an interrupt.
+ * However, the code must first determine the differential location in a zone
+ * based on the processor number and then inc/dec the counter. There is no
+ * guarantee without disabling preemption that the processor will not change
+ * in between and therefore the atomicity vs. interrupt cannot be exploited
+ * in a useful way here.
+ */
+static void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
+{
+       struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+       s8 *p = pcp->vm_stat_diff + item;
+
+       (*p)++;
+
+       if (unlikely(*p > pcp->stat_threshold)) {
+               int overstep = pcp->stat_threshold / 2;
+
+               zone_page_state_add(*p + overstep, zone, item);
+               *p = -overstep;
+       }
+}
+
+void __inc_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+       __inc_zone_state(page_zone(page), item);
+}
+EXPORT_SYMBOL(__inc_zone_page_state);
+
+void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+       struct zone *zone = page_zone(page);
+       struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+       s8 *p = pcp->vm_stat_diff + item;
+
+       (*p)--;
+
+       if (unlikely(*p < - pcp->stat_threshold)) {
+               int overstep = pcp->stat_threshold / 2;
+
+               zone_page_state_add(*p - overstep, zone, item);
+               *p = overstep;
+       }
+}
+EXPORT_SYMBOL(__dec_zone_page_state);
+
+void inc_zone_state(struct zone *zone, enum zone_stat_item item)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __inc_zone_state(zone, item);
+       local_irq_restore(flags);
+}
+
+void inc_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+       unsigned long flags;
+       struct zone *zone;
+
+       zone = page_zone(page);
+       local_irq_save(flags);
+       __inc_zone_state(zone, item);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(inc_zone_page_state);
+
+void dec_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __dec_zone_page_state(page, item);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(dec_zone_page_state);
+
+/*
+ * Update the zone counters for one cpu.
+ */
+void refresh_cpu_vm_stats(int cpu)
+{
+       struct zone *zone;
+       int i;
+       unsigned long flags;
+
+       for_each_zone(zone) {
+               struct per_cpu_pageset *pcp;
+
+               pcp = zone_pcp(zone, cpu);
+
+               for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+                       if (pcp->vm_stat_diff[i]) {
+                               local_irq_save(flags);
+                               zone_page_state_add(pcp->vm_stat_diff[i],
+                                       zone, i);
+                               pcp->vm_stat_diff[i] = 0;
+                               local_irq_restore(flags);
+                       }
+       }
+}
+
+static void __refresh_cpu_vm_stats(void *dummy)
+{
+       refresh_cpu_vm_stats(smp_processor_id());
+}
+
+/*
+ * Consolidate all counters.
+ *
+ * Note that the result is less inaccurate but still inaccurate
+ * if concurrent processes are allowed to run.
+ */
+void refresh_vm_stats(void)
+{
+       on_each_cpu(__refresh_cpu_vm_stats, NULL, 0, 1);
+}
+EXPORT_SYMBOL(refresh_vm_stats);
+
+#endif
+
+#ifdef CONFIG_NUMA
+/*
+ * zonelist = the list of zones passed to the allocator
+ * z       = the zone from which the allocation occurred.
+ *
+ * Must be called with interrupts disabled.
+ */
+void zone_statistics(struct zonelist *zonelist, struct zone *z)
+{
+       if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) {
+               __inc_zone_state(z, NUMA_HIT);
+       } else {
+               __inc_zone_state(z, NUMA_MISS);
+               __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN);
+       }
+       if (z->zone_pgdat == NODE_DATA(numa_node_id()))
+               __inc_zone_state(z, NUMA_LOCAL);
+       else
+               __inc_zone_state(z, NUMA_OTHER);
+}
+#endif
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/seq_file.h>
+
+static void *frag_start(struct seq_file *m, loff_t *pos)
+{
+       pg_data_t *pgdat;
+       loff_t node = *pos;
+       for (pgdat = first_online_pgdat();
+            pgdat && node;
+            pgdat = next_online_pgdat(pgdat))
+               --node;
+
+       return pgdat;
+}
+
+static void *frag_next(struct seq_file *m, void *arg, loff_t *pos)
+{
+       pg_data_t *pgdat = (pg_data_t *)arg;
+
+       (*pos)++;
+       return next_online_pgdat(pgdat);
+}
+
+static void frag_stop(struct seq_file *m, void *arg)
+{
+}
+
+/*
+ * This walks the free areas for each zone.
+ */
+static int frag_show(struct seq_file *m, void *arg)
+{
+       pg_data_t *pgdat = (pg_data_t *)arg;
+       struct zone *zone;
+       struct zone *node_zones = pgdat->node_zones;
+       unsigned long flags;
+       int order;
+
+       for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
+               if (!populated_zone(zone))
+                       continue;
+
+               spin_lock_irqsave(&zone->lock, flags);
+               seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
+               for (order = 0; order < MAX_ORDER; ++order)
+                       seq_printf(m, "%6lu ", zone->free_area[order].nr_free);
+               spin_unlock_irqrestore(&zone->lock, flags);
+               seq_putc(m, '\n');
+       }
+       return 0;
+}
+
+struct seq_operations fragmentation_op = {
+       .start  = frag_start,
+       .next   = frag_next,
+       .stop   = frag_stop,
+       .show   = frag_show,
+};
+
+static char *vmstat_text[] = {
+       /* Zoned VM counters */
+       "nr_anon_pages",
+       "nr_mapped",
+       "nr_file_pages",
+       "nr_slab",
+       "nr_page_table_pages",
+       "nr_dirty",
+       "nr_writeback",
+       "nr_unstable",
+       "nr_bounce",
+
+#ifdef CONFIG_NUMA
+       "numa_hit",
+       "numa_miss",
+       "numa_foreign",
+       "numa_interleave",
+       "numa_local",
+       "numa_other",
+#endif
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+       "pgpgin",
+       "pgpgout",
+       "pswpin",
+       "pswpout",
+
+       "pgalloc_dma",
+       "pgalloc_dma32",
+       "pgalloc_normal",
+       "pgalloc_high",
+
+       "pgfree",
+       "pgactivate",
+       "pgdeactivate",
+
+       "pgfault",
+       "pgmajfault",
+
+       "pgrefill_dma",
+       "pgrefill_dma32",
+       "pgrefill_normal",
+       "pgrefill_high",
+
+       "pgsteal_dma",
+       "pgsteal_dma32",
+       "pgsteal_normal",
+       "pgsteal_high",
+
+       "pgscan_kswapd_dma",
+       "pgscan_kswapd_dma32",
+       "pgscan_kswapd_normal",
+       "pgscan_kswapd_high",
+
+       "pgscan_direct_dma",
+       "pgscan_direct_dma32",
+       "pgscan_direct_normal",
+       "pgscan_direct_high",
+
+       "pginodesteal",
+       "slabs_scanned",
+       "kswapd_steal",
+       "kswapd_inodesteal",
+       "pageoutrun",
+       "allocstall",
+
+       "pgrotated",
+#endif
+};
+
+/*
+ * Output information about zones in @pgdat.
+ */
+static int zoneinfo_show(struct seq_file *m, void *arg)
+{
+       pg_data_t *pgdat = arg;
+       struct zone *zone;
+       struct zone *node_zones = pgdat->node_zones;
+       unsigned long flags;
+
+       for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
+               int i;
+
+               if (!populated_zone(zone))
+                       continue;
+
+               spin_lock_irqsave(&zone->lock, flags);
+               seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
+               seq_printf(m,
+                          "\n  pages free     %lu"
+                          "\n        min      %lu"
+                          "\n        low      %lu"
+                          "\n        high     %lu"
+                          "\n        active   %lu"
+                          "\n        inactive %lu"
+                          "\n        scanned  %lu (a: %lu i: %lu)"
+                          "\n        spanned  %lu"
+                          "\n        present  %lu",
+                          zone->free_pages,
+                          zone->pages_min,
+                          zone->pages_low,
+                          zone->pages_high,
+                          zone->nr_active,
+                          zone->nr_inactive,
+                          zone->pages_scanned,
+                          zone->nr_scan_active, zone->nr_scan_inactive,
+                          zone->spanned_pages,
+                          zone->present_pages);
+
+               for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+                       seq_printf(m, "\n    %-12s %lu", vmstat_text[i],
+                                       zone_page_state(zone, i));
+
+               seq_printf(m,
+                          "\n        protection: (%lu",
+                          zone->lowmem_reserve[0]);
+               for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
+                       seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
+               seq_printf(m,
+                          ")"
+                          "\n  pagesets");
+               for_each_online_cpu(i) {
+                       struct per_cpu_pageset *pageset;
+                       int j;
+
+                       pageset = zone_pcp(zone, i);
+                       for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+                               if (pageset->pcp[j].count)
+                                       break;
+                       }
+                       if (j == ARRAY_SIZE(pageset->pcp))
+                               continue;
+                       for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+                               seq_printf(m,
+                                          "\n    cpu: %i pcp: %i"
+                                          "\n              count: %i"
+                                          "\n              high:  %i"
+                                          "\n              batch: %i",
+                                          i, j,
+                                          pageset->pcp[j].count,
+                                          pageset->pcp[j].high,
+                                          pageset->pcp[j].batch);
+                       }
+#ifdef CONFIG_SMP
+                       seq_printf(m, "\n  vm stats threshold: %d",
+                                       pageset->stat_threshold);
+#endif
+               }
+               seq_printf(m,
+                          "\n  all_unreclaimable: %u"
+                          "\n  prev_priority:     %i"
+                          "\n  start_pfn:         %lu",
+                          zone->all_unreclaimable,
+                          zone->prev_priority,
+                          zone->zone_start_pfn);
+               spin_unlock_irqrestore(&zone->lock, flags);
+               seq_putc(m, '\n');
+       }
+       return 0;
+}
+
+struct seq_operations zoneinfo_op = {
+       .start  = frag_start, /* iterate over all zones. The same as in
+                              * fragmentation. */
+       .next   = frag_next,
+       .stop   = frag_stop,
+       .show   = zoneinfo_show,
+};
+
+static void *vmstat_start(struct seq_file *m, loff_t *pos)
+{
+       unsigned long *v;
+#ifdef CONFIG_VM_EVENT_COUNTERS
+       unsigned long *e;
+#endif
+       int i;
+
+       if (*pos >= ARRAY_SIZE(vmstat_text))
+               return NULL;
+
+#ifdef CONFIG_VM_EVENT_COUNTERS
+       v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long)
+                       + sizeof(struct vm_event_state), GFP_KERNEL);
+#else
+       v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long),
+                       GFP_KERNEL);
+#endif
+       m->private = v;
+       if (!v)
+               return ERR_PTR(-ENOMEM);
+       for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+               v[i] = global_page_state(i);
+#ifdef CONFIG_VM_EVENT_COUNTERS
+       e = v + NR_VM_ZONE_STAT_ITEMS;
+       all_vm_events(e);
+       e[PGPGIN] /= 2;         /* sectors -> kbytes */
+       e[PGPGOUT] /= 2;
+#endif
+       return v + *pos;
+}
+
+static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos)
+{
+       (*pos)++;
+       if (*pos >= ARRAY_SIZE(vmstat_text))
+               return NULL;
+       return (unsigned long *)m->private + *pos;
+}
+
+static int vmstat_show(struct seq_file *m, void *arg)
+{
+       unsigned long *l = arg;
+       unsigned long off = l - (unsigned long *)m->private;
+
+       seq_printf(m, "%s %lu\n", vmstat_text[off], *l);
+       return 0;
+}
+
+static void vmstat_stop(struct seq_file *m, void *arg)
+{
+       kfree(m->private);
+       m->private = NULL;
+}
+
+struct seq_operations vmstat_op = {
+       .start  = vmstat_start,
+       .next   = vmstat_next,
+       .stop   = vmstat_stop,
+       .show   = vmstat_show,
+};
+
+#endif /* CONFIG_PROC_FS */
+
+#ifdef CONFIG_SMP
+/*
+ * Use the cpu notifier to insure that the thresholds are recalculated
+ * when necessary.
+ */
+static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
+               unsigned long action,
+               void *hcpu)
+{
+       switch (action) {
+               case CPU_UP_PREPARE:
+               case CPU_UP_CANCELED:
+               case CPU_DEAD:
+                       refresh_zone_stat_thresholds();
+                       break;
+               default:
+                       break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata vmstat_notifier =
+       { &vmstat_cpuup_callback, NULL, 0 };
+
+int __init setup_vmstat(void)
+{
+       refresh_zone_stat_thresholds();
+       register_cpu_notifier(&vmstat_notifier);
+       return 0;
+}
+module_init(setup_vmstat)
+#endif
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
new file mode 100644 (file)
index 0000000..c0a4ae2
--- /dev/null
@@ -0,0 +1,175 @@
+/* ATM driver model support. */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/atmdev.h>
+#include "common.h"
+#include "resources.h"
+
+#define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev)
+
+static ssize_t show_type(struct class_device *cdev, char *buf)
+{
+       struct atm_dev *adev = to_atm_dev(cdev);
+       return sprintf(buf, "%s\n", adev->type);
+}
+
+static ssize_t show_address(struct class_device *cdev, char *buf)
+{
+       char *pos = buf;
+       struct atm_dev *adev = to_atm_dev(cdev);
+       int i;
+
+       for (i = 0; i < (ESI_LEN - 1); i++)
+               pos += sprintf(pos, "%02x:", adev->esi[i]);
+       pos += sprintf(pos, "%02x\n", adev->esi[i]);
+
+       return pos - buf;
+}
+
+static ssize_t show_atmaddress(struct class_device *cdev, char *buf)
+{
+        unsigned long flags;
+       char *pos = buf;
+       struct atm_dev *adev = to_atm_dev(cdev);
+        struct atm_dev_addr *aaddr;
+       int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin;
+       int i, j;
+
+        spin_lock_irqsave(&adev->lock, flags);
+        list_for_each_entry(aaddr, &adev->local, entry) {
+               for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) {
+                       if (j == *fmt) {
+                               pos += sprintf(pos, ".");
+                               ++fmt;
+                               j = 0;
+                       }
+                       pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]);
+               }
+               pos += sprintf(pos, "\n");
+       }
+        spin_unlock_irqrestore(&adev->lock, flags);
+
+       return pos - buf;
+}
+
+static ssize_t show_carrier(struct class_device *cdev, char *buf)
+{
+       char *pos = buf;
+       struct atm_dev *adev = to_atm_dev(cdev);
+
+       pos += sprintf(pos, "%d\n",
+                      adev->signal == ATM_PHY_SIG_LOST ? 0 : 1);
+               
+       return pos - buf;
+}
+
+static ssize_t show_link_rate(struct class_device *cdev, char *buf)
+{
+       char *pos = buf;
+       struct atm_dev *adev = to_atm_dev(cdev);
+       int link_rate;
+
+       /* show the link rate, not the data rate */
+       switch (adev->link_rate) {
+               case ATM_OC3_PCR:
+                       link_rate = 155520000;
+                       break;
+               case ATM_OC12_PCR:
+                       link_rate = 622080000;
+                       break;
+               case ATM_25_PCR:
+                       link_rate = 25600000;
+                       break;
+               default:
+                       link_rate = adev->link_rate * 8 * 53;
+       }
+       pos += sprintf(pos, "%d\n", link_rate);
+               
+       return pos - buf;
+}
+
+static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static CLASS_DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL);
+static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
+static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
+static CLASS_DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL);
+
+static struct class_device_attribute *atm_attrs[] = {
+       &class_device_attr_atmaddress,
+       &class_device_attr_address,
+       &class_device_attr_carrier,
+       &class_device_attr_type,
+       &class_device_attr_link_rate,
+       NULL
+};
+
+static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
+{
+       struct atm_dev *adev;
+       int i = 0, len = 0;
+
+       if (!cdev)
+               return -ENODEV;
+
+       adev = to_atm_dev(cdev);
+       if (!adev)
+               return -ENODEV;
+
+       if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
+                          "NAME=%s%d", adev->type, adev->number))
+               return -ENOMEM;
+
+       envp[i] = NULL;
+       return 0;
+}
+
+static void atm_release(struct class_device *cdev)
+{
+       struct atm_dev *adev = to_atm_dev(cdev);
+
+       kfree(adev);
+}
+
+static struct class atm_class = {
+       .name           = "atm",
+       .release        = atm_release,
+       .uevent         = atm_uevent,
+};
+
+int atm_register_sysfs(struct atm_dev *adev)
+{
+       struct class_device *cdev = &adev->class_dev;
+       int i, err;
+
+       cdev->class = &atm_class;
+       class_set_devdata(cdev, adev);
+
+       snprintf(cdev->class_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number);
+       err = class_device_register(cdev);
+       if (err < 0)
+               return err;
+
+       for (i = 0; atm_attrs[i]; i++)
+               class_device_create_file(cdev, atm_attrs[i]);
+
+       return 0;
+}
+
+void atm_unregister_sysfs(struct atm_dev *adev)
+{
+       struct class_device *cdev = &adev->class_dev;
+
+       class_device_del(cdev);
+}
+
+int __init atm_sysfs_init(void)
+{
+       return class_register(&atm_class);
+}
+
+void __exit atm_sysfs_exit(void)
+{
+       class_unregister(&atm_class);
+}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
new file mode 100644 (file)
index 0000000..53086fb
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ *     Bridge netlink control interface
+ *
+ *     Authors:
+ *     Stephen Hemminger               <shemminger@osdl.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/rtnetlink.h>
+#include "br_private.h"
+
+/*
+ * Create one netlink message for one interface
+ * Contains port and master info as well as carrier and bridge state.
+ */
+static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
+                         u32 pid, u32 seq, int event, unsigned int flags)
+{
+       const struct net_bridge *br = port->br;
+       const struct net_device *dev = port->dev;
+       struct ifinfomsg *r;
+       struct nlmsghdr *nlh;
+       unsigned char *b = skb->tail;
+       u32 mtu = dev->mtu;
+       u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+       u8 portstate = port->state;
+
+       pr_debug("br_fill_info event %d port %s master %s\n",
+                event, dev->name, br->dev->name);
+
+       nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
+       r = NLMSG_DATA(nlh);
+       r->ifi_family = AF_BRIDGE;
+       r->__ifi_pad = 0;
+       r->ifi_type = dev->type;
+       r->ifi_index = dev->ifindex;
+       r->ifi_flags = dev_get_flags(dev);
+       r->ifi_change = 0;
+
+       RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+
+       RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
+
+       if (dev->addr_len)
+               RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+
+       RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
+       if (dev->ifindex != dev->iflink)
+               RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+
+
+       RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
+
+       if (event == RTM_NEWLINK)
+               RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
+
+       nlh->nlmsg_len = skb->tail - b;
+
+       return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+
+       skb_trim(skb, b - skb->data);
+       return -EINVAL;
+}
+
+/*
+ * Notify listeners of a change in port information
+ */
+void br_ifinfo_notify(int event, struct net_bridge_port *port)
+{
+       struct sk_buff *skb;
+       int err = -ENOMEM;
+
+       pr_debug("bridge notify event=%d\n", event);
+       skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
+                       GFP_ATOMIC);
+       if (!skb)
+               goto err_out;
+
+       err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
+       if (err < 0)
+               goto err_kfree;
+
+       NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
+       netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
+       return;
+
+err_kfree:
+       kfree_skb(skb);
+err_out:
+       netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
+}
+
+/*
+ * Dump information about all ports, in response to GETLINK
+ */
+static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net_device *dev;
+       int idx;
+       int s_idx = cb->args[0];
+       int err = 0;
+
+       read_lock(&dev_base_lock);
+       for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+               struct net_bridge_port *p = dev->br_port;
+
+               /* not a bridge port */
+               if (!p)
+                       continue;
+
+               if (idx < s_idx)
+                       goto cont;
+
+               err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
+                                    cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
+               if (err <= 0)
+                       break;
+cont:
+               ++idx;
+       }
+       read_unlock(&dev_base_lock);
+
+       cb->args[0] = idx;
+
+       return skb->len;
+}
+
+/*
+ * Change state of port (ie from forwarding to blocking etc)
+ * Used by spanning tree in user space.
+ */
+static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+{
+       struct rtattr  **rta = arg;
+       struct ifinfomsg *ifm = NLMSG_DATA(nlh);
+       struct net_device *dev;
+       struct net_bridge_port *p;
+       u8 new_state;
+
+       if (ifm->ifi_family != AF_BRIDGE)
+               return -EPFNOSUPPORT;
+
+       /* Must pass valid state as PROTINFO */
+       if (rta[IFLA_PROTINFO-1]) {
+               u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
+               new_state = *pstate;
+       } else
+               return -EINVAL;
+
+       if (new_state > BR_STATE_BLOCKING)
+               return -EINVAL;
+
+       /* Find bridge port */
+       dev = __dev_get_by_index(ifm->ifi_index);
+       if (!dev)
+               return -ENODEV;
+
+       p = dev->br_port;
+       if (!p)
+               return -EINVAL;
+
+       /* if kernel STP is running, don't allow changes */
+       if (p->br->stp_enabled)
+               return -EBUSY;
+
+       if (!netif_running(dev))
+               return -ENETDOWN;
+
+       if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
+               return -ENETDOWN;
+
+       p->state = new_state;
+       br_log_state(p);
+       return 0;
+}
+
+
+static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = {
+       [RTM_GETLINK - RTM_BASE] = { .dumpit    = br_dump_ifinfo, },
+       [RTM_SETLINK - RTM_BASE] = { .doit      = br_rtm_setlink, },
+};
+
+void __init br_netlink_init(void)
+{
+       rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table;
+}
+
+void __exit br_netlink_fini(void)
+{
+       rtnetlink_links[PF_BRIDGE] = NULL;
+}
+
diff --git a/net/core/netevent.c b/net/core/netevent.c
new file mode 100644 (file)
index 0000000..35d02c3
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *     Network event notifiers
+ *
+ *     Authors:
+ *      Tom Tucker             <tom@opengridcomputing.com>
+ *      Steve Wise             <swise@opengridcomputing.com>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *     Fixes:
+ */
+
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+
+static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);
+
+/**
+ *     register_netevent_notifier - register a netevent notifier block
+ *     @nb: notifier
+ *
+ *     Register a notifier to be called when a netevent occurs.
+ *     The notifier passed is linked into the kernel structures and must
+ *     not be reused until it has been unregistered. A negative errno code
+ *     is returned on a failure.
+ */
+int register_netevent_notifier(struct notifier_block *nb)
+{
+       int err;
+
+       err = atomic_notifier_chain_register(&netevent_notif_chain, nb);
+       return err;
+}
+
+/**
+ *     netevent_unregister_notifier - unregister a netevent notifier block
+ *     @nb: notifier
+ *
+ *     Unregister a notifier previously registered by
+ *     register_neigh_notifier(). The notifier is unlinked into the
+ *     kernel structures and may then be reused. A negative errno code
+ *     is returned on a failure.
+ */
+
+int unregister_netevent_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&netevent_notif_chain, nb);
+}
+
+/**
+ *     call_netevent_notifiers - call all netevent notifier blocks
+ *      @val: value passed unmodified to notifier function
+ *      @v:   pointer passed unmodified to notifier function
+ *
+ *     Call all neighbour notifier blocks.  Parameters and return value
+ *     are as for notifier_call_chain().
+ */
+
+int call_netevent_notifiers(unsigned long val, void *v)
+{
+       return atomic_notifier_call_chain(&netevent_notif_chain, val, v);
+}
+
+EXPORT_SYMBOL_GPL(register_netevent_notifier);
+EXPORT_SYMBOL_GPL(unregister_netevent_notifier);
+EXPORT_SYMBOL_GPL(call_netevent_notifiers);
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
new file mode 100644 (file)
index 0000000..248a6b6
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Portions based on net/core/datagram.c and copyrighted by their authors.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This code allows the net stack to make use of a DMA engine for
+ * skb to iovec copies.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h> /* for BUG_TRAP */
+#include <net/tcp.h>
+#include <net/netdma.h>
+
+#define NET_DMA_DEFAULT_COPYBREAK 4096
+
+int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK;
+
+/**
+ *     dma_skb_copy_datagram_iovec - Copy a datagram to an iovec.
+ *     @skb - buffer to copy
+ *     @offset - offset in the buffer to start copying from
+ *     @iovec - io vector to copy to
+ *     @len - amount of data to copy from buffer to iovec
+ *     @pinned_list - locked iovec buffer data
+ *
+ *     Note: the iovec is modified during the copy.
+ */
+int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
+                       struct sk_buff *skb, int offset, struct iovec *to,
+                       size_t len, struct dma_pinned_list *pinned_list)
+{
+       int start = skb_headlen(skb);
+       int i, copy = start - offset;
+       dma_cookie_t cookie = 0;
+
+       /* Copy header. */
+       if (copy > 0) {
+               if (copy > len)
+                       copy = len;
+               cookie = dma_memcpy_to_iovec(chan, to, pinned_list,
+                                           skb->data + offset, copy);
+               if (cookie < 0)
+                       goto fault;
+               len -= copy;
+               if (len == 0)
+                       goto end;
+               offset += copy;
+       }
+
+       /* Copy paged appendix. Hmm... why does this look so complicated? */
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               int end;
+
+               BUG_TRAP(start <= offset + len);
+
+               end = start + skb_shinfo(skb)->frags[i].size;
+               copy = end - offset;
+               if ((copy = end - offset) > 0) {
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+                       struct page *page = frag->page;
+
+                       if (copy > len)
+                               copy = len;
+
+                       cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page,
+                                       frag->page_offset + offset - start, copy);
+                       if (cookie < 0)
+                               goto fault;
+                       len -= copy;
+                       if (len == 0)
+                               goto end;
+                       offset += copy;
+               }
+               start = end;
+       }
+
+       if (skb_shinfo(skb)->frag_list) {
+               struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+               for (; list; list = list->next) {
+                       int end;
+
+                       BUG_TRAP(start <= offset + len);
+
+                       end = start + list->len;
+                       copy = end - offset;
+                       if (copy > 0) {
+                               if (copy > len)
+                                       copy = len;
+                               cookie = dma_skb_copy_datagram_iovec(chan, list,
+                                               offset - start, to, copy,
+                                               pinned_list);
+                               if (cookie < 0)
+                                       goto fault;
+                               len -= copy;
+                               if (len == 0)
+                                       goto end;
+                               offset += copy;
+                       }
+                       start = end;
+               }
+       }
+
+end:
+       if (!len) {
+               skb->dma_cookie = cookie;
+               return cookie;
+       }
+
+fault:
+       return -EFAULT;
+}
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
new file mode 100644 (file)
index 0000000..2893e9c
--- /dev/null
@@ -0,0 +1,470 @@
+/* SIP extension for IP connection tracking.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_conntrack_ftp.c and other 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP connection tracking helper");
+
+#define MAX_PORTS      8
+static unsigned short ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, ushort, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers of sip servers");
+
+static unsigned int sip_timeout = SIP_TIMEOUT;
+module_param(sip_timeout, uint, 0600);
+MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
+
+unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+                               enum ip_conntrack_info ctinfo,
+                               struct ip_conntrack *ct,
+                               const char **dptr);
+EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
+
+unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
+                               enum ip_conntrack_info ctinfo,
+                               struct ip_conntrack_expect *exp,
+                               const char *dptr);
+EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
+
+int ct_sip_get_info(const char *dptr, size_t dlen,
+                               unsigned int *matchoff,
+                               unsigned int *matchlen,
+                               struct sip_header_nfo *hnfo);
+EXPORT_SYMBOL_GPL(ct_sip_get_info);
+
+
+static int digits_len(const char *dptr, const char *limit, int *shift);
+static int epaddr_len(const char *dptr, const char *limit, int *shift);
+static int skp_digits_len(const char *dptr, const char *limit, int *shift);
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
+
+struct sip_header_nfo ct_sip_hdrs[] = {
+       {       /* Via header */
+               .lname          = "Via:",
+               .lnlen          = sizeof("Via:") - 1,
+               .sname          = "\r\nv:",
+               .snlen          = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
+               .ln_str         = "UDP ",
+               .ln_strlen      = sizeof("UDP ") - 1,
+               .match_len      = epaddr_len,
+       },
+       {       /* Contact header */
+               .lname          = "Contact:",
+               .lnlen          = sizeof("Contact:") - 1,
+               .sname          = "\r\nm:",
+               .snlen          = sizeof("\r\nm:") - 1,
+               .ln_str         = "sip:",
+               .ln_strlen      = sizeof("sip:") - 1,
+               .match_len      = skp_epaddr_len
+       },
+       {       /* Content length header */
+               .lname          = "Content-Length:",
+               .lnlen          = sizeof("Content-Length:") - 1,
+               .sname          = "\r\nl:",
+               .snlen          = sizeof("\r\nl:") - 1,
+               .ln_str         = ":",
+               .ln_strlen      = sizeof(":") - 1,
+               .match_len      = skp_digits_len
+       },
+       {       /* SDP media info */
+               .lname          = "\nm=",
+               .lnlen          = sizeof("\nm=") - 1,
+               .sname          = "\rm=",
+               .snlen          = sizeof("\rm=") - 1,
+               .ln_str         = "audio ",
+               .ln_strlen      = sizeof("audio ") - 1,
+               .match_len      = digits_len
+       },
+       {       /* SDP owner address*/
+               .lname          = "\no=",
+               .lnlen          = sizeof("\no=") - 1,
+               .sname          = "\ro=",
+               .snlen          = sizeof("\ro=") - 1,
+               .ln_str         = "IN IP4 ",
+               .ln_strlen      = sizeof("IN IP4 ") - 1,
+               .match_len      = epaddr_len
+       },
+       {       /* SDP connection info */
+               .lname          = "\nc=",
+               .lnlen          = sizeof("\nc=") - 1,
+               .sname          = "\rc=",
+               .snlen          = sizeof("\rc=") - 1,
+               .ln_str         = "IN IP4 ",
+               .ln_strlen      = sizeof("IN IP4 ") - 1,
+               .match_len      = epaddr_len
+       },
+       {       /* Requests headers */
+               .lname          = "sip:",
+               .lnlen          = sizeof("sip:") - 1,
+               .sname          = "sip:",
+               .snlen          = sizeof("sip:") - 1, /* yes, i know.. ;) */
+               .ln_str         = "@",
+               .ln_strlen      = sizeof("@") - 1,
+               .match_len      = epaddr_len
+       },
+       {       /* SDP version header */
+               .lname          = "\nv=",
+               .lnlen          = sizeof("\nv=") - 1,
+               .sname          = "\rv=",
+               .snlen          = sizeof("\rv=") - 1,
+               .ln_str         = "=",
+               .ln_strlen      = sizeof("=") - 1,
+               .match_len      = digits_len
+       }
+};
+EXPORT_SYMBOL_GPL(ct_sip_hdrs);
+
+/* get line lenght until first CR or LF seen. */
+int ct_sip_lnlen(const char *line, const char *limit)
+{
+       const char *k = line;
+
+       while ((line <= limit) && (*line == '\r' || *line == '\n'))
+               line++;
+
+       while (line <= limit) {
+               if (*line == '\r' || *line == '\n')
+                       break;
+               line++;
+       }
+       return line - k;
+}
+EXPORT_SYMBOL_GPL(ct_sip_lnlen);
+
+/* Linear string search, case sensitive. */
+const char *ct_sip_search(const char *needle, const char *haystack,
+                          size_t needle_len, size_t haystack_len)
+{
+       const char *limit = haystack + (haystack_len - needle_len);
+
+       while (haystack <= limit) {
+               if (memcmp(haystack, needle, needle_len) == 0)
+                       return haystack;
+               haystack++;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(ct_sip_search);
+
+static int digits_len(const char *dptr, const char *limit, int *shift)
+{
+       int len = 0;
+       while (dptr <= limit && isdigit(*dptr)) {
+               dptr++;
+               len++;
+       }
+       return len;
+}
+
+/* get digits lenght, skiping blank spaces. */
+static int skp_digits_len(const char *dptr, const char *limit, int *shift)
+{
+       for (; dptr <= limit && *dptr == ' '; dptr++)
+               (*shift)++;
+
+       return digits_len(dptr, limit, shift);
+}
+
+/* Simple ipaddr parser.. */
+static int parse_ipaddr(const char *cp,        const char **endp,
+                       u_int32_t *ipaddr, const char *limit)
+{
+       unsigned long int val;
+       int i, digit = 0;
+
+       for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
+               digit = 0;
+               if (!isdigit(*cp))
+                       break;
+
+               val = simple_strtoul(cp, (char **)&cp, 10);
+               if (val > 0xFF)
+                       return -1;
+
+               ((u_int8_t *)ipaddr)[i] = val;
+               digit = 1;
+
+               if (*cp != '.')
+                       break;
+               cp++;
+       }
+       if (!digit)
+               return -1;
+
+       if (endp)
+               *endp = cp;
+
+       return 0;
+}
+
+/* skip ip address. returns it lenght. */
+static int epaddr_len(const char *dptr, const char *limit, int *shift)
+{
+       const char *aux = dptr;
+       u_int32_t ip;
+
+       if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
+               DEBUGP("ip: %s parse failed.!\n", dptr);
+               return 0;
+       }
+
+       /* Port number */
+       if (*dptr == ':') {
+               dptr++;
+               dptr += digits_len(dptr, limit, shift);
+       }
+       return dptr - aux;
+}
+
+/* get address length, skiping user info. */
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
+{
+       int s = *shift;
+
+       for (; dptr <= limit && *dptr != '@'; dptr++)
+               (*shift)++;
+
+       if (*dptr == '@') {
+               dptr++;
+               (*shift)++;
+       } else
+               *shift = s;
+
+       return epaddr_len(dptr, limit, shift);
+}
+
+/* Returns 0 if not found, -1 error parsing. */
+int ct_sip_get_info(const char *dptr, size_t dlen,
+                   unsigned int *matchoff,
+                   unsigned int *matchlen,
+                   struct sip_header_nfo *hnfo)
+{
+       const char *limit, *aux, *k = dptr;
+       int shift = 0;
+
+       limit = dptr + (dlen - hnfo->lnlen);
+
+       while (dptr <= limit) {
+               if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
+                   (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+                       dptr++;
+                       continue;
+               }
+               aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
+                                   ct_sip_lnlen(dptr, limit));
+               if (!aux) {
+                       DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
+                              hnfo->lname);
+                       return -1;
+               }
+               aux += hnfo->ln_strlen;
+
+               *matchlen = hnfo->match_len(aux, limit, &shift);
+               if (!*matchlen)
+                       return -1;
+
+               *matchoff = (aux - k) + shift;
+
+               DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
+                      *matchlen);
+               return 1;
+       }
+       DEBUGP("%s header not found.\n", hnfo->lname);
+       return 0;
+}
+
+static int set_expected_rtp(struct sk_buff **pskb,
+                           struct ip_conntrack *ct,
+                           enum ip_conntrack_info ctinfo,
+                           u_int32_t ipaddr, u_int16_t port,
+                           const char *dptr)
+{
+       struct ip_conntrack_expect *exp;
+       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+       int ret;
+
+       exp = ip_conntrack_expect_alloc(ct);
+       if (exp == NULL)
+               return NF_DROP;
+
+       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+       exp->tuple.src.u.udp.port = 0;
+       exp->tuple.dst.ip = ipaddr;
+       exp->tuple.dst.u.udp.port = htons(port);
+       exp->tuple.dst.protonum = IPPROTO_UDP;
+
+       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.u.udp.port = 0;
+       exp->mask.dst.ip = 0xFFFFFFFF;
+       exp->mask.dst.u.udp.port = 0xFFFF;
+       exp->mask.dst.protonum = 0xFF;
+
+       exp->expectfn = NULL;
+       exp->flags = 0;
+
+       if (ip_nat_sdp_hook)
+               ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
+       else {
+               if (ip_conntrack_expect_related(exp) != 0)
+                       ret = NF_DROP;
+               else
+                       ret = NF_ACCEPT;
+       }
+       ip_conntrack_expect_put(exp);
+
+       return ret;
+}
+
+static int sip_help(struct sk_buff **pskb,
+                   struct ip_conntrack *ct,
+                   enum ip_conntrack_info ctinfo)
+{
+       unsigned int dataoff, datalen;
+       const char *dptr;
+       int ret = NF_ACCEPT;
+       int matchoff, matchlen;
+       u_int32_t ipaddr;
+       u_int16_t port;
+
+       /* No Data ? */
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+       if (dataoff >= (*pskb)->len) {
+               DEBUGP("skb->len = %u\n", (*pskb)->len);
+               return NF_ACCEPT;
+        }
+
+       ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
+
+       if (!skb_is_nonlinear(*pskb))
+               dptr = (*pskb)->data + dataoff;
+       else {
+               DEBUGP("Copy of skbuff not supported yet.\n");
+               goto out;
+       }
+
+       if (ip_nat_sip_hook) {
+               if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
+                       ret = NF_DROP;
+                       goto out;
+               }
+       }
+
+       /* After this point NAT, could have mangled skb, so
+          we need to recalculate payload lenght. */
+       datalen = (*pskb)->len - dataoff;
+
+       if (datalen < (sizeof("SIP/2.0 200") - 1))
+               goto out;
+
+       /* RTP info only in some SDP pkts */
+       if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+           memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+               goto out;
+       }
+       /* Get ip and port address from SDP packet. */
+       if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
+                           &ct_sip_hdrs[POS_CONNECTION]) > 0) {
+
+               /* We'll drop only if there are parse problems. */
+               if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
+                                dptr + datalen) < 0) {
+                       ret = NF_DROP;
+                       goto out;
+               }
+               if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
+                                   &ct_sip_hdrs[POS_MEDIA]) > 0) {
+
+                       port = simple_strtoul(dptr + matchoff, NULL, 10);
+                       if (port < 1024) {
+                               ret = NF_DROP;
+                               goto out;
+                       }
+                       ret = set_expected_rtp(pskb, ct, ctinfo,
+                                              ipaddr, port, dptr);
+               }
+       }
+out:
+       return ret;
+}
+
+static struct ip_conntrack_helper sip[MAX_PORTS];
+static char sip_names[MAX_PORTS][10];
+
+static void fini(void)
+{
+       int i;
+       for (i = 0; i < ports_c; i++) {
+               DEBUGP("unregistering helper for port %d\n", ports[i]);
+               ip_conntrack_helper_unregister(&sip[i]);
+       }
+}
+
+static int __init init(void)
+{
+       int i, ret;
+       char *tmpname;
+
+       if (ports_c == 0)
+               ports[ports_c++] = SIP_PORT;
+
+       for (i = 0; i < ports_c; i++) {
+               /* Create helper structure */
+               memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
+
+               sip[i].tuple.dst.protonum = IPPROTO_UDP;
+               sip[i].tuple.src.u.udp.port = htons(ports[i]);
+               sip[i].mask.src.u.udp.port = 0xFFFF;
+               sip[i].mask.dst.protonum = 0xFF;
+               sip[i].max_expected = 2;
+               sip[i].timeout = 3 * 60; /* 3 minutes */
+               sip[i].me = THIS_MODULE;
+               sip[i].help = sip_help;
+
+               tmpname = &sip_names[i][0];
+               if (ports[i] == SIP_PORT)
+                       sprintf(tmpname, "sip");
+               else
+                       sprintf(tmpname, "sip-%d", i);
+               sip[i].name = tmpname;
+
+               DEBUGP("port #%d: %d\n", i, ports[i]);
+
+               ret = ip_conntrack_helper_register(&sip[i]);
+               if (ret) {
+                       printk("ERROR registering helper for port %d\n",
+                               ports[i]);
+                       fini();
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
new file mode 100644 (file)
index 0000000..6ffba63
--- /dev/null
@@ -0,0 +1,249 @@
+/* SIP extension for UDP NAT alteration.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_nat_ftp.c and other 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP NAT helper");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+extern struct sip_header_nfo ct_sip_hdrs[];
+
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+                                     enum ip_conntrack_info ctinfo,
+                                     struct ip_conntrack *ct,
+                                     const char **dptr, size_t dlen,
+                                     char *buffer, int bufflen,
+                                     struct sip_header_nfo *hnfo)
+{
+       unsigned int matchlen, matchoff;
+
+       if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
+               return 0;
+
+       if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+                                     matchoff, matchlen, buffer, bufflen))
+               return 0;
+
+       /* We need to reload this. Thanks Patrick. */
+       *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+       return 1;
+}
+
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct ip_conntrack *ct,
+                              const char **dptr)
+{
+       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+       char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+       unsigned int bufflen, dataoff;
+       u_int32_t ip;
+       u_int16_t port;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+       ip   = ct->tuplehash[!dir].tuple.dst.ip;
+       port = ct->tuplehash[!dir].tuple.dst.u.udp.port;
+       bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
+
+       /* short packet ? */
+       if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
+               return 0;
+
+       /* Basic rules: requests and responses. */
+       if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
+               const char *aux;
+
+               if ((ctinfo) < IP_CT_IS_REPLY) {
+                       mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                         (*pskb)->len - dataoff,
+                                         buffer, bufflen,
+                                         &ct_sip_hdrs[POS_CONTACT]);
+                       return 1;
+               }
+
+               if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                      (*pskb)->len - dataoff,
+                                      buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+                       return 0;
+
+               /* This search should ignore case, but later.. */
+               aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
+                                   (*pskb)->len - dataoff);
+               if (!aux)
+                       return 0;
+
+               if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
+                   ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
+                       return 1;
+
+               return mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                        (*pskb)->len - dataoff,
+                                        buffer, bufflen,
+                                        &ct_sip_hdrs[POS_CONTACT]);
+       }
+       if ((ctinfo) < IP_CT_IS_REPLY) {
+               if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                      (*pskb)->len - dataoff,
+                                      buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+                       return 0;
+
+               /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
+               mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
+                                 buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
+               return 1;
+       }
+       /* This mangle requests headers. */
+       return mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                ct_sip_lnlen(*dptr,
+                                             *dptr + (*pskb)->len - dataoff),
+                                buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
+}
+
+static int mangle_content_len(struct sk_buff **pskb,
+                             enum ip_conntrack_info ctinfo,
+                             struct ip_conntrack *ct,
+                             const char *dptr)
+{
+       unsigned int dataoff, matchoff, matchlen;
+       char buffer[sizeof("65536")];
+       int bufflen;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+       /* Get actual SDP lenght */
+       if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
+                           &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
+
+               /* since ct_sip_get_info() give us a pointer passing 'v='
+                  we need to add 2 bytes in this count. */
+               int c_len = (*pskb)->len - dataoff - matchoff + 2;
+
+               /* Now, update SDP lenght */
+               if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
+                                   &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
+
+                       bufflen = sprintf(buffer, "%u", c_len);
+
+                       return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+                                                       matchoff, matchlen,
+                                                       buffer, bufflen);
+               }
+       }
+       return 0;
+}
+
+static unsigned int mangle_sdp(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct ip_conntrack *ct,
+                              u_int32_t newip, u_int16_t port,
+                              const char *dptr)
+{
+       char buffer[sizeof("nnn.nnn.nnn.nnn")];
+       unsigned int dataoff, bufflen;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+       /* Mangle owner and contact info. */
+       bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
+       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+                              buffer, bufflen, &ct_sip_hdrs[POS_OWNER]))
+               return 0;
+
+       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+                              buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION]))
+               return 0;
+
+       /* Mangle media port. */
+       bufflen = sprintf(buffer, "%u", port);
+       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+                              buffer, bufflen, &ct_sip_hdrs[POS_MEDIA]))
+               return 0;
+
+       return mangle_content_len(pskb, ctinfo, ct, dptr);
+}
+
+/* So, this packet has hit the connection tracking matching code.
+   Mangle it, and change the expectation to match the new version. */
+static unsigned int ip_nat_sdp(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct ip_conntrack_expect *exp,
+                              const char *dptr)
+{
+       struct ip_conntrack *ct = exp->master;
+       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+       u_int32_t newip;
+       u_int16_t port;
+
+       DEBUGP("ip_nat_sdp():\n");
+
+       /* Connection will come from reply */
+       newip = ct->tuplehash[!dir].tuple.dst.ip;
+
+       exp->tuple.dst.ip = newip;
+       exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
+       exp->dir = !dir;
+
+       /* When you see the packet, we need to NAT it the same as the
+          this one. */
+       exp->expectfn = ip_nat_follow_master;
+
+       /* Try to get same port: if not, try to change it. */
+       for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
+               exp->tuple.dst.u.udp.port = htons(port);
+               if (ip_conntrack_expect_related(exp) == 0)
+                       break;
+       }
+
+       if (port == 0)
+               return NF_DROP;
+
+       if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
+               ip_conntrack_unexpect_related(exp);
+               return NF_DROP;
+       }
+       return NF_ACCEPT;
+}
+
+static void __exit fini(void)
+{
+       ip_nat_sip_hook = NULL;
+       ip_nat_sdp_hook = NULL;
+       /* Make sure noone calls it, meanwhile. */
+       synchronize_net();
+}
+
+static int __init init(void)
+{
+       BUG_ON(ip_nat_sip_hook);
+       BUG_ON(ip_nat_sdp_hook);
+       ip_nat_sip_hook = ip_nat_sip;
+       ip_nat_sdp_hook = ip_nat_sdp;
+       return 0;
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
new file mode 100644 (file)
index 0000000..649ebae
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * TCP Low Priority (TCP-LP)
+ *
+ * TCP Low Priority is a distributed algorithm whose goal is to utilize only
+ *   the excess network bandwidth as compared to the ``fair share`` of
+ *   bandwidth as targeted by TCP.
+ *
+ * As of 2.6.13, Linux supports pluggable congestion control algorithms.
+ * Due to the limitation of the API, we take the following changes from
+ * the original TCP-LP implementation:
+ *   o We use newReno in most core CA handling. Only add some checking
+ *     within cong_avoid.
+ *   o Error correcting in remote HZ, therefore remote HZ will be keeped
+ *     on checking and updating.
+ *   o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne
+ *     OWD have a similar meaning as RTT. Also correct the buggy formular.
+ *   o Handle reaction for Early Congestion Indication (ECI) within
+ *     pkts_acked, as mentioned within pseudo code.
+ *   o OWD is handled in relative format, where local time stamp will in
+ *     tcp_time_stamp format.
+ *
+ * Original Author:
+ *   Aleksandar Kuzmanovic <akuzma@northwestern.edu>
+ * Available from:
+ *   http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf
+ * Original implementation for 2.4.19:
+ *   http://www-ece.rice.edu/networks/TCP-LP/
+ *
+ * 2.6.x module Authors:
+ *   Wong Hoi Sing, Edison <hswong3i@gmail.com>
+ *   Hung Hing Lun, Mike <hlhung3i@gmail.com>
+ * SourceForge project page:
+ *   http://tcp-lp-mod.sourceforge.net/
+ *
+ * Version: $Id: tcp_lp.c,v 1.24 2006/09/05 20:22:53 hswong3i Exp $
+ */
+
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* resolution of owd */
+#define LP_RESOL       1000
+
+/**
+ * enum tcp_lp_state
+ * @LP_VALID_RHZ: is remote HZ valid?
+ * @LP_VALID_OWD: is OWD valid?
+ * @LP_WITHIN_THR: are we within threshold?
+ * @LP_WITHIN_INF: are we within inference?
+ *
+ * TCP-LP's state flags.
+ * We create this set of state flag mainly for debugging.
+ */
+enum tcp_lp_state {
+       LP_VALID_RHZ = (1 << 0),
+       LP_VALID_OWD = (1 << 1),
+       LP_WITHIN_THR = (1 << 3),
+       LP_WITHIN_INF = (1 << 4),
+};
+
+/**
+ * struct lp
+ * @flag: TCP-LP state flag
+ * @sowd: smoothed OWD << 3
+ * @owd_min: min OWD
+ * @owd_max: max OWD
+ * @owd_max_rsv: resrved max owd
+ * @remote_hz: estimated remote HZ
+ * @remote_ref_time: remote reference time
+ * @local_ref_time: local reference time
+ * @last_drop: time for last active drop
+ * @inference: current inference
+ *
+ * TCP-LP's private struct.
+ * We get the idea from original TCP-LP implementation where only left those we
+ * found are really useful.
+ */
+struct lp {
+       u32 flag;
+       u32 sowd;
+       u32 owd_min;
+       u32 owd_max;
+       u32 owd_max_rsv;
+       u32 remote_hz;
+       u32 remote_ref_time;
+       u32 local_ref_time;
+       u32 last_drop;
+       u32 inference;
+};
+
+/**
+ * tcp_lp_init
+ *
+ * Init all required variables.
+ * Clone the handling from Vegas module implementation.
+ */
+static void tcp_lp_init(struct sock *sk)
+{
+       struct lp *lp = inet_csk_ca(sk);
+
+       lp->flag = 0;
+       lp->sowd = 0;
+       lp->owd_min = 0xffffffff;
+       lp->owd_max = 0;
+       lp->owd_max_rsv = 0;
+       lp->remote_hz = 0;
+       lp->remote_ref_time = 0;
+       lp->local_ref_time = 0;
+       lp->last_drop = 0;
+       lp->inference = 0;
+}
+
+/**
+ * tcp_lp_cong_avoid
+ *
+ * Implementation of cong_avoid.
+ * Will only call newReno CA when away from inference.
+ * From TCP-LP's paper, this will be handled in additive increasement.
+ */
+static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
+                             int flag)
+{
+       struct lp *lp = inet_csk_ca(sk);
+
+       if (!(lp->flag & LP_WITHIN_INF))
+               tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag);
+}
+
+/**
+ * tcp_lp_remote_hz_estimator
+ *
+ * Estimate remote HZ.
+ * We keep on updating the estimated value, where original TCP-LP
+ * implementation only guest it for once and use forever.
+ */
+static u32 tcp_lp_remote_hz_estimator(struct sock *sk)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
+       s64 rhz = lp->remote_hz << 6;   /* remote HZ << 6 */
+       s64 m = 0;
+
+       /* not yet record reference time
+        * go away!! record it before come back!! */
+       if (lp->remote_ref_time == 0 || lp->local_ref_time == 0)
+               goto out;
+
+       /* we can't calc remote HZ with no different!! */
+       if (tp->rx_opt.rcv_tsval == lp->remote_ref_time
+           || tp->rx_opt.rcv_tsecr == lp->local_ref_time)
+               goto out;
+
+       m = HZ * (tp->rx_opt.rcv_tsval -
+                 lp->remote_ref_time) / (tp->rx_opt.rcv_tsecr -
+                                         lp->local_ref_time);
+       if (m < 0)
+               m = -m;
+
+       if (rhz > 0) {
+               m -= rhz >> 6;  /* m is now error in remote HZ est */
+               rhz += m;       /* 63/64 old + 1/64 new */
+       } else
+               rhz = m << 6;
+
+ out:
+       /* record time for successful remote HZ calc */
+       if (rhz > 0)
+               lp->flag |= LP_VALID_RHZ;
+       else
+               lp->flag &= ~LP_VALID_RHZ;
+
+       /* record reference time stamp */
+       lp->remote_ref_time = tp->rx_opt.rcv_tsval;
+       lp->local_ref_time = tp->rx_opt.rcv_tsecr;
+
+       return rhz >> 6;
+}
+
+/**
+ * tcp_lp_owd_calculator
+ *
+ * Calculate one way delay (in relative format).
+ * Original implement OWD as minus of remote time difference to local time
+ * difference directly. As this time difference just simply equal to RTT, when
+ * the network status is stable, remote RTT will equal to local RTT, and result
+ * OWD into zero.
+ * It seems to be a bug and so we fixed it.
+ */
+static u32 tcp_lp_owd_calculator(struct sock *sk)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
+       s64 owd = 0;
+
+       lp->remote_hz = tcp_lp_remote_hz_estimator(sk);
+
+       if (lp->flag & LP_VALID_RHZ) {
+               owd =
+                   tp->rx_opt.rcv_tsval * (LP_RESOL / lp->remote_hz) -
+                   tp->rx_opt.rcv_tsecr * (LP_RESOL / HZ);
+               if (owd < 0)
+                       owd = -owd;
+       }
+
+       if (owd > 0)
+               lp->flag |= LP_VALID_OWD;
+       else
+               lp->flag &= ~LP_VALID_OWD;
+
+       return owd;
+}
+
+/**
+ * tcp_lp_rtt_sample
+ *
+ * Implementation or rtt_sample.
+ * Will take the following action,
+ *   1. calc OWD,
+ *   2. record the min/max OWD,
+ *   3. calc smoothed OWD (SOWD).
+ * Most ideas come from the original TCP-LP implementation.
+ */
+static void tcp_lp_rtt_sample(struct sock *sk, u32 usrtt)
+{
+       struct lp *lp = inet_csk_ca(sk);
+       s64 mowd = tcp_lp_owd_calculator(sk);
+
+       /* sorry that we don't have valid data */
+       if (!(lp->flag & LP_VALID_RHZ) || !(lp->flag & LP_VALID_OWD))
+               return;
+
+       /* record the next min owd */
+       if (mowd < lp->owd_min)
+               lp->owd_min = mowd;
+
+       /* always forget the max of the max
+        * we just set owd_max as one below it */
+       if (mowd > lp->owd_max) {
+               if (mowd > lp->owd_max_rsv) {
+                       if (lp->owd_max_rsv == 0)
+                               lp->owd_max = mowd;
+                       else
+                               lp->owd_max = lp->owd_max_rsv;
+                       lp->owd_max_rsv = mowd;
+               } else
+                       lp->owd_max = mowd;
+       }
+
+       /* calc for smoothed owd */
+       if (lp->sowd != 0) {
+               mowd -= lp->sowd >> 3;  /* m is now error in owd est */
+               lp->sowd += mowd;       /* owd = 7/8 owd + 1/8 new */
+       } else
+               lp->sowd = mowd << 3;   /* take the measured time be owd */
+}
+
+/**
+ * tcp_lp_pkts_acked
+ *
+ * Implementation of pkts_acked.
+ * Deal with active drop under Early Congestion Indication.
+ * Only drop to half and 1 will be handle, because we hope to use back
+ * newReno in increase case.
+ * We work it out by following the idea from TCP-LP's paper directly
+ */
+static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
+
+       /* calc inference */
+       if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
+               lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
+
+       /* test if within inference */
+       if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
+               lp->flag |= LP_WITHIN_INF;
+       else
+               lp->flag &= ~LP_WITHIN_INF;
+
+       /* test if within threshold */
+       if (lp->sowd >> 3 <
+           lp->owd_min + 15 * (lp->owd_max - lp->owd_min) / 100)
+               lp->flag |= LP_WITHIN_THR;
+       else
+               lp->flag &= ~LP_WITHIN_THR;
+
+       pr_debug("TCP-LP: %05o|%5u|%5u|%15u|%15u|%15u\n", lp->flag,
+                tp->snd_cwnd, lp->remote_hz, lp->owd_min, lp->owd_max,
+                lp->sowd >> 3);
+
+       if (lp->flag & LP_WITHIN_THR)
+               return;
+
+       /* FIXME: try to reset owd_min and owd_max here
+        * so decrease the chance the min/max is no longer suitable
+        * and will usually within threshold when whithin inference */
+       lp->owd_min = lp->sowd >> 3;
+       lp->owd_max = lp->sowd >> 2;
+       lp->owd_max_rsv = lp->sowd >> 2;
+
+       /* happened within inference
+        * drop snd_cwnd into 1 */
+       if (lp->flag & LP_WITHIN_INF)
+               tp->snd_cwnd = 1U;
+
+       /* happened after inference
+        * cut snd_cwnd into half */
+       else
+               tp->snd_cwnd = max(tp->snd_cwnd >> 1U, 1U);
+
+       /* record this drop time */
+       lp->last_drop = tcp_time_stamp;
+}
+
+static struct tcp_congestion_ops tcp_lp = {
+       .init = tcp_lp_init,
+       .ssthresh = tcp_reno_ssthresh,
+       .cong_avoid = tcp_lp_cong_avoid,
+       .min_cwnd = tcp_reno_min_cwnd,
+       .rtt_sample = tcp_lp_rtt_sample,
+       .pkts_acked = tcp_lp_pkts_acked,
+
+       .owner = THIS_MODULE,
+       .name = "lp"
+};
+
+static int __init tcp_lp_register(void)
+{
+       BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
+       return tcp_register_congestion_control(&tcp_lp);
+}
+
+static void __exit tcp_lp_unregister(void)
+{
+       tcp_unregister_congestion_control(&tcp_lp);
+}
+
+module_init(tcp_lp_register);
+module_exit(tcp_lp_unregister);
+
+MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun Mike");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Low Priority");
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
new file mode 100644 (file)
index 0000000..dab37d2
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * tcpprobe - Observe the TCP flow with kprobes.
+ *
+ * The idea for this came from Werner Almesberger's umlsim
+ * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/socket.h>
+#include <linux/tcp.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/kfifo.h>
+#include <linux/vmalloc.h>
+
+#include <net/tcp.h>
+
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_DESCRIPTION("TCP cwnd snooper");
+MODULE_LICENSE("GPL");
+
+static int port = 0;
+MODULE_PARM_DESC(port, "Port to match (0=all)");
+module_param(port, int, 0);
+
+static int bufsize = 64*1024;
+MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+module_param(bufsize, int, 0);
+
+static const char procname[] = "tcpprobe";
+
+struct {
+       struct kfifo  *fifo;
+       spinlock_t    lock;
+       wait_queue_head_t wait;
+       struct timeval tstart;
+} tcpw;
+
+static void printl(const char *fmt, ...)
+{
+       va_list args;
+       int len;
+       struct timeval now;
+       char tbuf[256];
+
+       va_start(args, fmt);
+       do_gettimeofday(&now);
+
+       now.tv_sec -= tcpw.tstart.tv_sec;
+       now.tv_usec -= tcpw.tstart.tv_usec;
+       if (now.tv_usec < 0) {
+               --now.tv_sec;
+               now.tv_usec += 1000000;
+       }
+
+       len = sprintf(tbuf, "%lu.%06lu ",
+                     (unsigned long) now.tv_sec,
+                     (unsigned long) now.tv_usec);
+       len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
+       va_end(args);
+
+       kfifo_put(tcpw.fifo, tbuf, len);
+       wake_up(&tcpw.wait);
+}
+
+static int jtcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+                       struct msghdr *msg, size_t size)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       const struct inet_sock *inet = inet_sk(sk);
+
+       if (port == 0 || ntohs(inet->dport) == port ||
+           ntohs(inet->sport) == port) {
+               printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n",
+                      NIPQUAD(inet->saddr), ntohs(inet->sport),
+                      NIPQUAD(inet->daddr), ntohs(inet->dport),
+                      size, tp->snd_nxt, tp->snd_una,
+                      tp->snd_cwnd, tcp_current_ssthresh(sk),
+                      tp->snd_wnd);
+       }
+
+       jprobe_return();
+       return 0;
+}
+
+static struct jprobe tcp_send_probe = {
+       .kp = { .addr = (kprobe_opcode_t *) &tcp_sendmsg, },
+       .entry = (kprobe_opcode_t *) &jtcp_sendmsg,
+};
+
+
+static int tcpprobe_open(struct inode * inode, struct file * file)
+{
+       kfifo_reset(tcpw.fifo);
+       do_gettimeofday(&tcpw.tstart);
+       return 0;
+}
+
+static ssize_t tcpprobe_read(struct file *file, char __user *buf,
+                            size_t len, loff_t *ppos)
+{
+       int error = 0, cnt = 0;
+       unsigned char *tbuf;
+
+       if (!buf || len < 0)
+               return -EINVAL;
+
+       if (len == 0)
+               return 0;
+
+       tbuf = vmalloc(len);
+       if (!tbuf)
+               return -ENOMEM;
+
+       error = wait_event_interruptible(tcpw.wait,
+                                        __kfifo_len(tcpw.fifo) != 0);
+       if (error)
+               goto out_free;
+
+       cnt = kfifo_get(tcpw.fifo, tbuf, len);
+       error = copy_to_user(buf, tbuf, cnt);
+
+out_free:
+       vfree(tbuf);
+
+       return error ? error : cnt;
+}
+
+static struct file_operations tcpprobe_fops = {
+       .owner   = THIS_MODULE,
+       .open    = tcpprobe_open,
+       .read    = tcpprobe_read,
+};
+
+static __init int tcpprobe_init(void)
+{
+       int ret = -ENOMEM;
+
+       init_waitqueue_head(&tcpw.wait);
+       spin_lock_init(&tcpw.lock);
+       tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
+
+       if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
+               goto err0;
+
+       ret = register_jprobe(&tcp_send_probe);
+       if (ret)
+               goto err1;
+
+       pr_info("TCP watch registered (port=%d)\n", port);
+       return 0;
+ err1:
+       proc_net_remove(procname);
+ err0:
+       kfifo_free(tcpw.fifo);
+       return ret;
+}
+module_init(tcpprobe_init);
+
+static __exit void tcpprobe_exit(void)
+{
+       kfifo_free(tcpw.fifo);
+       proc_net_remove(procname);
+       unregister_jprobe(&tcp_send_probe);
+
+}
+module_exit(tcpprobe_exit);
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
new file mode 100644 (file)
index 0000000..5b2fe6d
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * TCP Veno congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ *    C. P. Fu, S. C. Liew.
+ *    "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks."
+ *    IEEE Journal on Selected Areas in Communication,
+ *    Feb. 2003.
+ *     See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Veno variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+static const int beta = 3 << V_PARAM_SHIFT;
+
+/* Veno variables */
+struct veno {
+       u8 doing_veno_now;      /* if true, do veno for this rtt */
+       u16 cntrtt;             /* # of rtts measured within last rtt */
+       u32 minrtt;             /* min of rtts measured within last rtt (in usec) */
+       u32 basertt;            /* the min of all Veno rtt measurements seen (in usec) */
+       u32 inc;                /* decide whether to increase cwnd */
+       u32 diff;               /* calculate the diff rate */
+};
+
+/* There are several situations when we must "re-start" Veno:
+ *
+ *  o when a connection is established
+ *  o after an RTO
+ *  o after fast recovery
+ *  o when we send a packet and there is no outstanding
+ *    unacknowledged data (restarting an idle connection)
+ *
+ */
+static inline void veno_enable(struct sock *sk)
+{
+       struct veno *veno = inet_csk_ca(sk);
+
+       /* turn on Veno */
+       veno->doing_veno_now = 1;
+
+       veno->minrtt = 0x7fffffff;
+}
+
+static inline void veno_disable(struct sock *sk)
+{
+       struct veno *veno = inet_csk_ca(sk);
+
+       /* turn off Veno */
+       veno->doing_veno_now = 0;
+}
+
+static void tcp_veno_init(struct sock *sk)
+{
+       struct veno *veno = inet_csk_ca(sk);
+
+       veno->basertt = 0x7fffffff;
+       veno->inc = 1;
+       veno_enable(sk);
+}
+
+/* Do rtt sampling needed for Veno. */
+static void tcp_veno_rtt_calc(struct sock *sk, u32 usrtt)
+{
+       struct veno *veno = inet_csk_ca(sk);
+       u32 vrtt = usrtt + 1;   /* Never allow zero rtt or basertt */
+
+       /* Filter to find propagation delay: */
+       if (vrtt < veno->basertt)
+               veno->basertt = vrtt;
+
+       /* Find the min rtt during the last rtt to find
+        * the current prop. delay + queuing delay:
+        */
+       veno->minrtt = min(veno->minrtt, vrtt);
+       veno->cntrtt++;
+}
+
+static void tcp_veno_state(struct sock *sk, u8 ca_state)
+{
+       if (ca_state == TCP_CA_Open)
+               veno_enable(sk);
+       else
+               veno_disable(sk);
+}
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Veno calculations
+ * until we get fresh rtt samples.  So when we
+ * restart, we reset our Veno state to a clean
+ * state. After we get acks for this flight of
+ * packets, _then_ we can make Veno calculations
+ * again.
+ */
+static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+       if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+               tcp_veno_init(sk);
+}
+
+static void tcp_veno_cong_avoid(struct sock *sk, u32 ack,
+                               u32 seq_rtt, u32 in_flight, int flag)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct veno *veno = inet_csk_ca(sk);
+
+       if (!veno->doing_veno_now)
+               return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+
+       /* limited by applications */
+       if (!tcp_is_cwnd_limited(sk, in_flight))
+               return;
+
+       /* We do the Veno calculations only if we got enough rtt samples */
+       if (veno->cntrtt <= 2) {
+               /* We don't have enough rtt samples to do the Veno
+                * calculation, so we'll behave like Reno.
+                */
+               tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+       } else {
+               u32 rtt, target_cwnd;
+
+               /* We have enough rtt samples, so, using the Veno
+                * algorithm, we determine the state of the network.
+                */
+
+               rtt = veno->minrtt;
+
+               target_cwnd = ((tp->snd_cwnd * veno->basertt)
+                              << V_PARAM_SHIFT) / rtt;
+
+               veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
+
+               if (tp->snd_cwnd <= tp->snd_ssthresh) {
+                       /* Slow start.  */
+                       tcp_slow_start(tp);
+               } else {
+                       /* Congestion avoidance. */
+                       if (veno->diff < beta) {
+                               /* In the "non-congestive state", increase cwnd
+                                *  every rtt.
+                                */
+                               if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+                                       if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+                                               tp->snd_cwnd++;
+                                       tp->snd_cwnd_cnt = 0;
+                               } else
+                                       tp->snd_cwnd_cnt++;
+                       } else {
+                               /* In the "congestive state", increase cwnd
+                                * every other rtt.
+                                */
+                               if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+                                       if (veno->inc
+                                           && tp->snd_cwnd <
+                                           tp->snd_cwnd_clamp) {
+                                               tp->snd_cwnd++;
+                                               veno->inc = 0;
+                                       } else
+                                               veno->inc = 1;
+                                       tp->snd_cwnd_cnt = 0;
+                               } else
+                                       tp->snd_cwnd_cnt++;
+                       }
+
+               }
+               if (tp->snd_cwnd < 2)
+                       tp->snd_cwnd = 2;
+               else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
+                       tp->snd_cwnd = tp->snd_cwnd_clamp;
+       }
+       /* Wipe the slate clean for the next rtt. */
+       /* veno->cntrtt = 0; */
+       veno->minrtt = 0x7fffffff;
+}
+
+/* Veno MD phase */
+static u32 tcp_veno_ssthresh(struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       struct veno *veno = inet_csk_ca(sk);
+
+       if (veno->diff < beta)
+               /* in "non-congestive state", cut cwnd by 1/5 */
+               return max(tp->snd_cwnd * 4 / 5, 2U);
+       else
+               /* in "congestive state", cut cwnd by 1/2 */
+               return max(tp->snd_cwnd >> 1U, 2U);
+}
+
+static struct tcp_congestion_ops tcp_veno = {
+       .init           = tcp_veno_init,
+       .ssthresh       = tcp_veno_ssthresh,
+       .cong_avoid     = tcp_veno_cong_avoid,
+       .rtt_sample     = tcp_veno_rtt_calc,
+       .set_state      = tcp_veno_state,
+       .cwnd_event     = tcp_veno_cwnd_event,
+
+       .owner          = THIS_MODULE,
+       .name           = "veno",
+};
+
+static int __init tcp_veno_register(void)
+{
+       BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
+       tcp_register_congestion_control(&tcp_veno);
+       return 0;
+}
+
+static void __exit tcp_veno_unregister(void)
+{
+       tcp_unregister_congestion_control(&tcp_veno);
+}
+
+module_init(tcp_veno_register);
+module_exit(tcp_veno_unregister);
+
+MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Veno");
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
new file mode 100644 (file)
index 0000000..a9e6b3d
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header will be moved forward to make space for the encapsulation
+ * header.
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_transport_output(struct sk_buff *skb)
+{
+       struct xfrm_state *x;
+       struct iphdr *iph;
+       int ihl;
+
+       iph = skb->nh.iph;
+       skb->h.ipiph = iph;
+
+       ihl = iph->ihl * 4;
+       skb->h.raw += ihl;
+
+       x = skb->dst->xfrm;
+       skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl);
+       return 0;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int ihl = skb->data - skb->h.raw;
+
+       if (skb->h.raw != skb->nh.raw)
+               skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
+       skb->nh.iph->tot_len = htons(skb->len + ihl);
+       skb->h.raw = skb->data;
+       return 0;
+}
+
+static struct xfrm_mode xfrm4_transport_mode = {
+       .input = xfrm4_transport_input,
+       .output = xfrm4_transport_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm4_transport_init(void)
+{
+       return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
+}
+
+static void __exit xfrm4_transport_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET);
+       BUG_ON(err);
+}
+
+module_init(xfrm4_transport_init);
+module_exit(xfrm4_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
new file mode 100644 (file)
index 0000000..13cafbe
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
+{
+       struct iphdr *outer_iph = skb->nh.iph;
+       struct iphdr *inner_iph = skb->h.ipiph;
+
+       if (INET_ECN_is_ce(outer_iph->tos))
+               IP_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.  The following fields
+ * in it shall be filled in by x->type->output:
+ *      tot_len
+ *      check
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_tunnel_output(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       struct iphdr *iph, *top_iph;
+       int flags;
+
+       iph = skb->nh.iph;
+       skb->h.ipiph = iph;
+
+       skb->nh.raw = skb_push(skb, x->props.header_len);
+       top_iph = skb->nh.iph;
+
+       top_iph->ihl = 5;
+       top_iph->version = 4;
+
+       /* DS disclosed */
+       top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+
+       flags = x->props.flags;
+       if (flags & XFRM_STATE_NOECN)
+               IP_ECN_clear(top_iph);
+
+       top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+               0 : (iph->frag_off & htons(IP_DF));
+       if (!top_iph->frag_off)
+               __ip_select_ident(top_iph, dst->child, 0);
+
+       top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
+
+       top_iph->saddr = x->props.saddr.a4;
+       top_iph->daddr = x->id.daddr.a4;
+       top_iph->protocol = IPPROTO_IPIP;
+
+       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+       return 0;
+}
+
+static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->nh.iph;
+       int err = -EINVAL;
+
+       if (iph->protocol != IPPROTO_IPIP)
+               goto out;
+       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+               goto out;
+
+       if (skb_cloned(skb) &&
+           (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+               goto out;
+
+       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+               ipv4_copy_dscp(iph, skb->h.ipiph);
+       if (!(x->props.flags & XFRM_STATE_NOECN))
+               ipip_ecn_decapsulate(skb);
+       skb->mac.raw = memmove(skb->data - skb->mac_len,
+                              skb->mac.raw, skb->mac_len);
+       skb->nh.raw = skb->data;
+       err = 0;
+
+out:
+       return err;
+}
+
+static struct xfrm_mode xfrm4_tunnel_mode = {
+       .input = xfrm4_tunnel_input,
+       .output = xfrm4_tunnel_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm4_tunnel_init(void)
+{
+       return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
+}
+
+static void __exit xfrm4_tunnel_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
+       BUG_ON(err);
+}
+
+module_init(xfrm4_tunnel_init);
+module_exit(xfrm4_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
new file mode 100644 (file)
index 0000000..711d713
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header and mutable extension headers will be moved forward to make
+ * space for the encapsulation header.
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header.  The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_transport_output(struct sk_buff *skb)
+{
+       struct xfrm_state *x = skb->dst->xfrm;
+       struct ipv6hdr *iph;
+       u8 *prevhdr;
+       int hdr_len;
+
+       skb_push(skb, x->props.header_len);
+       iph = skb->nh.ipv6h;
+
+       hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+       skb->nh.raw = prevhdr - x->props.header_len;
+       skb->h.raw = skb->data + hdr_len;
+       memmove(skb->data, iph, hdr_len);
+       return 0;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int ihl = skb->data - skb->h.raw;
+
+       if (skb->h.raw != skb->nh.raw)
+               skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
+       skb->nh.ipv6h->payload_len = htons(skb->len + ihl -
+                                          sizeof(struct ipv6hdr));
+       skb->h.raw = skb->data;
+       return 0;
+}
+
+static struct xfrm_mode xfrm6_transport_mode = {
+       .input = xfrm6_transport_input,
+       .output = xfrm6_transport_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm6_transport_init(void)
+{
+       return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6);
+}
+
+static void __exit xfrm6_transport_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6);
+       BUG_ON(err);
+}
+
+module_init(xfrm6_transport_init);
+module_exit(xfrm6_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
new file mode 100644 (file)
index 0000000..8af79be
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dsfield.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
+{
+       struct ipv6hdr *outer_iph = skb->nh.ipv6h;
+       struct ipv6hdr *inner_iph = skb->h.ipv6h;
+
+       if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
+               IP6_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.  The following fields
+ * in it shall be filled in by x->type->output:
+ *     payload_len
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header.  The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_tunnel_output(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       struct ipv6hdr *iph, *top_iph;
+       int dsfield;
+
+       skb_push(skb, x->props.header_len);
+       iph = skb->nh.ipv6h;
+
+       skb->nh.raw = skb->data;
+       top_iph = skb->nh.ipv6h;
+       skb->nh.raw = &top_iph->nexthdr;
+       skb->h.ipv6h = top_iph + 1;
+
+       top_iph->version = 6;
+       top_iph->priority = iph->priority;
+       top_iph->flow_lbl[0] = iph->flow_lbl[0];
+       top_iph->flow_lbl[1] = iph->flow_lbl[1];
+       top_iph->flow_lbl[2] = iph->flow_lbl[2];
+       dsfield = ipv6_get_dsfield(top_iph);
+       dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+       if (x->props.flags & XFRM_STATE_NOECN)
+               dsfield &= ~INET_ECN_MASK;
+       ipv6_change_dsfield(top_iph, 0, dsfield);
+       top_iph->nexthdr = IPPROTO_IPV6; 
+       top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
+       ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+       ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+       return 0;
+}
+
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int err = -EINVAL;
+
+       if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6)
+               goto out;
+       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+               goto out;
+
+       if (skb_cloned(skb) &&
+           (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+               goto out;
+
+       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+               ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
+       if (!(x->props.flags & XFRM_STATE_NOECN))
+               ipip6_ecn_decapsulate(skb);
+       skb->mac.raw = memmove(skb->data - skb->mac_len,
+                              skb->mac.raw, skb->mac_len);
+       skb->nh.raw = skb->data;
+       err = 0;
+
+out:
+       return err;
+}
+
+static struct xfrm_mode xfrm6_tunnel_mode = {
+       .input = xfrm6_tunnel_input,
+       .output = xfrm6_tunnel_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm6_tunnel_init(void)
+{
+       return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6);
+}
+
+static void __exit xfrm6_tunnel_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6);
+       BUG_ON(err);
+}
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
new file mode 100644 (file)
index 0000000..8c011e0
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * This module is used to copy security markings from packets
+ * to connections, and restore security markings from connections
+ * back to packets.  This would normally be performed in conjunction
+ * with the SECMARK target and state match.
+ *
+ * Based somewhat on CONNMARK:
+ *   Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ *    by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+#include <net/netfilter/nf_conntrack_compat.h>
+
+#define PFX "CONNSECMARK: "
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module");
+MODULE_ALIAS("ipt_CONNSECMARK");
+MODULE_ALIAS("ip6t_CONNSECMARK");
+
+/*
+ * If the packet has a security mark and the connection does not, copy
+ * the security mark from the packet to the connection.
+ */
+static void secmark_save(struct sk_buff *skb)
+{
+       if (skb->secmark) {
+               u32 *connsecmark;
+               enum ip_conntrack_info ctinfo;
+
+               connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+               if (connsecmark && !*connsecmark)
+                       if (*connsecmark != skb->secmark)
+                               *connsecmark = skb->secmark;
+       }
+}
+
+/*
+ * If packet has no security mark, and the connection does, restore the
+ * security mark from the connection to the packet.
+ */
+static void secmark_restore(struct sk_buff *skb)
+{
+       if (!skb->secmark) {
+               u32 *connsecmark;
+               enum ip_conntrack_info ctinfo;
+
+               connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+               if (connsecmark && *connsecmark)
+                       if (skb->secmark != *connsecmark)
+                               skb->secmark = *connsecmark;
+       }
+}
+
+static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+                          const struct net_device *out, unsigned int hooknum,
+                          const struct xt_target *target,
+                          const void *targinfo, void *userinfo)
+{
+       struct sk_buff *skb = *pskb;
+       const struct xt_connsecmark_target_info *info = targinfo;
+
+       switch (info->mode) {
+       case CONNSECMARK_SAVE:
+               secmark_save(skb);
+               break;
+
+       case CONNSECMARK_RESTORE:
+               secmark_restore(skb);
+               break;
+
+       default:
+               BUG();
+       }
+
+       return XT_CONTINUE;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+                     const struct xt_target *target, void *targinfo,
+                     unsigned int targinfosize, unsigned int hook_mask)
+{
+       struct xt_connsecmark_target_info *info = targinfo;
+
+       switch (info->mode) {
+       case CONNSECMARK_SAVE:
+       case CONNSECMARK_RESTORE:
+               break;
+
+       default:
+               printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+               return 0;
+       }
+
+       return 1;
+}
+
+static struct xt_target ipt_connsecmark_reg = {
+       .name           = "CONNSECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_connsecmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET,
+       .revision       = 0,
+};
+
+static struct xt_target ip6t_connsecmark_reg = {
+       .name           = "CONNSECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_connsecmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET6,
+       .revision       = 0,
+};
+
+static int __init xt_connsecmark_init(void)
+{
+       int err;
+
+       need_conntrack();
+
+       err = xt_register_target(&ipt_connsecmark_reg);
+       if (err)
+               return err;
+
+       err = xt_register_target(&ip6t_connsecmark_reg);
+       if (err)
+               xt_unregister_target(&ipt_connsecmark_reg);
+
+       return err;
+}
+
+static void __exit xt_connsecmark_fini(void)
+{
+       xt_unregister_target(&ip6t_connsecmark_reg);
+       xt_unregister_target(&ipt_connsecmark_reg);
+}
+
+module_init(xt_connsecmark_init);
+module_exit(xt_connsecmark_fini);
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
new file mode 100644 (file)
index 0000000..de9537a
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Module for modifying the secmark field of the skb, for use by
+ * security subsystems.
+ *
+ * Based on the nfmark match by:
+ * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/selinux.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables SECMARK modification module");
+MODULE_ALIAS("ipt_SECMARK");
+MODULE_ALIAS("ip6t_SECMARK");
+
+#define PFX "SECMARK: "
+
+static u8 mode;
+
+static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+                          const struct net_device *out, unsigned int hooknum,
+                          const struct xt_target *target,
+                          const void *targinfo, void *userinfo)
+{
+       u32 secmark = 0;
+       const struct xt_secmark_target_info *info = targinfo;
+
+       BUG_ON(info->mode != mode);
+
+       switch (mode) {
+       case SECMARK_MODE_SEL:
+               secmark = info->u.sel.selsid;
+               break;
+
+       default:
+               BUG();
+       }
+
+       if ((*pskb)->secmark != secmark)
+               (*pskb)->secmark = secmark;
+
+       return XT_CONTINUE;
+}
+
+static int checkentry_selinux(struct xt_secmark_target_info *info)
+{
+       int err;
+       struct xt_secmark_target_selinux_info *sel = &info->u.sel;
+       
+       sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0';
+
+       err = selinux_string_to_sid(sel->selctx, &sel->selsid);
+       if (err) {
+               if (err == -EINVAL)
+                       printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
+                              sel->selctx);
+               return 0;
+       }
+
+       if (!sel->selsid) {
+               printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
+                      sel->selctx);
+               return 0;
+       }
+
+       err = selinux_relabel_packet_permission(sel->selsid);
+       if (err) {
+               printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+                     const struct xt_target *target, void *targinfo,
+                     unsigned int targinfosize, unsigned int hook_mask)
+{
+       struct xt_secmark_target_info *info = targinfo;
+
+       if (mode && mode != info->mode) {
+               printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
+                      "rules for mode %hu\n", mode, info->mode);
+               return 0;
+       }
+
+       switch (info->mode) {
+       case SECMARK_MODE_SEL:
+               if (!checkentry_selinux(info))
+                       return 0;
+               break;
+
+       default:
+               printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+               return 0;
+       }
+
+       if (!mode)
+               mode = info->mode;
+       return 1;
+}
+
+static struct xt_target ipt_secmark_reg = {
+       .name           = "SECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_secmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET,
+       .revision       = 0,
+};
+
+static struct xt_target ip6t_secmark_reg = {
+       .name           = "SECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_secmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET6,
+       .revision       = 0,
+};
+
+static int __init xt_secmark_init(void)
+{
+       int err;
+
+       err = xt_register_target(&ipt_secmark_reg);
+       if (err)
+               return err;
+
+       err = xt_register_target(&ip6t_secmark_reg);
+       if (err)
+               xt_unregister_target(&ipt_secmark_reg);
+
+       return err;
+}
+
+static void __exit xt_secmark_fini(void)
+{
+       xt_unregister_target(&ip6t_secmark_reg);
+       xt_unregister_target(&ipt_secmark_reg);
+}
+
+module_init(xt_secmark_init);
+module_exit(xt_secmark_fini);
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
new file mode 100644 (file)
index 0000000..be8d3c2
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * netfilter module to enforce network quotas
+ *
+ * Sam Johnston <samj@samj.net>
+ */
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_quota.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
+MODULE_ALIAS("ipt_quota");
+MODULE_ALIAS("ip6t_quota");
+
+static DEFINE_SPINLOCK(quota_lock);
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in, const struct net_device *out,
+      const struct xt_match *match, const void *matchinfo,
+      int offset, unsigned int protoff, int *hotdrop)
+{
+       struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
+       int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
+
+       spin_lock_bh(&quota_lock);
+       if (q->quota >= skb->len) {
+               q->quota -= skb->len;
+               ret ^= 1;
+       } else {
+               /* we do not allow even small packets from now on */
+               q->quota = 0;
+       }
+       spin_unlock_bh(&quota_lock);
+
+       return ret;
+}
+
+static int
+checkentry(const char *tablename, const void *entry,
+          const struct xt_match *match, void *matchinfo,
+          unsigned int matchsize, unsigned int hook_mask)
+{
+       struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
+
+       if (q->flags & ~XT_QUOTA_MASK)
+               return 0;
+       /* For SMP, we only want to use one set of counters. */
+       q->master = q;
+       return 1;
+}
+
+static struct xt_match quota_match = {
+       .name           = "quota",
+       .family         = AF_INET,
+       .match          = match,
+       .matchsize      = sizeof(struct xt_quota_info),
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE
+};
+
+static struct xt_match quota_match6 = {
+       .name           = "quota",
+       .family         = AF_INET6,
+       .match          = match,
+       .matchsize      = sizeof(struct xt_quota_info),
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE
+};
+
+static int __init xt_quota_init(void)
+{
+       int ret;
+
+       ret = xt_register_match(&quota_match);
+       if (ret)
+               goto err1;
+       ret = xt_register_match(&quota_match6);
+       if (ret)
+               goto err2;
+       return ret;
+
+err2:
+       xt_unregister_match(&quota_match);
+err1:
+       return ret;
+}
+
+static void __exit xt_quota_fini(void)
+{
+       xt_unregister_match(&quota_match6);
+       xt_unregister_match(&quota_match);
+}
+
+module_init(xt_quota_init);
+module_exit(xt_quota_fini);
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
new file mode 100644 (file)
index 0000000..de1037f
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>.
+ */
+
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+
+#include <linux/netfilter/xt_statistic.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("xtables statistical match module");
+MODULE_ALIAS("ipt_statistic");
+MODULE_ALIAS("ip6t_statistic");
+
+static DEFINE_SPINLOCK(nth_lock);
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in, const struct net_device *out,
+      const struct xt_match *match, const void *matchinfo,
+      int offset, unsigned int protoff, int *hotdrop)
+{
+       struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+       int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0;
+
+       switch (info->mode) {
+       case XT_STATISTIC_MODE_RANDOM:
+               if ((net_random() & 0x7FFFFFFF) < info->u.random.probability)
+                       ret ^= 1;
+               break;
+       case XT_STATISTIC_MODE_NTH:
+               info = info->master;
+               spin_lock_bh(&nth_lock);
+               if (info->u.nth.count++ == info->u.nth.every) {
+                       info->u.nth.count = 0;
+                       ret ^= 1;
+               }
+               spin_unlock_bh(&nth_lock);
+               break;
+       }
+
+       return ret;
+}
+
+static int
+checkentry(const char *tablename, const void *entry,
+          const struct xt_match *match, void *matchinfo,
+          unsigned int matchsize, unsigned int hook_mask)
+{
+       struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+
+       if (info->mode > XT_STATISTIC_MODE_MAX ||
+           info->flags & ~XT_STATISTIC_MASK)
+               return 0;
+       info->master = info;
+       return 1;
+}
+
+static struct xt_match statistic_match = {
+       .name           = "statistic",
+       .match          = match,
+       .matchsize      = sizeof(struct xt_statistic_info),
+       .checkentry     = checkentry,
+       .family         = AF_INET,
+       .me             = THIS_MODULE,
+};
+
+static struct xt_match statistic_match6 = {
+       .name           = "statistic",
+       .match          = match,
+       .matchsize      = sizeof(struct xt_statistic_info),
+       .checkentry     = checkentry,
+       .family         = AF_INET6,
+       .me             = THIS_MODULE,
+};
+
+static int __init xt_statistic_init(void)
+{
+       int ret;
+
+       ret = xt_register_match(&statistic_match);
+       if (ret)
+               goto err1;
+
+       ret = xt_register_match(&statistic_match6);
+       if (ret)
+               goto err2;
+       return ret;
+err2:
+       xt_unregister_match(&statistic_match);
+err1:
+       return ret;
+}
+
+static void __exit xt_statistic_fini(void)
+{
+       xt_unregister_match(&statistic_match6);
+       xt_unregister_match(&statistic_match);
+}
+
+module_init(xt_statistic_init);
+module_exit(xt_statistic_fini);
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
new file mode 100644 (file)
index 0000000..12e1daf
--- /dev/null
@@ -0,0 +1,160 @@
+# ==========================================================================
+# Installing headers
+#
+# header-y files will be installed verbatim
+# unifdef-y are the files where unifdef will be run before installing files
+# objhdr-y are generated files that will be installed verbatim
+#
+# ==========================================================================
+
+UNIFDEF := unifdef -U__KERNEL__
+
+# Eliminate the contents of (and inclusions of) compiler.h
+HDRSED  := sed         -e "s/ inline / __inline__ /g" \
+               -e "s/[[:space:]]__user[[:space:]]\+/ /g" \
+               -e "s/(__user[[:space:]]\+/ (/g" \
+               -e "s/[[:space:]]__force[[:space:]]\+/ /g" \
+               -e "s/(__force[[:space:]]\+/ (/g" \
+               -e "s/[[:space:]]__iomem[[:space:]]\+/ /g" \
+               -e "s/(__iomem[[:space:]]\+/ (/g" \
+               -e "s/[[:space:]]__attribute_const__[[:space:]]\+/\ /g" \
+               -e "s/[[:space:]]__attribute_const__$$//" \
+               -e "/^\#include <linux\/compiler.h>/d"
+
+_dst := $(if $(dst),$(dst),$(obj))
+
+.PHONY: __headersinst
+__headersinst:
+
+
+ifeq (,$(patsubst include/asm/%,,$(obj)/))
+# For producing the generated stuff in include/asm for biarch builds, include
+# both sets of Kbuild files; we'll generate anything which is mentioned in
+# _either_ arch, and recurse into subdirectories which are mentioned in either
+# arch. Since some directories may exist in one but not the other, we must
+# use '-include'.
+GENASM := 1
+archasm           := $(subst include/asm,asm-$(ARCH),$(obj))
+altarchasm := $(subst include/asm,asm-$(ALTARCH),$(obj))
+-include $(srctree)/include/$(archasm)/Kbuild
+-include $(srctree)/include/$(altarchasm)/Kbuild
+else
+include $(srctree)/$(obj)/Kbuild
+endif
+
+include scripts/Kbuild.include
+
+# If this is include/asm-$(ARCH) and there's no $(ALTARCH), then
+# override $(_dst) so that we install to include/asm directly.
+ifeq ($(obj)$(ALTARCH),include/asm-$(ARCH))
+     _dst := include/asm
+endif
+
+header-y       := $(sort $(header-y))
+unifdef-y      := $(sort $(unifdef-y))
+subdir-y       := $(patsubst %/,%,$(filter %/, $(header-y)))
+header-y       := $(filter-out %/, $(header-y))
+header-y       := $(filter-out $(unifdef-y),$(header-y))
+
+ifdef ALTARCH
+ifeq ($(obj),include/asm-$(ARCH))
+altarch-y      := altarch-dir
+endif
+endif
+
+# Make the definitions visible for recursive make invocations
+export ALTARCH
+export ARCHDEF
+export ALTARCHDEF
+
+quiet_cmd_o_hdr_install   = INSTALL $(_dst)/$@
+      cmd_o_hdr_install   = cp $(objtree)/$(obj)/$@ $(INSTALL_HDR_PATH)/$(_dst)
+
+quiet_cmd_headers_install = INSTALL $(_dst)/$@
+      cmd_headers_install = $(HDRSED) $(srctree)/$(obj)/$@             \
+                           > $(INSTALL_HDR_PATH)/$(_dst)/$@
+
+quiet_cmd_unifdef        = UNIFDEF $(_dst)/$@
+      cmd_unifdef        = $(UNIFDEF) $(srctree)/$(obj)/$@ | $(HDRSED) \
+                            > $(INSTALL_HDR_PATH)/$(_dst)/$@ || :
+
+quiet_cmd_check                  = CHECK   $(_dst)/$@
+      cmd_check                  = $(srctree)/scripts/hdrcheck.sh              \
+                              $(INSTALL_HDR_PATH)/include              \
+                             $(INSTALL_HDR_PATH)/$(_dst)/$@
+
+quiet_cmd_mkdir                  = MKDIR   $@
+      cmd_mkdir                  = mkdir -p $(INSTALL_HDR_PATH)/$@
+
+quiet_cmd_gen            = GEN     $(_dst)/$@
+      cmd_gen            = \
+STUBDEF=__ASM_STUB_`echo $@ | tr a-z. A-Z_`;                           \
+(echo "/* File autogenerated by 'make headers_install' */" ;           \
+echo "\#ifndef $$STUBDEF" ;                                            \
+echo "\#define $$STUBDEF" ;                                            \
+echo "\# if $(ARCHDEF)" ;                                              \
+if [ -r $(INSTALL_HDR_PATH)/include/$(archasm)/$@ ]; then              \
+       echo "\#  include <$(archasm)/$@>" ;                            \
+else                                                                   \
+       echo "\#  error $(archasm)/$@ does not exist in"                \
+                       "the $(ARCH) architecture" ;                    \
+fi ;                                                                   \
+echo "\# elif $(ALTARCHDEF)" ;                                         \
+if [ -r $(INSTALL_HDR_PATH)/include/$(altarchasm)/$@ ]; then           \
+       echo "\#  include <$(altarchasm)/$@>" ;                         \
+else                                                                   \
+       echo "\#  error $(altarchasm)/$@ does not exist in"             \
+                       "the $(ALTARCH) architecture" ;                 \
+fi ;                                                                   \
+echo "\# else" ;                                                       \
+echo "\#  warning This machine appears to be"                          \
+                "neither $(ARCH) nor $(ALTARCH)." ;                    \
+echo "\# endif" ;                                                      \
+echo "\#endif /* $$STUBDEF */" ;                                       \
+) > $(INSTALL_HDR_PATH)/$(_dst)/$@
+
+__headersinst: $(subdir-y) $(header-y) $(unifdef-y) $(altarch-y) $(objhdr-y)
+
+.PHONY: $(header-y) $(unifdef-y) $(subdir-y)
+
+ifdef HDRCHECK
+# Rules for checking headers
+$(objhdr-y) $(header-y) $(unifdef-y):
+       $(call cmd,check)
+else
+# Rules for installing headers
+
+$(objhdr-y) $(subdir-y) $(header-y) $(unifdef-y): $(_dst)
+
+.PHONY: $(_dst)
+$(_dst):
+       $(call cmd,mkdir)
+
+ifdef GENASM
+$(objhdr-y) $(header-y) $(unifdef-y):
+       $(call cmd,gen)
+
+else
+$(objhdr-y):
+       $(call cmd,o_hdr_install)
+
+$(header-y):
+       $(call cmd,headers_install)
+
+$(unifdef-y):
+       $(call cmd,unifdef)
+endif
+endif
+
+hdrinst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
+
+.PHONY: altarch-dir
+# All the files in the normal arch dir must be created first, since we test
+# for their existence.
+altarch-dir: $(subdir-y) $(header-y) $(unifdef-y) $(objhdr-y)
+       $(Q)$(MAKE) $(hdrinst)=include/asm-$(ALTARCH) dst=include/asm-$(ALTARCH)
+       $(Q)$(MAKE) $(hdrinst)=include/asm dst=include/asm
+
+# Recursion
+$(subdir-y):
+       $(Q)$(MAKE) $(hdrinst)=$(obj)/$@ dst=$(_dst)/$@ rel=../$(rel)
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
new file mode 100644 (file)
index 0000000..9ed00d9
--- /dev/null
@@ -0,0 +1,169 @@
+#!/usr/bin/perl -w
+#
+# (C) Copyright IBM Corporation 2006.
+#      Released under GPL v2.
+#      Author : Ram Pai (linuxram@us.ibm.com)
+#
+# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c
+#
+
+use Getopt::Std;
+use strict;
+
+sub numerically {
+       my $no1 = (split /\s+/, $a)[1];
+       my $no2 = (split /\s+/, $b)[1];
+       return $no1 <=> $no2;
+}
+
+sub alphabetically {
+       my ($module1, $value1) = @{$a};
+       my ($module2, $value2) = @{$b};
+       return $value1 <=> $value2 || $module2 cmp $module1;
+}
+
+sub print_depends_on {
+       my ($href) = @_;
+       print "\n";
+       while (my ($mod, $list) = each %$href) {
+               print "\t$mod:\n";
+               foreach my $sym (sort numerically @{$list}) {
+                       my ($symbol, $no) = split /\s+/, $sym;
+                       printf("\t\t%-25s\t%-25d\n", $symbol, $no);
+               }
+               print "\n";
+       }
+       print "\n";
+       print "~"x80 , "\n";
+}
+
+sub usage {
+        print "Usage: @_ -h -k Module.symvers  [ -o outputfile ] \n",
+             "\t-f: treat all the non-option argument as .mod.c files. ",
+             "Recommend using this as the last option\n",
+             "\t-h: print detailed help\n",
+             "\t-k: the path to Module.symvers file. By default uses ",
+             "the file from the current directory\n",
+             "\t-o outputfile: output the report to outputfile\n";
+       exit 0;
+}
+
+sub collectcfiles {
+        my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`;
+        @file = grep {s/\.ko/.mod.c/} @file;
+       chomp @file;
+        return @file;
+}
+
+my (%SYMBOL, %MODULE, %opt, @allcfiles);
+
+if (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) {
+        usage($0);
+}
+
+if (defined $opt{'f'}) {
+       @allcfiles = @ARGV;
+} else {
+       @allcfiles = collectcfiles();
+}
+
+if (not defined $opt{'k'}) {
+       $opt{'k'} = "Module.symvers";
+}
+
+unless (open(MODULE_SYMVERS, $opt{'k'})) {
+       die "Sorry, cannot open $opt{'k'}: $!\n";
+}
+
+if (defined $opt{'o'}) {
+       unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) {
+               die "Sorry, cannot open $opt{'o'} $!\n";
+       }
+       select OUTPUT_HANDLE;
+}
+#
+# collect all the symbols and their attributes from the
+# Module.symvers file
+#
+while ( <MODULE_SYMVERS> ) {
+       chomp;
+       my (undef, $symbol, $module, $gpl) = split;
+       $SYMBOL { $symbol } =  [ $module , "0" , $symbol, $gpl];
+}
+close(MODULE_SYMVERS);
+
+#
+# collect the usage count of each symbol.
+#
+foreach my $thismod (@allcfiles) {
+       unless (open(MODULE_MODULE, $thismod)) {
+               print "Sorry, cannot open $thismod: $!\n";
+               next;
+       }
+       my $state=0;
+       while ( <MODULE_MODULE> ) {
+               chomp;
+               if ($state eq 0) {
+                       $state = 1 if ($_ =~ /static const struct modversion_info/);
+                       next;
+               }
+               if ($state eq 1) {
+                       $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/);
+                       next;
+               }
+               if ($state eq 2) {
+                       if ( $_ !~ /0x[0-9a-f]{7,8},/ ) {
+                               next;
+                       }
+                       my $sym = (split /([,"])/,)[4];
+                       my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}};
+                       $SYMBOL{ $sym } =  [ $module, $value+1, $symbol, $gpl];
+                       push(@{$MODULE{$thismod}} , $sym);
+               }
+       }
+       if ($state ne 2) {
+               print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n";
+       }
+       close(MODULE_MODULE);
+}
+
+print "\tThis file reports the exported symbols usage patterns by in-tree\n",
+       "\t\t\t\tmodules\n";
+printf("%s\n\n\n","x"x80);
+printf("\t\t\t\tINDEX\n\n\n");
+printf("SECTION 1: Usage counts of all exported symbols\n");
+printf("SECTION 2: List of modules and the exported symbols they use\n");
+printf("%s\n\n\n","x"x80);
+printf("SECTION 1:\tThe exported symbols and their usage count\n\n");
+printf("%-25s\t%-25s\t%-5s\t%-25s\n", "Symbol", "Module", "Usage count",
+       "export type");
+
+#
+# print the list of unused exported symbols
+#
+foreach my $list (sort alphabetically values(%SYMBOL)) {
+       my ($module, $value, $symbol, $gpl) = @{$list};
+       printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value);
+       if (defined $gpl) {
+               printf("%-25s\n",$gpl);
+       } else {
+               printf("\n");
+       }
+}
+printf("%s\n\n\n","x"x80);
+
+printf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel
+modules. Each module lists the modules, and the symbols from that module that
+it uses.  Each listed symbol reports the number of modules using it\n");
+
+print "~"x80 , "\n";
+while (my ($thismod, $list) = each %MODULE) {
+       my %depends;
+       $thismod =~ s/\.mod\.c/.ko/;
+       print "\t\t\t$thismod\n";
+       foreach my $symbol (@{$list}) {
+               my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}};
+               push (@{$depends{"$module"}}, "$symbol $value");
+       }
+       print_depends_on(\%depends);
+}
diff --git a/scripts/hdrcheck.sh b/scripts/hdrcheck.sh
new file mode 100755 (executable)
index 0000000..b5ca35a
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+for FILE in `grep '^[ \t]*#[ \t]*include[ \t]*<' $2 | cut -f2 -d\< | cut -f1 -d\> | egrep ^linux\|^asm` ; do
+    if [ ! -r $1/$FILE ]; then
+       echo $2 requires $FILE, which does not exist in exported headers
+       exit 1
+    fi
+done
diff --git a/scripts/rt-tester/check-all.sh b/scripts/rt-tester/check-all.sh
new file mode 100644 (file)
index 0000000..43098af
--- /dev/null
@@ -0,0 +1,22 @@
+
+
+function testit ()
+{
+ printf "%-30s: " $1
+ ./rt-tester.py $1 | grep Pass
+}
+
+testit t2-l1-2rt-sameprio.tst
+testit t2-l1-pi.tst
+testit t2-l1-signal.tst
+#testit t2-l2-2rt-deadlock.tst
+testit t3-l1-pi-1rt.tst
+testit t3-l1-pi-2rt.tst
+testit t3-l1-pi-3rt.tst
+testit t3-l1-pi-signal.tst
+testit t3-l1-pi-steal.tst
+testit t3-l2-pi.tst
+testit t4-l2-pi-deboost.tst
+testit t5-l4-pi-boost-deboost.tst
+testit t5-l4-pi-boost-deboost-setsched.tst
+
diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py
new file mode 100644 (file)
index 0000000..4c79660
--- /dev/null
@@ -0,0 +1,222 @@
+#!/usr/bin/env python
+#
+# rt-mutex tester
+#
+# (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+import os
+import sys
+import getopt
+import shutil
+import string
+
+# Globals
+quiet = 0
+test = 0
+comments = 0
+
+sysfsprefix = "/sys/devices/system/rttest/rttest"
+statusfile = "/status"
+commandfile = "/command"
+
+# Command opcodes
+cmd_opcodes = {
+    "schedother"    : "1",
+    "schedfifo"     : "2",
+    "lock"          : "3",
+    "locknowait"    : "4",
+    "lockint"       : "5",
+    "lockintnowait" : "6",
+    "lockcont"      : "7",
+    "unlock"        : "8",
+    "lockbkl"       : "9",
+    "unlockbkl"     : "10",
+    "signal"        : "11",
+    "resetevent"    : "98",
+    "reset"         : "99",
+    }
+
+test_opcodes = {
+    "prioeq"        : ["P" , "eq" , None],
+    "priolt"        : ["P" , "lt" , None],
+    "priogt"        : ["P" , "gt" , None],
+    "nprioeq"       : ["N" , "eq" , None],
+    "npriolt"       : ["N" , "lt" , None],
+    "npriogt"       : ["N" , "gt" , None],
+    "unlocked"      : ["M" , "eq" , 0],
+    "trylock"       : ["M" , "eq" , 1],
+    "blocked"       : ["M" , "eq" , 2],
+    "blockedwake"   : ["M" , "eq" , 3],
+    "locked"        : ["M" , "eq" , 4],
+    "opcodeeq"      : ["O" , "eq" , None],
+    "opcodelt"      : ["O" , "lt" , None],
+    "opcodegt"      : ["O" , "gt" , None],
+    "eventeq"       : ["E" , "eq" , None],
+    "eventlt"       : ["E" , "lt" , None],
+    "eventgt"       : ["E" , "gt" , None],
+    }
+
+# Print usage information
+def usage():
+    print "rt-tester.py <-c -h -q -t> <testfile>"
+    print " -c    display comments after first command"
+    print " -h    help"
+    print " -q    quiet mode"
+    print " -t    test mode (syntax check)"
+    print " testfile: read test specification from testfile"
+    print " otherwise from stdin"
+    return
+
+# Print progress when not in quiet mode
+def progress(str):
+    if not quiet:
+        print str
+
+# Analyse a status value
+def analyse(val, top, arg):
+
+    intval = int(val)
+
+    if top[0] == "M":
+        intval = intval / (10 ** int(arg))
+       intval = intval % 10
+        argval = top[2]
+    elif top[0] == "O":
+        argval = int(cmd_opcodes.get(arg, arg))
+    else:
+        argval = int(arg)
+
+    # progress("%d %s %d" %(intval, top[1], argval))
+
+    if top[1] == "eq" and intval == argval:
+       return 1
+    if top[1] == "lt" and intval < argval:
+        return 1
+    if top[1] == "gt" and intval > argval:
+       return 1
+    return 0
+
+# Parse the commandline
+try:
+    (options, arguments) = getopt.getopt(sys.argv[1:],'chqt')
+except getopt.GetoptError, ex:
+    usage()
+    sys.exit(1)
+
+# Parse commandline options
+for option, value in options:
+    if option == "-c":
+        comments = 1
+    elif option == "-q":
+        quiet = 1
+    elif option == "-t":
+        test = 1
+    elif option == '-h':
+        usage()
+        sys.exit(0)
+
+# Select the input source
+if arguments:
+    try:
+        fd = open(arguments[0])
+    except Exception,ex:
+        sys.stderr.write("File not found %s\n" %(arguments[0]))
+        sys.exit(1)
+else:
+    fd = sys.stdin
+
+linenr = 0
+
+# Read the test patterns
+while 1:
+
+    linenr = linenr + 1
+    line = fd.readline()
+    if not len(line):
+        break
+
+    line = line.strip()
+    parts = line.split(":")
+
+    if not parts or len(parts) < 1:
+        continue
+
+    if len(parts[0]) == 0:
+        continue
+
+    if parts[0].startswith("#"):
+       if comments > 1:
+           progress(line)
+       continue
+
+    if comments == 1:
+       comments = 2
+
+    progress(line)
+
+    cmd = parts[0].strip().lower()
+    opc = parts[1].strip().lower()
+    tid = parts[2].strip()
+    dat = parts[3].strip()
+
+    try:
+        # Test or wait for a status value
+        if cmd == "t" or cmd == "w":
+            testop = test_opcodes[opc]
+
+            fname = "%s%s%s" %(sysfsprefix, tid, statusfile)
+            if test:
+               print fname
+                continue
+
+            while 1:
+                query = 1
+                fsta = open(fname, 'r')
+                status = fsta.readline().strip()
+                fsta.close()
+                stat = status.split(",")
+                for s in stat:
+                   s = s.strip()
+                    if s.startswith(testop[0]):
+                        # Seperate status value
+                        val = s[2:].strip()
+                        query = analyse(val, testop, dat)
+                        break
+                if query or cmd == "t":
+                    break
+
+            progress("   " + status)
+
+            if not query:
+                sys.stderr.write("Test failed in line %d\n" %(linenr))
+               sys.exit(1)
+
+        # Issue a command to the tester
+        elif cmd == "c":
+            cmdnr = cmd_opcodes[opc]
+            # Build command string and sys filename
+            cmdstr = "%s:%s" %(cmdnr, dat)
+            fname = "%s%s%s" %(sysfsprefix, tid, commandfile)
+            if test:
+               print fname
+                continue
+            fcmd = open(fname, 'w')
+            fcmd.write(cmdstr)
+            fcmd.close()
+
+    except Exception,ex:
+       sys.stderr.write(str(ex))
+        sys.stderr.write("\nSyntax error in line %d\n" %(linenr))
+        if not test:
+            fd.close()
+            sys.exit(1)
+
+# Normal exit pass
+print "Pass"
+sys.exit(0)
+
+
diff --git a/scripts/rt-tester/t2-l1-2rt-sameprio.tst b/scripts/rt-tester/t2-l1-2rt-sameprio.tst
new file mode 100644 (file)
index 0000000..8821f27
--- /dev/null
@@ -0,0 +1,99 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       0
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 2 threads 1 lock
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedfifo:          0:      80
+C: schedfifo:          1:      80
+
+# T0 lock L0
+C: locknowait:         0:      0
+C: locknowait:         1:      0
+W: locked:             0:      0
+W: blocked:            1:      0
+T: prioeq:             0:      80
+
+# T0 unlock L0
+C: unlock:             0:      0
+W: locked:             1:      0
+
+# Verify T0
+W: unlocked:           0:      0
+T: prioeq:             0:      80
+
+# Unlock
+C: unlock:             1:      0
+W: unlocked:           1:      0
+
+# T1,T0 lock L0
+C: locknowait:         1:      0
+C: locknowait:         0:      0
+W: locked:             1:      0
+W: blocked:            0:      0
+T: prioeq:             1:      80
+
+# T1 unlock L0
+C: unlock:             1:      0
+W: locked:             0:      0
+
+# Verify T1
+W: unlocked:           1:      0
+T: prioeq:             1:      80
+
+# Unlock and exit
+C: unlock:             0:      0
+W: unlocked:           0:      0
+
diff --git a/scripts/rt-tester/t2-l1-pi.tst b/scripts/rt-tester/t2-l1-pi.tst
new file mode 100644 (file)
index 0000000..cde1f18
--- /dev/null
@@ -0,0 +1,82 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       0
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 2 threads 1 lock with priority inversion
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedfifo:          1:      80
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: locknowait:         1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      80
+
+# T0 unlock L0
+C: unlock:             0:      0
+W: locked:             1:      0
+
+# Verify T1
+W: unlocked:           0:      0
+T: priolt:             0:      1
+
+# Unlock and exit
+C: unlock:             1:      0
+W: unlocked:           1:      0
+
diff --git a/scripts/rt-tester/t2-l1-signal.tst b/scripts/rt-tester/t2-l1-signal.tst
new file mode 100644 (file)
index 0000000..3ab0bfc
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       0
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 2 threads 1 lock with priority inversion
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedother:         1:      0
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: lockintnowait:      1:      0
+W: blocked:            1:      0
+
+# Interrupt T1
+C: signal:             1:      0
+W: unlocked:           1:      0
+T: opcodeeq:           1:      -4
+
+# Unlock and exit
+C: unlock:             0:      0
+W: unlocked:           0:      0
diff --git a/scripts/rt-tester/t2-l2-2rt-deadlock.tst b/scripts/rt-tester/t2-l2-2rt-deadlock.tst
new file mode 100644 (file)
index 0000000..f4b5d5d
--- /dev/null
@@ -0,0 +1,89 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       0
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 2 threads 2 lock
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedfifo:          0:      80
+C: schedfifo:          1:      80
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L1
+C: locknowait:         1:      1
+W: locked:             1:      1
+
+# T0 lock L1
+C: lockintnowait:      0:      1
+W: blocked:            0:      1
+
+# T1 lock L0
+C: lockintnowait:      1:      0
+W: blocked:            1:      0
+
+# Make deadlock go away
+C: signal:             1:      0
+W: unlocked:           1:      0
+C: signal:             0:      0
+W: unlocked:           0:      1
+
+# Unlock and exit
+C: unlock:             0:      0
+W: unlocked:           0:      0
+C: unlock:             1:      1
+W: unlocked:           1:      1
+
diff --git a/scripts/rt-tester/t3-l1-pi-1rt.tst b/scripts/rt-tester/t3-l1-pi-1rt.tst
new file mode 100644 (file)
index 0000000..63440ca
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 3 threads 1 lock PI
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedother:         1:      0
+C: schedfifo:          2:      82
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: locknowait:         1:      0
+W: blocked:            1:      0
+T: priolt:             0:      1
+
+# T2 lock L0
+C: locknowait:         2:      0
+W: blocked:            2:      0
+T: prioeq:             0:      82
+
+# T0 unlock L0
+C: unlock:             0:      0
+
+# Wait until T2 got the lock
+W: locked:             2:      0
+W: unlocked:           0:      0
+T: priolt:             0:      1
+
+# T2 unlock L0
+C: unlock:             2:      0
+
+W: unlocked:           2:      0
+W: locked:             1:      0
+
+C: unlock:             1:      0
+W: unlocked:           1:      0
diff --git a/scripts/rt-tester/t3-l1-pi-2rt.tst b/scripts/rt-tester/t3-l1-pi-2rt.tst
new file mode 100644 (file)
index 0000000..e5816fe
--- /dev/null
@@ -0,0 +1,93 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 3 threads 1 lock PI
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedfifo:          1:      81
+C: schedfifo:          2:      82
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: locknowait:         1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      81
+
+# T2 lock L0
+C: locknowait:         2:      0
+W: blocked:            2:      0
+T: prioeq:             0:      82
+T: prioeq:             1:      81
+
+# T0 unlock L0
+C: unlock:             0:      0
+
+# Wait until T2 got the lock
+W: locked:             2:      0
+W: unlocked:           0:      0
+T: priolt:             0:      1
+
+# T2 unlock L0
+C: unlock:             2:      0
+
+W: unlocked:           2:      0
+W: locked:             1:      0
+
+C: unlock:             1:      0
+W: unlocked:           1:      0
diff --git a/scripts/rt-tester/t3-l1-pi-3rt.tst b/scripts/rt-tester/t3-l1-pi-3rt.tst
new file mode 100644 (file)
index 0000000..718b82b
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 3 threads 1 lock PI
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedfifo:          0:      80
+C: schedfifo:          1:      81
+C: schedfifo:          2:      82
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: locknowait:         1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      81
+
+# T2 lock L0
+C: locknowait:         2:      0
+W: blocked:            2:      0
+T: prioeq:             0:      82
+
+# T0 unlock L0
+C: unlock:             0:      0
+
+# Wait until T2 got the lock
+W: locked:             2:      0
+W: unlocked:           0:      0
+T: prioeq:             0:      80
+
+# T2 unlock L0
+C: unlock:             2:      0
+
+W: locked:             1:      0
+W: unlocked:           2:      0
+
+C: unlock:             1:      0
+W: unlocked:           1:      0
diff --git a/scripts/rt-tester/t3-l1-pi-signal.tst b/scripts/rt-tester/t3-l1-pi-signal.tst
new file mode 100644 (file)
index 0000000..c6e2135
--- /dev/null
@@ -0,0 +1,98 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+# Reset event counter
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set priorities
+C: schedother:         0:      0
+C: schedfifo:          1:      80
+C: schedfifo:          2:      81
+
+# T0 lock L0
+C: lock:               0:      0
+W: locked:             0:      0
+
+# T1 lock L0, no wait in the wakeup path
+C: locknowait:         1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      80
+T: prioeq:             1:      80
+
+# T2 lock L0 interruptible, no wait in the wakeup path
+C: lockintnowait:      2:      0
+W: blocked:            2:      0
+T: prioeq:             0:      81
+T: prioeq:             1:      80
+
+# Interrupt T2
+C: signal:             2:      2
+W: unlocked:           2:      0
+T: prioeq:             1:      80
+T: prioeq:             0:      80
+
+T: locked:             0:      0
+T: blocked:            1:      0
+
+# T0 unlock L0
+C: unlock:             0:      0
+
+# Wait until T1 has locked L0 and exit
+W: locked:             1:      0
+W: unlocked:           0:      0
+T: priolt:             0:      1
+
+C: unlock:             1:      0
+W: unlocked:           1:      0
+
+
+
diff --git a/scripts/rt-tester/t3-l1-pi-steal.tst b/scripts/rt-tester/t3-l1-pi-steal.tst
new file mode 100644 (file)
index 0000000..f53749d
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 3 threads 1 lock PI steal pending ownership
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedfifo:          1:      80
+C: schedfifo:          2:      81
+
+# T0 lock L0
+C: lock:               0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: lock:               1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      80
+
+# T0 unlock L0
+C: unlock:             0:      0
+
+# Wait until T1 is in the wakeup loop
+W: blockedwake:                1:      0
+T: priolt:             0:      1
+
+# T2 lock L0
+C: lock:               2:      0
+# T1 leave wakeup loop
+C: lockcont:           1:      0
+
+# T2 must have the lock and T1 must be blocked
+W: locked:             2:      0
+W: blocked:            1:      0
+
+# T2 unlock L0
+C: unlock:             2:      0
+
+# Wait until T1 is in the wakeup loop and let it run
+W: blockedwake:                1:      0
+C: lockcont:           1:      0
+W: locked:             1:      0
+C: unlock:             1:      0
+W: unlocked:           1:      0
diff --git a/scripts/rt-tester/t3-l2-pi.tst b/scripts/rt-tester/t3-l2-pi.tst
new file mode 100644 (file)
index 0000000..cdc3e4f
--- /dev/null
@@ -0,0 +1,92 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 3 threads 2 lock PI
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedother:         1:      0
+C: schedfifo:          2:      82
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L0
+C: locknowait:         1:      0
+W: blocked:            1:      0
+T: priolt:             0:      1
+
+# T2 lock L0
+C: locknowait:         2:      0
+W: blocked:            2:      0
+T: prioeq:             0:      82
+
+# T0 unlock L0
+C: unlock:             0:      0
+
+# Wait until T2 got the lock
+W: locked:             2:      0
+W: unlocked:           0:      0
+T: priolt:             0:      1
+
+# T2 unlock L0
+C: unlock:             2:      0
+
+W: unlocked:           2:      0
+W: locked:             1:      0
+
+C: unlock:             1:      0
+W: unlocked:           1:      0
diff --git a/scripts/rt-tester/t4-l2-pi-deboost.tst b/scripts/rt-tester/t4-l2-pi-deboost.tst
new file mode 100644 (file)
index 0000000..baa1413
--- /dev/null
@@ -0,0 +1,123 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 4 threads 2 lock PI
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedother:         1:      0
+C: schedfifo:          2:      82
+C: schedfifo:          3:      83
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L1
+C: locknowait:         1:      1
+W: locked:             1:      1
+
+# T3 lock L0
+C: lockintnowait:      3:      0
+W: blocked:            3:      0
+T: prioeq:             0:      83
+
+# T0 lock L1
+C: lock:               0:      1
+W: blocked:            0:      1
+T: prioeq:             1:      83
+
+# T1 unlock L1
+C: unlock:             1:      1
+
+# Wait until T0 is in the wakeup code
+W: blockedwake:                0:      1
+
+# Verify that T1 is unboosted
+W: unlocked:           1:      1
+T: priolt:             1:      1
+
+# T2 lock L1 (T0 is boosted and pending owner !)
+C: locknowait:         2:      1
+W: blocked:            2:      1
+T: prioeq:             0:      83
+
+# Interrupt T3 and wait until T3 returned
+C: signal:             3:      0
+W: unlocked:           3:      0
+
+# Verify prio of T0 (still pending owner,
+# but T2 is enqueued due to the previous boost by T3
+T: prioeq:             0:      82
+
+# Let T0 continue
+C: lockcont:           0:      1
+W: locked:             0:      1
+
+# Unlock L1 and let T2 get L1
+C: unlock:             0:      1
+W: locked:             2:      1
+
+# Verify that T0 is unboosted
+W: unlocked:           0:      1
+T: priolt:             0:      1
+
+# Unlock everything and exit
+C: unlock:             2:      1
+W: unlocked:           2:      1
+
+C: unlock:             0:      0
+W: unlocked:           0:      0
+
diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst
new file mode 100644 (file)
index 0000000..e6ec0c8
--- /dev/null
@@ -0,0 +1,183 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 5 threads 4 lock PI - modify priority of blocked threads
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedfifo:          1:      81
+C: schedfifo:          2:      82
+C: schedfifo:          3:      83
+C: schedfifo:          4:      84
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L1
+C: locknowait:         1:      1
+W: locked:             1:      1
+
+# T1 lock L0
+C: lockintnowait:      1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      81
+
+# T2 lock L2
+C: locknowait:         2:      2
+W: locked:             2:      2
+
+# T2 lock L1
+C: lockintnowait:      2:      1
+W: blocked:            2:      1
+T: prioeq:             0:      82
+T: prioeq:             1:      82
+
+# T3 lock L3
+C: locknowait:         3:      3
+W: locked:             3:      3
+
+# T3 lock L2
+C: lockintnowait:      3:      2
+W: blocked:            3:      2
+T: prioeq:             0:      83
+T: prioeq:             1:      83
+T: prioeq:             2:      83
+
+# T4 lock L3
+C: lockintnowait:      4:      3
+W: blocked:            4:      3
+T: prioeq:             0:      84
+T: prioeq:             1:      84
+T: prioeq:             2:      84
+T: prioeq:             3:      84
+
+# Reduce prio of T4
+C: schedfifo:          4:      80
+T: prioeq:             0:      83
+T: prioeq:             1:      83
+T: prioeq:             2:      83
+T: prioeq:             3:      83
+T: prioeq:             4:      80
+
+# Increase prio of T4
+C: schedfifo:          4:      84
+T: prioeq:             0:      84
+T: prioeq:             1:      84
+T: prioeq:             2:      84
+T: prioeq:             3:      84
+T: prioeq:             4:      84
+
+# Reduce prio of T3
+C: schedfifo:          3:      80
+T: prioeq:             0:      84
+T: prioeq:             1:      84
+T: prioeq:             2:      84
+T: prioeq:             3:      84
+T: prioeq:             4:      84
+
+# Increase prio of T3
+C: schedfifo:          3:      85
+T: prioeq:             0:      85
+T: prioeq:             1:      85
+T: prioeq:             2:      85
+T: prioeq:             3:      85
+T: prioeq:             4:      84
+
+# Reduce prio of T3
+C: schedfifo:          3:      83
+T: prioeq:             0:      84
+T: prioeq:             1:      84
+T: prioeq:             2:      84
+T: prioeq:             3:      84
+T: prioeq:             4:      84
+
+# Signal T4
+C: signal:             4:      0
+W: unlocked:           4:      3
+T: prioeq:             0:      83
+T: prioeq:             1:      83
+T: prioeq:             2:      83
+T: prioeq:             3:      83
+
+# Signal T3
+C: signal:             3:      0
+W: unlocked:           3:      2
+T: prioeq:             0:      82
+T: prioeq:             1:      82
+T: prioeq:             2:      82
+
+# Signal T2
+C: signal:             2:      0
+W: unlocked:           2:      1
+T: prioeq:             0:      81
+T: prioeq:             1:      81
+
+# Signal T1
+C: signal:             1:      0
+W: unlocked:           1:      0
+T: priolt:             0:      1
+
+# Unlock and exit
+C: unlock:             3:      3
+C: unlock:             2:      2
+C: unlock:             1:      1
+C: unlock:             0:      0
+
+W: unlocked:           3:      3
+W: unlocked:           2:      2
+W: unlocked:           1:      1
+W: unlocked:           0:      0
+
diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst
new file mode 100644 (file)
index 0000000..ca64f8b
--- /dev/null
@@ -0,0 +1,143 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode       opcode argument
+# schedother   nice value
+# schedfifo    priority
+# lock         lock nr (0-7)
+# locknowait   lock nr (0-7)
+# lockint      lock nr (0-7)
+# lockintnowait        lock nr (0-7)
+# lockcont     lock nr (0-7)
+# unlock       lock nr (0-7)
+# lockbkl      lock nr (0-7)
+# unlockbkl    lock nr (0-7)
+# signal       thread to signal (0-7)
+# reset                0
+# resetevent   0
+#
+# Tests / Wait
+#
+# opcode       opcode argument
+#
+# prioeq       priority
+# priolt       priority
+# priogt       priority
+# nprioeq      normal priority
+# npriolt      normal priority
+# npriogt      normal priority
+# locked       lock nr (0-7)
+# blocked      lock nr (0-7)
+# blockedwake  lock nr (0-7)
+# unlocked     lock nr (0-7)
+# lockedbkl    dont care
+# blockedbkl   dont care
+# unlockedbkl  dont care
+# opcodeeq     command opcode or number
+# opcodelt     number
+# opcodegt     number
+# eventeq      number
+# eventgt      number
+# eventlt      number
+
+#
+# 5 threads 4 lock PI
+#
+C: resetevent:         0:      0
+W: opcodeeq:           0:      0
+
+# Set schedulers
+C: schedother:         0:      0
+C: schedfifo:          1:      81
+C: schedfifo:          2:      82
+C: schedfifo:          3:      83
+C: schedfifo:          4:      84
+
+# T0 lock L0
+C: locknowait:         0:      0
+W: locked:             0:      0
+
+# T1 lock L1
+C: locknowait:         1:      1
+W: locked:             1:      1
+
+# T1 lock L0
+C: lockintnowait:      1:      0
+W: blocked:            1:      0
+T: prioeq:             0:      81
+
+# T2 lock L2
+C: locknowait:         2:      2
+W: locked:             2:      2
+
+# T2 lock L1
+C: lockintnowait:      2:      1
+W: blocked:            2:      1
+T: prioeq:             0:      82
+T: prioeq:             1:      82
+
+# T3 lock L3
+C: locknowait:         3:      3
+W: locked:             3:      3
+
+# T3 lock L2
+C: lockintnowait:      3:      2
+W: blocked:            3:      2
+T: prioeq:             0:      83
+T: prioeq:             1:      83
+T: prioeq:             2:      83
+
+# T4 lock L3
+C: lockintnowait:      4:      3
+W: blocked:            4:      3
+T: prioeq:             0:      84
+T: prioeq:             1:      84
+T: prioeq:             2:      84
+T: prioeq:             3:      84
+
+# Signal T4
+C: signal:             4:      0
+W: unlocked:           4:      3
+T: prioeq:             0:      83
+T: prioeq:             1:      83
+T: prioeq:             2:      83
+T: prioeq:             3:      83
+
+# Signal T3
+C: signal:             3:      0
+W: unlocked:           3:      2
+T: prioeq:             0:      82
+T: prioeq:             1:      82
+T: prioeq:             2:      82
+
+# Signal T2
+C: signal:             2:      0
+W: unlocked:           2:      1
+T: prioeq:             0:      81
+T: prioeq:             1:      81
+
+# Signal T1
+C: signal:             1:      0
+W: unlocked:           1:      0
+T: priolt:             0:      1
+
+# Unlock and exit
+C: unlock:             3:      3
+C: unlock:             2:      2
+C: unlock:             1:      1
+C: unlock:             0:      0
+
+W: unlocked:           3:      3
+W: unlocked:           2:      2
+W: unlocked:           1:      1
+W: unlocked:           0:      0
+
diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig
new file mode 100644 (file)
index 0000000..2f4334d
--- /dev/null
@@ -0,0 +1,18 @@
+menu "Apple Onboard Audio driver"
+       depends on SND!=n && PPC
+
+config SND_AOA
+       tristate "Apple Onboard Audio driver"
+       depends on SND
+       select SND_PCM
+       ---help---
+       This option enables the new driver for the various
+       Apple Onboard Audio components.
+
+source "sound/aoa/fabrics/Kconfig"
+
+source "sound/aoa/codecs/Kconfig"
+
+source "sound/aoa/soundbus/Kconfig"
+
+endmenu
diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile
new file mode 100644 (file)
index 0000000..a8c037f
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_SND_AOA) += core/
+obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/
+obj-$(CONFIG_SND_AOA) += fabrics/
+obj-$(CONFIG_SND_AOA) += codecs/
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h
new file mode 100644 (file)
index 0000000..3a61f31
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Apple Onboard Audio GPIO definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#ifndef __AOA_GPIO_H
+#define __AOA_GPIO_H
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <asm/prom.h>
+
+typedef void (*notify_func_t)(void *data);
+
+enum notify_type {
+       AOA_NOTIFY_HEADPHONE,
+       AOA_NOTIFY_LINE_IN,
+       AOA_NOTIFY_LINE_OUT,
+};
+
+struct gpio_runtime;
+struct gpio_methods {
+       /* for initialisation/de-initialisation of the GPIO layer */
+       void (*init)(struct gpio_runtime *rt);
+       void (*exit)(struct gpio_runtime *rt);
+
+       /* turn off headphone, speakers, lineout */
+       void (*all_amps_off)(struct gpio_runtime *rt);
+       /* turn headphone, speakers, lineout back to previous setting */
+       void (*all_amps_restore)(struct gpio_runtime *rt);
+
+       void (*set_headphone)(struct gpio_runtime *rt, int on);
+       void (*set_speakers)(struct gpio_runtime *rt, int on);
+       void (*set_lineout)(struct gpio_runtime *rt, int on);
+
+       int (*get_headphone)(struct gpio_runtime *rt);
+       int (*get_speakers)(struct gpio_runtime *rt);
+       int (*get_lineout)(struct gpio_runtime *rt);
+
+       void (*set_hw_reset)(struct gpio_runtime *rt, int on);
+
+       /* use this to be notified of any events. The notification
+        * function is passed the data, and is called in process
+        * context by the use of schedule_work.
+        * The interface for it is that setting a function to NULL
+        * removes it, and they return 0 if the operation succeeded,
+        * and -EBUSY if the notification is already assigned by
+        * someone else. */
+       int (*set_notify)(struct gpio_runtime *rt,
+                         enum notify_type type,
+                         notify_func_t notify,
+                         void *data);
+       /* returns 0 if not plugged in, 1 if plugged in
+        * or a negative error code */
+       int (*get_detect)(struct gpio_runtime *rt,
+                         enum notify_type type);
+};
+
+struct gpio_notification {
+       notify_func_t notify;
+       void *data;
+       void *gpio_private;
+       struct work_struct work;
+       struct mutex mutex;
+};
+
+struct gpio_runtime {
+       /* to be assigned by fabric */
+       struct device_node *node;
+       /* since everyone needs this pointer anyway... */
+       struct gpio_methods *methods;
+       /* to be used by the gpio implementation */
+       int implementation_private;
+       struct gpio_notification headphone_notify;
+       struct gpio_notification line_in_notify;
+       struct gpio_notification line_out_notify;
+};
+
+#endif /* __AOA_GPIO_H */
diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h
new file mode 100644 (file)
index 0000000..378ef1e
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Apple Onboard Audio definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#ifndef __AOA_H
+#define __AOA_H
+#include <asm/prom.h>
+#include <linux/module.h>
+/* So apparently there's a reason for requiring driver.h to be included first! */
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/asound.h>
+#include <sound/control.h>
+#include "aoa-gpio.h"
+#include "soundbus/soundbus.h"
+
+#define MAX_CODEC_NAME_LEN     32
+
+struct aoa_codec {
+       char    name[MAX_CODEC_NAME_LEN];
+
+       struct module *owner;
+
+       /* called when the fabric wants to init this codec.
+        * Do alsa card manipulations from here. */
+       int (*init)(struct aoa_codec *codec);
+
+       /* called when the fabric is done with the codec.
+        * The alsa card will be cleaned up so don't bother. */
+       void (*exit)(struct aoa_codec *codec);
+
+       /* May be NULL, but can be used by the fabric.
+        * Refcounting is the codec driver's responsibility */
+       struct device_node *node;
+
+       /* assigned by fabric before init() is called, points
+        * to the soundbus device. Cannot be NULL. */
+       struct soundbus_dev *soundbus_dev;
+
+       /* assigned by the fabric before init() is called, points
+        * to the fabric's gpio runtime record for the relevant
+        * device. */
+       struct gpio_runtime *gpio;
+
+       /* assigned by the fabric before init() is called, contains
+        * a codec specific bitmask of what outputs and inputs are
+        * actually connected */
+       u32 connected;
+
+       /* data the fabric can associate with this structure */
+       void *fabric_data;
+
+       /* private! */
+       struct list_head list;
+       struct aoa_fabric *fabric;
+};
+
+/* return 0 on success */
+extern int
+aoa_codec_register(struct aoa_codec *codec);
+extern void
+aoa_codec_unregister(struct aoa_codec *codec);
+
+#define MAX_LAYOUT_NAME_LEN    32
+
+struct aoa_fabric {
+       char    name[MAX_LAYOUT_NAME_LEN];
+
+       struct module *owner;
+
+       /* once codecs register, they are passed here after.
+        * They are of course not initialised, since the
+        * fabric is responsible for initialising some fields
+        * in the codec structure! */
+       int (*found_codec)(struct aoa_codec *codec);
+       /* called for each codec when it is removed,
+        * also in the case that aoa_fabric_unregister
+        * is called and all codecs are removed
+        * from this fabric.
+        * Also called if found_codec returned 0 but
+        * the codec couldn't initialise. */
+       void (*remove_codec)(struct aoa_codec *codec);
+       /* If found_codec returned 0, and the codec
+        * could be initialised, this is called. */
+       void (*attached_codec)(struct aoa_codec *codec);
+};
+
+/* return 0 on success, -EEXIST if another fabric is
+ * registered, -EALREADY if the same fabric is registered.
+ * Passing NULL can be used to test for the presence
+ * of another fabric, if -EALREADY is returned there is
+ * no other fabric present.
+ * In the case that the function returns -EALREADY
+ * and the fabric passed is not NULL, all codecs
+ * that are not assigned yet are passed to the fabric
+ * again for reconsideration. */
+extern int
+aoa_fabric_register(struct aoa_fabric *fabric);
+
+/* it is vital to call this when the fabric exits!
+ * When calling, the remove_codec will be called
+ * for all codecs, unless it is NULL. */
+extern void
+aoa_fabric_unregister(struct aoa_fabric *fabric);
+
+/* if for some reason you want to get rid of a codec
+ * before the fabric is removed, use this.
+ * Note that remove_codec is called for it! */
+extern void
+aoa_fabric_unlink_codec(struct aoa_codec *codec);
+
+/* alsa help methods */
+struct aoa_card {
+       struct snd_card *alsa_card;
+};
+        
+extern int aoa_snd_device_new(snd_device_type_t type,
+       void * device_data, struct snd_device_ops * ops);
+extern struct snd_card *aoa_get_card(void);
+extern int aoa_snd_ctl_add(struct snd_kcontrol* control);
+
+/* GPIO stuff */
+extern struct gpio_methods *pmf_gpio_methods;
+extern struct gpio_methods *ftr_gpio_methods;
+/* extern struct gpio_methods *map_gpio_methods; */
+
+#endif /* __AOA_H */
diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig
new file mode 100644 (file)
index 0000000..90cf58f
--- /dev/null
@@ -0,0 +1,32 @@
+config SND_AOA_ONYX
+       tristate "support Onyx chip"
+       depends on SND_AOA
+       ---help---
+       This option enables support for the Onyx (pcm3052)
+       codec chip found in the latest Apple machines
+       (most of those with digital audio output).
+
+#config SND_AOA_TOPAZ
+#      tristate "support Topaz chips"
+#      depends on SND_AOA
+#      ---help---
+#      This option enables support for the Topaz (CS84xx)
+#      codec chips found in the latest Apple machines,
+#      these chips do the digital input and output on
+#      some PowerMacs.
+
+config SND_AOA_TAS
+       tristate "support TAS chips"
+       depends on SND_AOA
+       ---help---
+       This option enables support for the tas chips
+       found in a lot of Apple Machines, especially
+       iBooks and PowerBooks without digital.
+
+config SND_AOA_TOONIE
+       tristate "support Toonie chip"
+       depends on SND_AOA
+       ---help---
+       This option enables support for the toonie codec
+       found in the Mac Mini. If you have a Mac Mini and
+       want to hear sound, select this option.
diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile
new file mode 100644 (file)
index 0000000..31cbe68
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o
+obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o
+obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
new file mode 100644 (file)
index 0000000..0b76507
--- /dev/null
@@ -0,0 +1,1113 @@
+/*
+ * Apple Onboard Audio driver for Onyx codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This is a driver for the pcm3052 codec chip (codenamed Onyx)
+ * that is present in newer Apple hardware (with digital output).
+ *
+ * The Onyx codec has the following connections (listed by the bit
+ * to be used in aoa_codec.connected):
+ *  0: analog output
+ *  1: digital output
+ *  2: line input
+ *  3: microphone input
+ * Note that even though I know of no machine that has for example
+ * the digital output connected but not the analog, I have handled
+ * all the different cases in the code so that this driver may serve
+ * as a good example of what to do.
+ *
+ * NOTE: This driver assumes that there's at most one chip to be
+ *      used with one alsa card, in form of creating all kinds
+ *      of mixer elements without regard for their existence.
+ *      But snd-aoa assumes that there's at most one card, so
+ *      this means you can only have one onyx on a system. This
+ *      should probably be fixed by changing the assumption of
+ *      having just a single card on a system, and making the
+ *      'card' pointer accessible to anyone who needs it instead
+ *      of hiding it in the aoa_snd_* functions...
+ *
+ */
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
+
+#include "snd-aoa-codec-onyx.h"
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+
+#define PFX "snd-aoa-codec-onyx: "
+
+struct onyx {
+       /* cache registers 65 to 80, they are write-only! */
+       u8                      cache[16];
+       struct i2c_client       i2c;
+       struct aoa_codec        codec;
+       u32                     initialised:1,
+                               spdif_locked:1,
+                               analog_locked:1,
+                               original_mute:2;
+       int                     open_count;
+       struct codec_info       *codec_info;
+
+       /* mutex serializes concurrent access to the device
+        * and this structure.
+        */
+       struct mutex mutex;
+};
+#define codec_to_onyx(c) container_of(c, struct onyx, codec)
+
+/* both return 0 if all ok, else on error */
+static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
+{
+       s32 v;
+
+       if (reg != ONYX_REG_CONTROL) {
+               *value = onyx->cache[reg-FIRSTREGISTER];
+               return 0;
+       }
+       v = i2c_smbus_read_byte_data(&onyx->i2c, reg);
+       if (v < 0)
+               return -1;
+       *value = (u8)v;
+       onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value;
+       return 0;
+}
+
+static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
+{
+       int result;
+
+       result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value);
+       if (!result)
+               onyx->cache[reg-FIRSTREGISTER] = value;
+       return result;
+}
+
+/* alsa stuff */
+
+static int onyx_dev_register(struct snd_device *dev)
+{
+       return 0;
+}
+
+static struct snd_device_ops ops = {
+       .dev_register = onyx_dev_register,
+};
+
+/* this is necessary because most alsa mixer programs
+ * can't properly handle the negative range */
+#define VOLUME_RANGE_SHIFT     128
+
+static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT;
+       uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT;
+       return 0;
+}
+
+static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       s8 l, r;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
+       onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
+       mutex_unlock(&onyx->mutex);
+
+       ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
+       ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
+
+       return 0;
+}
+
+static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       s8 l, r;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
+       onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
+
+       if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
+           r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
+               mutex_unlock(&onyx->mutex);
+               return 0;
+       }
+
+       onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
+                           ucontrol->value.integer.value[0]
+                            - VOLUME_RANGE_SHIFT);
+       onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
+                           ucontrol->value.integer.value[1]
+                            - VOLUME_RANGE_SHIFT);
+       mutex_unlock(&onyx->mutex);
+
+       return 1;
+}
+
+static struct snd_kcontrol_new volume_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Master Playback Volume",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = onyx_snd_vol_info,
+       .get = onyx_snd_vol_get,
+       .put = onyx_snd_vol_put,
+};
+
+/* like above, this is necessary because a lot
+ * of alsa mixer programs don't handle ranges
+ * that don't start at 0 properly.
+ * even alsamixer is one of them... */
+#define INPUTGAIN_RANGE_SHIFT  (-3)
+
+static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT;
+       uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT;
+       return 0;
+}
+
+static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 ig;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
+       mutex_unlock(&onyx->mutex);
+
+       ucontrol->value.integer.value[0] =
+               (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
+
+       return 0;
+}
+
+static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 v, n;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+       n = v;
+       n &= ~ONYX_ADC_PGA_GAIN_MASK;
+       n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
+               & ONYX_ADC_PGA_GAIN_MASK;
+       onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
+       mutex_unlock(&onyx->mutex);
+
+       return n != v;
+}
+
+static struct snd_kcontrol_new inputgain_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Master Capture Volume",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = onyx_snd_inputgain_info,
+       .get = onyx_snd_inputgain_get,
+       .put = onyx_snd_inputgain_put,
+};
+
+static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       static char *texts[] = { "Line-In", "Microphone" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item > 1)
+               uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       s8 v;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+       mutex_unlock(&onyx->mutex);
+
+       ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
+
+       return 0;
+}
+
+static void onyx_set_capture_source(struct onyx *onyx, int mic)
+{
+       s8 v;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+       v &= ~ONYX_ADC_INPUT_MIC;
+       if (mic)
+               v |= ONYX_ADC_INPUT_MIC;
+       onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
+       mutex_unlock(&onyx->mutex);
+}
+
+static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
+                               ucontrol->value.enumerated.item[0]);
+       return 1;
+}
+
+static struct snd_kcontrol_new capture_source_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       /* If we name this 'Input Source', it properly shows up in
+        * alsamixer as a selection, * but it's shown under the 
+        * 'Playback' category.
+        * If I name it 'Capture Source', it shows up in strange
+        * ways (two bools of which one can be selected at a
+        * time) but at least it's shown in the 'Capture'
+        * category.
+        * I was told that this was due to backward compatibility,
+        * but I don't understand then why the mangling is *not*
+        * done when I name it "Input Source".....
+        */
+       .name = "Capture Source",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = onyx_snd_capture_source_info,
+       .get = onyx_snd_capture_source_get,
+       .put = onyx_snd_capture_source_put,
+};
+
+static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 c;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
+       mutex_unlock(&onyx->mutex);
+
+       ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
+       ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
+
+       return 0;
+}
+
+static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 v = 0, c = 0;
+       int err = -EBUSY;
+
+       mutex_lock(&onyx->mutex);
+       if (onyx->analog_locked)
+               goto out_unlock;
+
+       onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+       c = v;
+       c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT);
+       if (!ucontrol->value.integer.value[0])
+               c |= ONYX_MUTE_LEFT;
+       if (!ucontrol->value.integer.value[1])
+               c |= ONYX_MUTE_RIGHT;
+       err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
+
+ out_unlock:
+       mutex_unlock(&onyx->mutex);
+
+       return !err ? (v != c) : err;
+}
+
+static struct snd_kcontrol_new mute_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Master Playback Switch",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = onyx_snd_mute_info,
+       .get = onyx_snd_mute_get,
+       .put = onyx_snd_mute_put,
+};
+
+
+static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+#define FLAG_POLARITY_INVERT   1
+#define FLAG_SPDIFLOCK         2
+
+static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 c;
+       long int pv = kcontrol->private_value;
+       u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
+       u8 address = (pv >> 8) & 0xff;
+       u8 mask = pv & 0xff;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, address, &c);
+       mutex_unlock(&onyx->mutex);
+
+       ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
+
+       return 0;
+}
+
+static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 v = 0, c = 0;
+       int err;
+       long int pv = kcontrol->private_value;
+       u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
+       u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK;
+       u8 address = (pv >> 8) & 0xff;
+       u8 mask = pv & 0xff;
+
+       mutex_lock(&onyx->mutex);
+       if (spdiflock && onyx->spdif_locked) {
+               /* even if alsamixer doesn't care.. */
+               err = -EBUSY;
+               goto out_unlock;
+       }
+       onyx_read_register(onyx, address, &v);
+       c = v;
+       c &= ~(mask);
+       if (!!ucontrol->value.integer.value[0] ^ polarity)
+               c |= mask;
+       err = onyx_write_register(onyx, address, c);
+
+ out_unlock:
+       mutex_unlock(&onyx->mutex);
+
+       return !err ? (v != c) : err;
+}
+
+#define SINGLE_BIT(n, type, description, address, mask, flags)         \
+static struct snd_kcontrol_new n##_control = {                         \
+       .iface = SNDRV_CTL_ELEM_IFACE_##type,                           \
+       .name = description,                                            \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                      \
+       .info = onyx_snd_single_bit_info,                               \
+       .get = onyx_snd_single_bit_get,                                 \
+       .put = onyx_snd_single_bit_put,                                 \
+       .private_value = (flags << 16) | (address << 8) | mask          \
+}
+
+SINGLE_BIT(spdif,
+          MIXER,
+          SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
+          ONYX_REG_DIG_INFO4,
+          ONYX_SPDIF_ENABLE,
+          FLAG_SPDIFLOCK);
+SINGLE_BIT(ovr1,
+          MIXER,
+          "Oversampling Rate",
+          ONYX_REG_DAC_CONTROL,
+          ONYX_OVR1,
+          0);
+SINGLE_BIT(flt0,
+          MIXER,
+          "Fast Digital Filter Rolloff",
+          ONYX_REG_DAC_FILTER,
+          ONYX_ROLLOFF_FAST,
+          FLAG_POLARITY_INVERT);
+SINGLE_BIT(hpf,
+          MIXER,
+          "Highpass Filter",
+          ONYX_REG_ADC_HPF_BYPASS,
+          ONYX_HPF_DISABLE,
+          FLAG_POLARITY_INVERT);
+SINGLE_BIT(dm12,
+          MIXER,
+          "Digital De-Emphasis",
+          ONYX_REG_DAC_DEEMPH,
+          ONYX_DIGDEEMPH_CTRL,
+          0);
+
+static int onyx_spdif_info(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+       uinfo->count = 1;
+       return 0;
+}
+
+static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       /* datasheet page 30, all others are 0 */
+       ucontrol->value.iec958.status[0] = 0x3e;
+       ucontrol->value.iec958.status[1] = 0xff;
+
+       ucontrol->value.iec958.status[3] = 0x3f;
+       ucontrol->value.iec958.status[4] = 0x0f;
+       
+       return 0;
+}
+
+static struct snd_kcontrol_new onyx_spdif_mask = {
+       .access =       SNDRV_CTL_ELEM_ACCESS_READ,
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+       .info =         onyx_spdif_info,
+       .get =          onyx_spdif_mask_get,
+};
+
+static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 v;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
+       ucontrol->value.iec958.status[0] = v & 0x3e;
+
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v);
+       ucontrol->value.iec958.status[1] = v;
+
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
+       ucontrol->value.iec958.status[3] = v & 0x3f;
+
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+       ucontrol->value.iec958.status[4] = v & 0x0f;
+       mutex_unlock(&onyx->mutex);
+
+       return 0;
+}
+
+static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_value *ucontrol)
+{
+       struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+       u8 v;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
+       v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
+       onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
+
+       v = ucontrol->value.iec958.status[1];
+       onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v);
+
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
+       v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f);
+       onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v);
+
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+       v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
+       onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
+       mutex_unlock(&onyx->mutex);
+
+       return 1;
+}
+
+static struct snd_kcontrol_new onyx_spdif_ctrl = {
+       .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+       .info =         onyx_spdif_info,
+       .get =          onyx_spdif_get,
+       .put =          onyx_spdif_put,
+};
+
+/* our registers */
+
+static u8 register_map[] = {
+       ONYX_REG_DAC_ATTEN_LEFT,
+       ONYX_REG_DAC_ATTEN_RIGHT,
+       ONYX_REG_CONTROL,
+       ONYX_REG_DAC_CONTROL,
+       ONYX_REG_DAC_DEEMPH,
+       ONYX_REG_DAC_FILTER,
+       ONYX_REG_DAC_OUTPHASE,
+       ONYX_REG_ADC_CONTROL,
+       ONYX_REG_ADC_HPF_BYPASS,
+       ONYX_REG_DIG_INFO1,
+       ONYX_REG_DIG_INFO2,
+       ONYX_REG_DIG_INFO3,
+       ONYX_REG_DIG_INFO4
+};
+
+static u8 initial_values[ARRAY_SIZE(register_map)] = {
+       0x80, 0x80, /* muted */
+       ONYX_MRST | ONYX_SRST, /* but handled specially! */
+       ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
+       0, /* no deemphasis */
+       ONYX_DAC_FILTER_ALWAYS,
+       ONYX_OUTPHASE_INVERTED,
+       (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
+       ONYX_ADC_HPF_ALWAYS,
+       (1<<2), /* pcm audio */
+       2,      /* category: pcm coder */
+       0,      /* sampling frequency 44.1 kHz, clock accuracy level II */
+       1       /* 24 bit depth */
+};
+
+/* reset registers of chip, either to initial or to previous values */
+static int onyx_register_init(struct onyx *onyx)
+{
+       int i;
+       u8 val;
+       u8 regs[sizeof(initial_values)];
+
+       if (!onyx->initialised) {
+               memcpy(regs, initial_values, sizeof(initial_values));
+               if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
+                       return -1;
+               val &= ~ONYX_SILICONVERSION;
+               val |= initial_values[3];
+               regs[3] = val;
+       } else {
+               for (i=0; i<sizeof(register_map); i++)
+                       regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER];
+       }
+
+       for (i=0; i<sizeof(register_map); i++) {
+               if (onyx_write_register(onyx, register_map[i], regs[i]))
+                       return -1;
+       }
+       onyx->initialised = 1;
+       return 0;
+}
+
+static struct transfer_info onyx_transfers[] = {
+       /* this is first so we can skip it if no input is present...
+        * No hardware exists with that, but it's here as an example
+        * of what to do :) */
+       {
+               /* analog input */
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+                          SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .transfer_in = 1,
+               .must_be_clock_source = 0,
+               .tag = 0,
+       },
+       {
+               /* if analog and digital are currently off, anything should go,
+                * so this entry describes everything we can do... */
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+                          SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+                          | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+#endif
+               ,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .tag = 0,
+       },
+       {
+               /* analog output */
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+                          SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .transfer_in = 0,
+               .must_be_clock_source = 0,
+               .tag = 1,
+       },
+       {
+               /* digital pcm output, also possible for analog out */
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+                          SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE,
+               .rates = SNDRV_PCM_RATE_32000 |
+                        SNDRV_PCM_RATE_44100 |
+                        SNDRV_PCM_RATE_48000,
+               .transfer_in = 0,
+               .must_be_clock_source = 0,
+               .tag = 2,
+       },
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+Once alsa gets supports for this kind of thing we can add it...
+       {
+               /* digital compressed output */
+               .formats =  SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
+               .rates = SNDRV_PCM_RATE_32000 |
+                        SNDRV_PCM_RATE_44100 |
+                        SNDRV_PCM_RATE_48000,
+               .tag = 2,
+       },
+#endif
+       {}
+};
+
+static int onyx_usable(struct codec_info_item *cii,
+                      struct transfer_info *ti,
+                      struct transfer_info *out)
+{
+       u8 v;
+       struct onyx *onyx = cii->codec_data;
+       int spdif_enabled, analog_enabled;
+
+       mutex_lock(&onyx->mutex);
+       onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+       spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
+       onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+       analog_enabled = 
+               (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
+                != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
+       mutex_unlock(&onyx->mutex);
+
+       switch (ti->tag) {
+       case 0: return 1;
+       case 1: return analog_enabled;
+       case 2: return spdif_enabled;
+       }
+       return 1;
+}
+
+static int onyx_prepare(struct codec_info_item *cii,
+                       struct bus_info *bi,
+                       struct snd_pcm_substream *substream)
+{
+       u8 v;
+       struct onyx *onyx = cii->codec_data;
+       int err = -EBUSY;
+
+       mutex_lock(&onyx->mutex);
+
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+       if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
+               /* mute and lock analog output */
+               onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+               if (onyx_write_register(onyx
+                                       ONYX_REG_DAC_CONTROL,
+                                       v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
+                       goto out_unlock;
+               onyx->analog_locked = 1;
+               err = 0;
+               goto out_unlock;
+       }
+#endif
+       switch (substream->runtime->rate) {
+       case 32000:
+       case 44100:
+       case 48000:
+               /* these rates are ok for all outputs */
+               /* FIXME: program spdif channel control bits here so that
+                *        userspace doesn't have to if it only plays pcm! */
+               err = 0;
+               goto out_unlock;
+       default:
+               /* got some rate that the digital output can't do,
+                * so disable and lock it */
+               onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v);
+               if (onyx_write_register(onyx,
+                                       ONYX_REG_DIG_INFO4,
+                                       v & ~ONYX_SPDIF_ENABLE))
+                       goto out_unlock;
+               onyx->spdif_locked = 1;
+               err = 0;
+               goto out_unlock;
+       }
+
+ out_unlock:
+       mutex_unlock(&onyx->mutex);
+
+       return err;
+}
+
+static int onyx_open(struct codec_info_item *cii,
+                    struct snd_pcm_substream *substream)
+{
+       struct onyx *onyx = cii->codec_data;
+
+       mutex_lock(&onyx->mutex);
+       onyx->open_count++;
+       mutex_unlock(&onyx->mutex);
+
+       return 0;
+}
+
+static int onyx_close(struct codec_info_item *cii,
+                     struct snd_pcm_substream *substream)
+{
+       struct onyx *onyx = cii->codec_data;
+
+       mutex_lock(&onyx->mutex);
+       onyx->open_count--;
+       if (!onyx->open_count)
+               onyx->spdif_locked = onyx->analog_locked = 0;
+       mutex_unlock(&onyx->mutex);
+
+       return 0;
+}
+
+static int onyx_switch_clock(struct codec_info_item *cii,
+                            enum clock_switch what)
+{
+       struct onyx *onyx = cii->codec_data;
+
+       mutex_lock(&onyx->mutex);
+       /* this *MUST* be more elaborate later... */
+       switch (what) {
+       case CLOCK_SWITCH_PREPARE_SLAVE:
+               onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio);
+               break;
+       case CLOCK_SWITCH_SLAVE:
+               onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio);
+               break;
+       default: /* silence warning */
+               break;
+       }
+       mutex_unlock(&onyx->mutex);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+       struct onyx *onyx = cii->codec_data;
+       u8 v;
+       int err = -ENXIO;
+
+       mutex_lock(&onyx->mutex);
+       if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
+               goto out_unlock;
+       onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
+       /* Apple does a sleep here but the datasheet says to do it on resume */
+       err = 0;
+ out_unlock:
+       mutex_unlock(&onyx->mutex);
+
+       return err;
+}
+
+static int onyx_resume(struct codec_info_item *cii)
+{
+       struct onyx *onyx = cii->codec_data;
+       u8 v;
+       int err = -ENXIO;
+
+       mutex_lock(&onyx->mutex);
+       /* take codec out of suspend */
+       if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
+               goto out_unlock;
+       onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
+       /* FIXME: should divide by sample rate, but 8k is the lowest we go */
+       msleep(2205000/8000);
+       /* reset all values */
+       onyx_register_init(onyx);
+       err = 0;
+ out_unlock:
+       mutex_unlock(&onyx->mutex);
+
+       return err;
+}
+
+#endif /* CONFIG_PM */
+
+static struct codec_info onyx_codec_info = {
+       .transfers = onyx_transfers,
+       .sysclock_factor = 256,
+       .bus_factor = 64,
+       .owner = THIS_MODULE,
+       .usable = onyx_usable,
+       .prepare = onyx_prepare,
+       .open = onyx_open,
+       .close = onyx_close,
+       .switch_clock = onyx_switch_clock,
+#ifdef CONFIG_PM
+       .suspend = onyx_suspend,
+       .resume = onyx_resume,
+#endif
+};
+
+static int onyx_init_codec(struct aoa_codec *codec)
+{
+       struct onyx *onyx = codec_to_onyx(codec);
+       struct snd_kcontrol *ctl;
+       struct codec_info *ci = &onyx_codec_info;
+       u8 v;
+       int err;
+
+       if (!onyx->codec.gpio || !onyx->codec.gpio->methods) {
+               printk(KERN_ERR PFX "gpios not assigned!!\n");
+               return -EINVAL;
+       }
+
+       onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+       msleep(1);
+       onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
+       msleep(1);
+       onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+       msleep(1);
+       
+       if (onyx_register_init(onyx)) {
+               printk(KERN_ERR PFX "failed to initialise onyx registers\n");
+               return -ENODEV;
+       }
+
+       if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) {
+               printk(KERN_ERR PFX "failed to create onyx snd device!\n");
+               return -ENODEV;
+       }
+
+       /* nothing connected? what a joke! */
+       if ((onyx->codec.connected & 0xF) == 0)
+               return -ENOTCONN;
+
+       /* if no inputs are present... */
+       if ((onyx->codec.connected & 0xC) == 0) {
+               if (!onyx->codec_info)
+                       onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
+               if (!onyx->codec_info)
+                       return -ENOMEM;
+               ci = onyx->codec_info;
+               *ci = onyx_codec_info;
+               ci->transfers++;
+       }
+
+       /* if no outputs are present... */
+       if ((onyx->codec.connected & 3) == 0) {
+               if (!onyx->codec_info)
+                       onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
+               if (!onyx->codec_info)
+                       return -ENOMEM;
+               ci = onyx->codec_info;
+               /* this is fine as there have to be inputs
+                * if we end up in this part of the code */
+               *ci = onyx_codec_info;
+               ci->transfers[1].formats = 0;
+       }
+
+       if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev,
+                                                  aoa_get_card(),
+                                                  ci, onyx)) {
+               printk(KERN_ERR PFX "error creating onyx pcm\n");
+               return -ENODEV;
+       }
+#define ADDCTL(n)                                                      \
+       do {                                                            \
+               ctl = snd_ctl_new1(&n, onyx);                           \
+               if (ctl) {                                              \
+                       ctl->id.device =                                \
+                               onyx->codec.soundbus_dev->pcm->device;  \
+                       err = aoa_snd_ctl_add(ctl);                     \
+                       if (err)                                        \
+                               goto error;                             \
+               }                                                       \
+       } while (0)
+
+       if (onyx->codec.soundbus_dev->pcm) {
+               /* give the user appropriate controls
+                * depending on what inputs are connected */
+               if ((onyx->codec.connected & 0xC) == 0xC)
+                       ADDCTL(capture_source_control);
+               else if (onyx->codec.connected & 4)
+                       onyx_set_capture_source(onyx, 0);
+               else
+                       onyx_set_capture_source(onyx, 1);
+               if (onyx->codec.connected & 0xC)
+                       ADDCTL(inputgain_control);
+
+               /* depending on what output is connected,
+                * give the user appropriate controls */
+               if (onyx->codec.connected & 1) {
+                       ADDCTL(volume_control);
+                       ADDCTL(mute_control);
+                       ADDCTL(ovr1_control);
+                       ADDCTL(flt0_control);
+                       ADDCTL(hpf_control);
+                       ADDCTL(dm12_control);
+                       /* spdif control defaults to off */
+               }
+               if (onyx->codec.connected & 2) {
+                       ADDCTL(onyx_spdif_mask);
+                       ADDCTL(onyx_spdif_ctrl);
+               }
+               if ((onyx->codec.connected & 3) == 3)
+                       ADDCTL(spdif_control);
+               /* if only S/PDIF is connected, enable it unconditionally */
+               if ((onyx->codec.connected & 3) == 2) {
+                       onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+                       v |= ONYX_SPDIF_ENABLE;
+                       onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
+               }
+       }
+#undef ADDCTL
+       printk(KERN_INFO PFX "attached to onyx codec via i2c\n");
+
+       return 0;
+ error:
+       onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
+       snd_device_free(aoa_get_card(), onyx);
+       return err;
+}
+
+static void onyx_exit_codec(struct aoa_codec *codec)
+{
+       struct onyx *onyx = codec_to_onyx(codec);
+
+       if (!onyx->codec.soundbus_dev) {
+               printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n");
+               return;
+       }
+       onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
+}
+
+static struct i2c_driver onyx_driver;
+
+static int onyx_create(struct i2c_adapter *adapter,
+                      struct device_node *node,
+                      int addr)
+{
+       struct onyx *onyx;
+       u8 dummy;
+
+       onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL);
+
+       if (!onyx)
+               return -ENOMEM;
+
+       mutex_init(&onyx->mutex);
+       onyx->i2c.driver = &onyx_driver;
+       onyx->i2c.adapter = adapter;
+       onyx->i2c.addr = addr & 0x7f;
+       strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1);
+
+       if (i2c_attach_client(&onyx->i2c)) {
+               printk(KERN_ERR PFX "failed to attach to i2c\n");
+               goto fail;
+       }
+
+       /* we try to read from register ONYX_REG_CONTROL
+        * to check if the codec is present */
+       if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
+               i2c_detach_client(&onyx->i2c);
+               printk(KERN_ERR PFX "failed to read control register\n");
+               goto fail;
+       }
+
+       strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1);
+       onyx->codec.owner = THIS_MODULE;
+       onyx->codec.init = onyx_init_codec;
+       onyx->codec.exit = onyx_exit_codec;
+       onyx->codec.node = of_node_get(node);
+
+       if (aoa_codec_register(&onyx->codec)) {
+               i2c_detach_client(&onyx->i2c);
+               goto fail;
+       }
+       printk(KERN_DEBUG PFX "created and attached onyx instance\n");
+       return 0;
+ fail:
+       kfree(onyx);
+       return -EINVAL;
+}
+
+static int onyx_i2c_attach(struct i2c_adapter *adapter)
+{
+       struct device_node *busnode, *dev = NULL;
+       struct pmac_i2c_bus *bus;
+
+       bus = pmac_i2c_adapter_to_bus(adapter);
+       if (bus == NULL)
+               return -ENODEV;
+       busnode = pmac_i2c_get_bus_node(bus);
+
+       while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+               if (device_is_compatible(dev, "pcm3052")) {
+                       u32 *addr;
+                       printk(KERN_DEBUG PFX "found pcm3052\n");
+                       addr = (u32 *) get_property(dev, "reg", NULL);
+                       if (!addr)
+                               return -ENODEV;
+                       return onyx_create(adapter, dev, (*addr)>>1);
+               }
+       }
+
+       /* if that didn't work, try desperate mode for older
+        * machines that have stuff missing from the device tree */
+       
+       if (!device_is_compatible(busnode, "k2-i2c"))
+               return -ENODEV;
+
+       printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n");
+       /* probe both possible addresses for the onyx chip */
+       if (onyx_create(adapter, NULL, 0x46) == 0)
+               return 0;
+       return onyx_create(adapter, NULL, 0x47);
+}
+
+static int onyx_i2c_detach(struct i2c_client *client)
+{
+       struct onyx *onyx = container_of(client, struct onyx, i2c);
+       int err;
+
+       if ((err = i2c_detach_client(client)))
+               return err;
+       aoa_codec_unregister(&onyx->codec);
+       of_node_put(onyx->codec.node);
+       if (onyx->codec_info)
+               kfree(onyx->codec_info);
+       kfree(onyx);
+       return 0;
+}
+
+static struct i2c_driver onyx_driver = {
+       .driver = {
+               .name = "aoa_codec_onyx",
+               .owner = THIS_MODULE,
+       },
+       .attach_adapter = onyx_i2c_attach,
+       .detach_client = onyx_i2c_detach,
+};
+
+static int __init onyx_init(void)
+{
+       return i2c_add_driver(&onyx_driver);
+}
+
+static void __exit onyx_exit(void)
+{
+       i2c_del_driver(&onyx_driver);
+}
+
+module_init(onyx_init);
+module_exit(onyx_exit);
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h
new file mode 100644 (file)
index 0000000..aeedda7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Apple Onboard Audio driver for Onyx codec (header)
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __SND_AOA_CODEC_ONYX_H
+#define __SND_AOA_CODEC_ONYX_H
+#include <stddef.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/pmac_low_i2c.h>
+#include <asm/prom.h>
+
+/* PCM3052 register definitions */
+
+/* the attenuation registers take values from
+ * -1 (0dB) to -127 (-63.0 dB) or others (muted) */
+#define ONYX_REG_DAC_ATTEN_LEFT                65
+#define FIRSTREGISTER                  ONYX_REG_DAC_ATTEN_LEFT
+#define ONYX_REG_DAC_ATTEN_RIGHT       66
+
+#define ONYX_REG_CONTROL               67
+#      define ONYX_MRST                (1<<7)
+#      define ONYX_SRST                (1<<6)
+#      define ONYX_ADPSV               (1<<5)
+#      define ONYX_DAPSV               (1<<4)
+#      define ONYX_SILICONVERSION      (1<<0)
+/* all others reserved */
+
+#define ONYX_REG_DAC_CONTROL           68
+#      define ONYX_OVR1                (1<<6)
+#      define ONYX_MUTE_RIGHT          (1<<1)
+#      define ONYX_MUTE_LEFT           (1<<0)
+
+#define ONYX_REG_DAC_DEEMPH            69
+#      define ONYX_DIGDEEMPH_SHIFT     5
+#      define ONYX_DIGDEEMPH_MASK      (3<<ONYX_DIGDEEMPH_SHIFT)
+#      define ONYX_DIGDEEMPH_CTRL      (1<<4)
+
+#define ONYX_REG_DAC_FILTER            70
+#      define ONYX_ROLLOFF_FAST        (1<<5)
+#      define ONYX_DAC_FILTER_ALWAYS   (1<<2)
+
+#define        ONYX_REG_DAC_OUTPHASE           71
+#      define ONYX_OUTPHASE_INVERTED   (1<<0)
+
+#define ONYX_REG_ADC_CONTROL           72
+#      define ONYX_ADC_INPUT_MIC       (1<<5)
+/* 8 + input gain in dB, valid range for input gain is -4 .. 20 dB */
+#      define ONYX_ADC_PGA_GAIN_MASK   0x1f
+
+#define ONYX_REG_ADC_HPF_BYPASS                75
+#      define ONYX_HPF_DISABLE         (1<<3)
+#      define ONYX_ADC_HPF_ALWAYS      (1<<2)
+
+#define ONYX_REG_DIG_INFO1             77
+#      define ONYX_MASK_DIN_TO_BPZ     (1<<7)
+/* bits 1-5 control channel bits 1-5 */
+#      define ONYX_DIGOUT_DISABLE      (1<<0)
+
+#define ONYX_REG_DIG_INFO2             78
+/* controls channel bits 8-15 */
+
+#define ONYX_REG_DIG_INFO3             79
+/* control channel bits 24-29, high 2 bits reserved */
+
+#define ONYX_REG_DIG_INFO4             80
+#      define ONYX_VALIDL              (1<<7)
+#      define ONYX_VALIDR              (1<<6)
+#      define ONYX_SPDIF_ENABLE        (1<<5)
+/* lower 4 bits control bits 32-35 of channel control and word length */
+#      define ONYX_WORDLEN_MASK        (0xF)
+
+#endif /* __SND_AOA_CODEC_ONYX_H */
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
new file mode 100644 (file)
index 0000000..69b6113
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * This file is only included exactly once!
+ *
+ * The tables here are derived from the tas3004 datasheet,
+ * modulo typo corrections and some smoothing...
+ */
+
+#define TAS3004_TREBLE_MIN     0
+#define TAS3004_TREBLE_MAX     72
+#define TAS3004_BASS_MIN       0
+#define TAS3004_BASS_MAX       72
+#define TAS3004_TREBLE_ZERO    36
+#define TAS3004_BASS_ZERO      36
+
+static u8 tas3004_treble_table[] = {
+       150, /* -18 dB */
+       149,
+       148,
+       147,
+       146,
+       145,
+       144,
+       143,
+       142,
+       141,
+       140,
+       139,
+       138,
+       137,
+       136,
+       135,
+       134,
+       133,
+       132,
+       131,
+       130,
+       129,
+       128,
+       127,
+       126,
+       125,
+       124,
+       123,
+       122,
+       121,
+       120,
+       119,
+       118,
+       117,
+       116,
+       115,
+       114, /* 0 dB */
+       113,
+       112,
+       111,
+       109,
+       108,
+       107,
+       105,
+       104,
+       103,
+       101,
+       99,
+       98,
+       96,
+       93,
+       91,
+       89,
+       86,
+       83,
+       81,
+       77,
+       74,
+       71,
+       67,
+       63,
+       59,
+       54,
+       49,
+       44,
+       38,
+       32,
+       26,
+       19,
+       10,
+       4,
+       2,
+       1, /* +18 dB */
+};
+
+static inline u8 tas3004_treble(int idx)
+{
+       return tas3004_treble_table[idx];
+}
+
+/* I only save the difference here to the treble table
+ * so that the binary is smaller...
+ * I have also ignored completely differences of
+ * +/- 1
+ */
+static s8 tas3004_bass_diff_to_treble[] = {
+       2, /* 7 dB, offset 50 */
+       2,
+       2,
+       2,
+       2,
+       1,
+       2,
+       2,
+       2,
+       3,
+       4,
+       4,
+       5,
+       6,
+       7,
+       8,
+       9,
+       10,
+       11,
+       14,
+       13,
+       8,
+       1, /* 18 dB */
+};
+
+static inline u8 tas3004_bass(int idx)
+{
+       u8 result = tas3004_treble_table[idx];
+
+       if (idx >= 50)
+               result += tas3004_bass_diff_to_treble[idx-50];
+       return result;
+}
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
new file mode 100644 (file)
index 0000000..4cfa675
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ This is the program used to generate below table.
+
+#include <stdio.h>
+#include <math.h>
+int main() {
+  int dB2;
+  printf("/" "* This file is only included exactly once!\n");
+  printf(" *\n");
+  printf(" * If they'd only tell us that generating this table was\n");
+  printf(" * as easy as calculating\n");
+  printf(" *      hwvalue = 1048576.0*exp(0.057564628*dB*2)\n");
+  printf(" * :) *" "/\n");
+  printf("static int tas_gaintable[] = {\n");
+  printf("     0x000000, /" "* -infinity dB *" "/\n");
+  for (dB2=-140;dB2<=36;dB2++)
+    printf("   0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0);
+  printf("};\n\n");
+}
+
+*/
+
+/* This file is only included exactly once!
+ *
+ * If they'd only tell us that generating this table was
+ * as easy as calculating
+ *      hwvalue = 1048576.0*exp(0.057564628*dB*2)
+ * :) */
+static int tas_gaintable[] = {
+       0x000000, /* -infinity dB */
+       0x00014b, /* -70.0 dB */
+       0x00015f, /* -69.5 dB */
+       0x000174, /* -69.0 dB */
+       0x00018a, /* -68.5 dB */
+       0x0001a1, /* -68.0 dB */
+       0x0001ba, /* -67.5 dB */
+       0x0001d4, /* -67.0 dB */
+       0x0001f0, /* -66.5 dB */
+       0x00020d, /* -66.0 dB */
+       0x00022c, /* -65.5 dB */
+       0x00024d, /* -65.0 dB */
+       0x000270, /* -64.5 dB */
+       0x000295, /* -64.0 dB */
+       0x0002bc, /* -63.5 dB */
+       0x0002e6, /* -63.0 dB */
+       0x000312, /* -62.5 dB */
+       0x000340, /* -62.0 dB */
+       0x000372, /* -61.5 dB */
+       0x0003a6, /* -61.0 dB */
+       0x0003dd, /* -60.5 dB */
+       0x000418, /* -60.0 dB */
+       0x000456, /* -59.5 dB */
+       0x000498, /* -59.0 dB */
+       0x0004de, /* -58.5 dB */
+       0x000528, /* -58.0 dB */
+       0x000576, /* -57.5 dB */
+       0x0005c9, /* -57.0 dB */
+       0x000620, /* -56.5 dB */
+       0x00067d, /* -56.0 dB */
+       0x0006e0, /* -55.5 dB */
+       0x000748, /* -55.0 dB */
+       0x0007b7, /* -54.5 dB */
+       0x00082c, /* -54.0 dB */
+       0x0008a8, /* -53.5 dB */
+       0x00092b, /* -53.0 dB */
+       0x0009b6, /* -52.5 dB */
+       0x000a49, /* -52.0 dB */
+       0x000ae5, /* -51.5 dB */
+       0x000b8b, /* -51.0 dB */
+       0x000c3a, /* -50.5 dB */
+       0x000cf3, /* -50.0 dB */
+       0x000db8, /* -49.5 dB */
+       0x000e88, /* -49.0 dB */
+       0x000f64, /* -48.5 dB */
+       0x00104e, /* -48.0 dB */
+       0x001145, /* -47.5 dB */
+       0x00124b, /* -47.0 dB */
+       0x001361, /* -46.5 dB */
+       0x001487, /* -46.0 dB */
+       0x0015be, /* -45.5 dB */
+       0x001708, /* -45.0 dB */
+       0x001865, /* -44.5 dB */
+       0x0019d8, /* -44.0 dB */
+       0x001b60, /* -43.5 dB */
+       0x001cff, /* -43.0 dB */
+       0x001eb7, /* -42.5 dB */
+       0x002089, /* -42.0 dB */
+       0x002276, /* -41.5 dB */
+       0x002481, /* -41.0 dB */
+       0x0026ab, /* -40.5 dB */
+       0x0028f5, /* -40.0 dB */
+       0x002b63, /* -39.5 dB */
+       0x002df5, /* -39.0 dB */
+       0x0030ae, /* -38.5 dB */
+       0x003390, /* -38.0 dB */
+       0x00369e, /* -37.5 dB */
+       0x0039db, /* -37.0 dB */
+       0x003d49, /* -36.5 dB */
+       0x0040ea, /* -36.0 dB */
+       0x0044c3, /* -35.5 dB */
+       0x0048d6, /* -35.0 dB */
+       0x004d27, /* -34.5 dB */
+       0x0051b9, /* -34.0 dB */
+       0x005691, /* -33.5 dB */
+       0x005bb2, /* -33.0 dB */
+       0x006121, /* -32.5 dB */
+       0x0066e3, /* -32.0 dB */
+       0x006cfb, /* -31.5 dB */
+       0x007370, /* -31.0 dB */
+       0x007a48, /* -30.5 dB */
+       0x008186, /* -30.0 dB */
+       0x008933, /* -29.5 dB */
+       0x009154, /* -29.0 dB */
+       0x0099f1, /* -28.5 dB */
+       0x00a310, /* -28.0 dB */
+       0x00acba, /* -27.5 dB */
+       0x00b6f6, /* -27.0 dB */
+       0x00c1cd, /* -26.5 dB */
+       0x00cd49, /* -26.0 dB */
+       0x00d973, /* -25.5 dB */
+       0x00e655, /* -25.0 dB */
+       0x00f3fb, /* -24.5 dB */
+       0x010270, /* -24.0 dB */
+       0x0111c0, /* -23.5 dB */
+       0x0121f9, /* -23.0 dB */
+       0x013328, /* -22.5 dB */
+       0x01455b, /* -22.0 dB */
+       0x0158a2, /* -21.5 dB */
+       0x016d0e, /* -21.0 dB */
+       0x0182af, /* -20.5 dB */
+       0x019999, /* -20.0 dB */
+       0x01b1de, /* -19.5 dB */
+       0x01cb94, /* -19.0 dB */
+       0x01e6cf, /* -18.5 dB */
+       0x0203a7, /* -18.0 dB */
+       0x022235, /* -17.5 dB */
+       0x024293, /* -17.0 dB */
+       0x0264db, /* -16.5 dB */
+       0x02892c, /* -16.0 dB */
+       0x02afa3, /* -15.5 dB */
+       0x02d862, /* -15.0 dB */
+       0x03038a, /* -14.5 dB */
+       0x033142, /* -14.0 dB */
+       0x0361af, /* -13.5 dB */
+       0x0394fa, /* -13.0 dB */
+       0x03cb50, /* -12.5 dB */
+       0x0404de, /* -12.0 dB */
+       0x0441d5, /* -11.5 dB */
+       0x048268, /* -11.0 dB */
+       0x04c6d0, /* -10.5 dB */
+       0x050f44, /* -10.0 dB */
+       0x055c04, /* -9.5 dB */
+       0x05ad50, /* -9.0 dB */
+       0x06036e, /* -8.5 dB */
+       0x065ea5, /* -8.0 dB */
+       0x06bf44, /* -7.5 dB */
+       0x07259d, /* -7.0 dB */
+       0x079207, /* -6.5 dB */
+       0x0804dc, /* -6.0 dB */
+       0x087e80, /* -5.5 dB */
+       0x08ff59, /* -5.0 dB */
+       0x0987d5, /* -4.5 dB */
+       0x0a1866, /* -4.0 dB */
+       0x0ab189, /* -3.5 dB */
+       0x0b53be, /* -3.0 dB */
+       0x0bff91, /* -2.5 dB */
+       0x0cb591, /* -2.0 dB */
+       0x0d765a, /* -1.5 dB */
+       0x0e4290, /* -1.0 dB */
+       0x0f1adf, /* -0.5 dB */
+       0x100000, /* 0.0 dB */
+       0x10f2b4, /* 0.5 dB */
+       0x11f3c9, /* 1.0 dB */
+       0x13041a, /* 1.5 dB */
+       0x14248e, /* 2.0 dB */
+       0x15561a, /* 2.5 dB */
+       0x1699c0, /* 3.0 dB */
+       0x17f094, /* 3.5 dB */
+       0x195bb8, /* 4.0 dB */
+       0x1adc61, /* 4.5 dB */
+       0x1c73d5, /* 5.0 dB */
+       0x1e236d, /* 5.5 dB */
+       0x1fec98, /* 6.0 dB */
+       0x21d0d9, /* 6.5 dB */
+       0x23d1cd, /* 7.0 dB */
+       0x25f125, /* 7.5 dB */
+       0x2830af, /* 8.0 dB */
+       0x2a9254, /* 8.5 dB */
+       0x2d1818, /* 9.0 dB */
+       0x2fc420, /* 9.5 dB */
+       0x3298b0, /* 10.0 dB */
+       0x35982f, /* 10.5 dB */
+       0x38c528, /* 11.0 dB */
+       0x3c224c, /* 11.5 dB */
+       0x3fb278, /* 12.0 dB */
+       0x4378b0, /* 12.5 dB */
+       0x477829, /* 13.0 dB */
+       0x4bb446, /* 13.5 dB */
+       0x5030a1, /* 14.0 dB */
+       0x54f106, /* 14.5 dB */
+       0x59f980, /* 15.0 dB */
+       0x5f4e52, /* 15.5 dB */
+       0x64f403, /* 16.0 dB */
+       0x6aef5e, /* 16.5 dB */
+       0x714575, /* 17.0 dB */
+       0x77fbaa, /* 17.5 dB */
+       0x7f17af, /* 18.0 dB */
+};
+
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
new file mode 100644 (file)
index 0000000..16c0b6b
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ * Apple Onboard Audio driver for tas codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ * Open questions:
+ *  - How to distinguish between 3004 and versions?
+ *
+ * FIXMEs:
+ *  - This codec driver doesn't honour the 'connected'
+ *    property of the aoa_codec struct, hence if
+ *    it is used in machines where not everything is
+ *    connected it will display wrong mixer elements.
+ *  - Driver assumes that the microphone is always
+ *    monaureal and connected to the right channel of
+ *    the input. This should also be a codec-dependent
+ *    flag, maybe the codec should have 3 different
+ *    bits for the three different possibilities how
+ *    it can be hooked up...
+ *    But as long as I don't see any hardware hooked
+ *    up that way...
+ *  - As Apple notes in their code, the tas3004 seems
+ *    to delay the right channel by one sample. You can
+ *    see this when for example recording stereo in
+ *    audacity, or recording the tas output via cable
+ *    on another machine (use a sinus generator or so).
+ *    I tried programming the BiQuads but couldn't
+ *    make the delay work, maybe someone can read the
+ *    datasheet and fix it. The relevant Apple comment
+ *    is in AppleTAS3004Audio.cpp lines 1637 ff. Note
+ *    that their comment describing how they program
+ *    the filters sucks...
+ *
+ * Other things:
+ *  - this should actually register *two* aoa_codec
+ *    structs since it has two inputs. Then it must
+ *    use the prepare callback to forbid running the
+ *    secondary output on a different clock.
+ *    Also, whatever bus knows how to do this must
+ *    provide two soundbus_dev devices and the fabric
+ *    must be able to link them correctly.
+ *
+ *    I don't even know if Apple ever uses the second
+ *    port on the tas3004 though, I don't think their
+ *    i2s controllers can even do it. OTOH, they all
+ *    derive the clocks from common clocks, so it
+ *    might just be possible. The framework allows the
+ *    codec to refine the transfer_info items in the
+ *    usable callback, so we can simply remove the
+ *    rates the second instance is not using when it
+ *    actually is in use.
+ *    Maybe we'll need to make the sound busses have
+ *    a 'clock group id' value so the codec can
+ *    determine if the two outputs can be driven at
+ *    the same time. But that is likely overkill, up
+ *    to the fabric to not link them up incorrectly,
+ *    and up to the hardware designer to not wire
+ *    them up in some weird unusable way.
+ */
+#include <stddef.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/pmac_low_i2c.h>
+#include <asm/prom.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("tas codec driver for snd-aoa");
+
+#include "snd-aoa-codec-tas.h"
+#include "snd-aoa-codec-tas-gain-table.h"
+#include "snd-aoa-codec-tas-basstreble.h"
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+#define PFX "snd-aoa-codec-tas: "
+
+
+struct tas {
+       struct aoa_codec        codec;
+       struct i2c_client       i2c;
+       u32                     mute_l:1, mute_r:1 ,
+                               controls_created:1 ,
+                               drc_enabled:1,
+                               hw_enabled:1;
+       u8                      cached_volume_l, cached_volume_r;
+       u8                      mixer_l[3], mixer_r[3];
+       u8                      bass, treble;
+       u8                      acr;
+       int                     drc_range;
+};
+
+static int tas_reset_init(struct tas *tas);
+
+static struct tas *codec_to_tas(struct aoa_codec *codec)
+{
+       return container_of(codec, struct tas, codec);
+}
+
+static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
+{
+       if (len == 1)
+               return i2c_smbus_write_byte_data(&tas->i2c, reg, *data);
+       else
+               return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
+}
+
+static void tas3004_set_drc(struct tas *tas)
+{
+       unsigned char val[6];
+
+       if (tas->drc_enabled)
+               val[0] = 0x50; /* 3:1 above threshold */
+       else
+               val[0] = 0x51; /* disabled */
+       val[1] = 0x02; /* 1:1 below threshold */
+       if (tas->drc_range > 0xef)
+               val[2] = 0xef;
+       else if (tas->drc_range < 0)
+               val[2] = 0x00;
+       else
+               val[2] = tas->drc_range;
+       val[3] = 0xb0;
+       val[4] = 0x60;
+       val[5] = 0xa0;
+
+       tas_write_reg(tas, TAS_REG_DRC, 6, val);
+}
+
+static void tas_set_treble(struct tas *tas)
+{
+       u8 tmp;
+
+       tmp = tas3004_treble(tas->treble);
+       tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
+}
+
+static void tas_set_bass(struct tas *tas)
+{
+       u8 tmp;
+
+       tmp = tas3004_bass(tas->bass);
+       tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
+}
+
+static void tas_set_volume(struct tas *tas)
+{
+       u8 block[6];
+       int tmp;
+       u8 left, right;
+
+       left = tas->cached_volume_l;
+       right = tas->cached_volume_r;
+
+       if (left > 177) left = 177;
+       if (right > 177) right = 177;
+
+       if (tas->mute_l) left = 0;
+       if (tas->mute_r) right = 0;
+
+       /* analysing the volume and mixer tables shows
+        * that they are similar enough when we shift
+        * the mixer table down by 4 bits. The error
+        * is miniscule, in just one item the error
+        * is 1, at a value of 0x07f17b (mixer table
+        * value is 0x07f17a) */
+       tmp = tas_gaintable[left];
+       block[0] = tmp>>20;
+       block[1] = tmp>>12;
+       block[2] = tmp>>4;
+       tmp = tas_gaintable[right];
+       block[3] = tmp>>20;
+       block[4] = tmp>>12;
+       block[5] = tmp>>4;
+       tas_write_reg(tas, TAS_REG_VOL, 6, block);
+}
+
+static void tas_set_mixer(struct tas *tas)
+{
+       u8 block[9];
+       int tmp, i;
+       u8 val;
+
+       for (i=0;i<3;i++) {
+               val = tas->mixer_l[i];
+               if (val > 177) val = 177;
+               tmp = tas_gaintable[val];
+               block[3*i+0] = tmp>>16;
+               block[3*i+1] = tmp>>8;
+               block[3*i+2] = tmp;
+       }
+       tas_write_reg(tas, TAS_REG_LMIX, 9, block);
+
+       for (i=0;i<3;i++) {
+               val = tas->mixer_r[i];
+               if (val > 177) val = 177;
+               tmp = tas_gaintable[val];
+               block[3*i+0] = tmp>>16;
+               block[3*i+1] = tmp>>8;
+               block[3*i+2] = tmp;
+       }
+       tas_write_reg(tas, TAS_REG_RMIX, 9, block);
+}
+
+/* alsa stuff */
+
+static int tas_dev_register(struct snd_device *dev)
+{
+       return 0;
+}
+
+static struct snd_device_ops ops = {
+       .dev_register = tas_dev_register,
+};
+
+static int tas_snd_vol_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 177;
+       return 0;
+}
+
+static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->cached_volume_l;
+       ucontrol->value.integer.value[1] = tas->cached_volume_r;
+       return 0;
+}
+
+static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->cached_volume_l == ucontrol->value.integer.value[0]
+        && tas->cached_volume_r == ucontrol->value.integer.value[1])
+               return 0;
+
+       tas->cached_volume_l = ucontrol->value.integer.value[0];
+       tas->cached_volume_r = ucontrol->value.integer.value[1];
+       if (tas->hw_enabled)
+               tas_set_volume(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new volume_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Master Playback Volume",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_vol_info,
+       .get = tas_snd_vol_get,
+       .put = tas_snd_vol_put,
+};
+
+static int tas_snd_mute_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = !tas->mute_l;
+       ucontrol->value.integer.value[1] = !tas->mute_r;
+       return 0;
+}
+
+static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->mute_l == !ucontrol->value.integer.value[0]
+        && tas->mute_r == !ucontrol->value.integer.value[1])
+               return 0;
+
+       tas->mute_l = !ucontrol->value.integer.value[0];
+       tas->mute_r = !ucontrol->value.integer.value[1];
+       if (tas->hw_enabled)
+               tas_set_volume(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new mute_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Master Playback Switch",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_mute_info,
+       .get = tas_snd_mute_get,
+       .put = tas_snd_mute_put,
+};
+
+static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 177;
+       return 0;
+}
+
+static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+       int idx = kcontrol->private_value;
+
+       ucontrol->value.integer.value[0] = tas->mixer_l[idx];
+       ucontrol->value.integer.value[1] = tas->mixer_r[idx];
+
+       return 0;
+}
+
+static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+       int idx = kcontrol->private_value;
+
+       if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
+        && tas->mixer_r[idx] == ucontrol->value.integer.value[1])
+               return 0;
+
+       tas->mixer_l[idx] = ucontrol->value.integer.value[0];
+       tas->mixer_r[idx] = ucontrol->value.integer.value[1];
+
+       if (tas->hw_enabled)
+               tas_set_mixer(tas);
+       return 1;
+}
+
+#define MIXER_CONTROL(n,descr,idx)                     \
+static struct snd_kcontrol_new n##_control = {         \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,            \
+       .name = descr " Playback Volume",               \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,      \
+       .info = tas_snd_mixer_info,                     \
+       .get = tas_snd_mixer_get,                       \
+       .put = tas_snd_mixer_put,                       \
+       .private_value = idx,                           \
+}
+
+MIXER_CONTROL(pcm1, "PCM", 0);
+MIXER_CONTROL(monitor, "Monitor", 2);
+
+static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = TAS3004_DRC_MAX;
+       return 0;
+}
+
+static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->drc_range;
+       return 0;
+}
+
+static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->drc_range == ucontrol->value.integer.value[0])
+               return 0;
+
+       tas->drc_range = ucontrol->value.integer.value[0];
+       if (tas->hw_enabled)
+               tas3004_set_drc(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new drc_range_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "DRC Range",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_drc_range_info,
+       .get = tas_snd_drc_range_get,
+       .put = tas_snd_drc_range_put,
+};
+
+static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->drc_enabled;
+       return 0;
+}
+
+static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->drc_enabled == ucontrol->value.integer.value[0])
+               return 0;
+
+       tas->drc_enabled = ucontrol->value.integer.value[0];
+       if (tas->hw_enabled)
+               tas3004_set_drc(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new drc_switch_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "DRC Range Switch",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_drc_switch_info,
+       .get = tas_snd_drc_switch_get,
+       .put = tas_snd_drc_switch_put,
+};
+
+static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       static char *texts[] = { "Line-In", "Microphone" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 2;
+       if (uinfo->value.enumerated.item > 1)
+               uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
+       return 0;
+}
+
+static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+       int oldacr = tas->acr;
+
+       tas->acr &= ~TAS_ACR_INPUT_B;
+       if (ucontrol->value.enumerated.item[0])
+               tas->acr |= TAS_ACR_INPUT_B;
+       if (oldacr == tas->acr)
+               return 0;
+       if (tas->hw_enabled)
+               tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
+       return 1;
+}
+
+static struct snd_kcontrol_new capture_source_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       /* If we name this 'Input Source', it properly shows up in
+        * alsamixer as a selection, * but it's shown under the
+        * 'Playback' category.
+        * If I name it 'Capture Source', it shows up in strange
+        * ways (two bools of which one can be selected at a
+        * time) but at least it's shown in the 'Capture'
+        * category.
+        * I was told that this was due to backward compatibility,
+        * but I don't understand then why the mangling is *not*
+        * done when I name it "Input Source".....
+        */
+       .name = "Capture Source",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_capture_source_info,
+       .get = tas_snd_capture_source_get,
+       .put = tas_snd_capture_source_put,
+};
+
+static int tas_snd_treble_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = TAS3004_TREBLE_MIN;
+       uinfo->value.integer.max = TAS3004_TREBLE_MAX;
+       return 0;
+}
+
+static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->treble;
+       return 0;
+}
+
+static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->treble == ucontrol->value.integer.value[0])
+               return 0;
+
+       tas->treble = ucontrol->value.integer.value[0];
+       if (tas->hw_enabled)
+               tas_set_treble(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new treble_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Treble",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_treble_info,
+       .get = tas_snd_treble_get,
+       .put = tas_snd_treble_put,
+};
+
+static int tas_snd_bass_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = TAS3004_BASS_MIN;
+       uinfo->value.integer.max = TAS3004_BASS_MAX;
+       return 0;
+}
+
+static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->bass;
+       return 0;
+}
+
+static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->bass == ucontrol->value.integer.value[0])
+               return 0;
+
+       tas->bass = ucontrol->value.integer.value[0];
+       if (tas->hw_enabled)
+               tas_set_bass(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new bass_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Bass",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_bass_info,
+       .get = tas_snd_bass_get,
+       .put = tas_snd_bass_put,
+};
+
+static struct transfer_info tas_transfers[] = {
+       {
+               /* input */
+               .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+               .transfer_in = 1,
+       },
+       {
+               /* output */
+               .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+               .transfer_in = 0,
+       },
+       {}
+};
+
+static int tas_usable(struct codec_info_item *cii,
+                     struct transfer_info *ti,
+                     struct transfer_info *out)
+{
+       return 1;
+}
+
+static int tas_reset_init(struct tas *tas)
+{
+       u8 tmp;
+
+       tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
+       msleep(5);
+       tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
+       msleep(5);
+       tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1);
+       msleep(20);
+       tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
+       msleep(10);
+       tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
+
+       tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
+       if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
+               return -ENODEV;
+
+       tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL |
+               TAS_ACR_B_MON_SEL_RIGHT;
+       if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
+               return -ENODEV;
+
+       tmp = 0;
+       if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
+               return -ENODEV;
+
+       tas3004_set_drc(tas);
+
+       /* Set treble & bass to 0dB */
+       tas->treble = TAS3004_TREBLE_ZERO;
+       tas->bass = TAS3004_BASS_ZERO;
+       tas_set_treble(tas);
+       tas_set_bass(tas);
+
+       tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
+       if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
+               return -ENODEV;
+
+       return 0;
+}
+
+static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock)
+{
+       struct tas *tas = cii->codec_data;
+
+       switch(clock) {
+       case CLOCK_SWITCH_PREPARE_SLAVE:
+               /* Clocks are going away, mute mute mute */
+               tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
+               tas->hw_enabled = 0;
+               break;
+       case CLOCK_SWITCH_SLAVE:
+               /* Clocks are back, re-init the codec */
+               tas_reset_init(tas);
+               tas_set_volume(tas);
+               tas_set_mixer(tas);
+               tas->hw_enabled = 1;
+               tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
+               break;
+       default:
+               /* doesn't happen as of now */
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* we are controlled via i2c and assume that is always up
+ * If that wasn't the case, we'd have to suspend once
+ * our i2c device is suspended, and then take note of that! */
+static int tas_suspend(struct tas *tas)
+{
+       tas->hw_enabled = 0;
+       tas->acr |= TAS_ACR_ANALOG_PDOWN;
+       tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
+       return 0;
+}
+
+static int tas_resume(struct tas *tas)
+{
+       /* reset codec */
+       tas_reset_init(tas);
+       tas_set_volume(tas);
+       tas_set_mixer(tas);
+       tas->hw_enabled = 1;
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int _tas_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+       return tas_suspend(cii->codec_data);
+}
+
+static int _tas_resume(struct codec_info_item *cii)
+{
+       return tas_resume(cii->codec_data);
+}
+#endif
+
+static struct codec_info tas_codec_info = {
+       .transfers = tas_transfers,
+       /* in theory, we can drive it at 512 too...
+        * but so far the framework doesn't allow
+        * for that and I don't see much point in it. */
+       .sysclock_factor = 256,
+       /* same here, could be 32 for just one 16 bit format */
+       .bus_factor = 64,
+       .owner = THIS_MODULE,
+       .usable = tas_usable,
+       .switch_clock = tas_switch_clock,
+#ifdef CONFIG_PM
+       .suspend = _tas_suspend,
+       .resume = _tas_resume,
+#endif
+};
+
+static int tas_init_codec(struct aoa_codec *codec)
+{
+       struct tas *tas = codec_to_tas(codec);
+       int err;
+
+       if (!tas->codec.gpio || !tas->codec.gpio->methods) {
+               printk(KERN_ERR PFX "gpios not assigned!!\n");
+               return -EINVAL;
+       }
+
+       if (tas_reset_init(tas)) {
+               printk(KERN_ERR PFX "tas failed to initialise\n");
+               return -ENXIO;
+       }
+       tas->hw_enabled = 1;
+
+       if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
+                                                  aoa_get_card(),
+                                                  &tas_codec_info, tas)) {
+               printk(KERN_ERR PFX "error attaching tas to soundbus\n");
+               return -ENODEV;
+       }
+
+       if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) {
+               printk(KERN_ERR PFX "failed to create tas snd device!\n");
+               return -ENODEV;
+       }
+       err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas));
+       if (err)
+               goto error;
+
+       return 0;
+ error:
+       tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
+       snd_device_free(aoa_get_card(), tas);
+       return err;
+}
+
+static void tas_exit_codec(struct aoa_codec *codec)
+{
+       struct tas *tas = codec_to_tas(codec);
+
+       if (!tas->codec.soundbus_dev)
+               return;
+       tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
+}
+       
+
+static struct i2c_driver tas_driver;
+
+static int tas_create(struct i2c_adapter *adapter,
+                      struct device_node *node,
+                      int addr)
+{
+       struct tas *tas;
+
+       tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
+
+       if (!tas)
+               return -ENOMEM;
+
+       tas->i2c.driver = &tas_driver;
+       tas->i2c.adapter = adapter;
+       tas->i2c.addr = addr;
+       /* seems that half is a saner default */
+       tas->drc_range = TAS3004_DRC_MAX / 2;
+       strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1);
+
+       if (i2c_attach_client(&tas->i2c)) {
+               printk(KERN_ERR PFX "failed to attach to i2c\n");
+               goto fail;
+       }
+
+       strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1);
+       tas->codec.owner = THIS_MODULE;
+       tas->codec.init = tas_init_codec;
+       tas->codec.exit = tas_exit_codec;
+       tas->codec.node = of_node_get(node);
+
+       if (aoa_codec_register(&tas->codec)) {
+               goto detach;
+       }
+       printk(KERN_DEBUG
+              "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n",
+              addr, node->full_name);
+       return 0;
+ detach:
+       i2c_detach_client(&tas->i2c);
+ fail:
+       kfree(tas);
+       return -EINVAL;
+}
+
+static int tas_i2c_attach(struct i2c_adapter *adapter)
+{
+       struct device_node *busnode, *dev = NULL;
+       struct pmac_i2c_bus *bus;
+
+       bus = pmac_i2c_adapter_to_bus(adapter);
+       if (bus == NULL)
+               return -ENODEV;
+       busnode = pmac_i2c_get_bus_node(bus);
+
+       while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+               if (device_is_compatible(dev, "tas3004")) {
+                       u32 *addr;
+                       printk(KERN_DEBUG PFX "found tas3004\n");
+                       addr = (u32 *) get_property(dev, "reg", NULL);
+                       if (!addr)
+                               continue;
+                       return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f);
+               }
+               /* older machines have no 'codec' node with a 'compatible'
+                * property that says 'tas3004', they just have a 'deq'
+                * node without any such property... */
+               if (strcmp(dev->name, "deq") == 0) {
+                       u32 *_addr, addr;
+                       printk(KERN_DEBUG PFX "found 'deq' node\n");
+                       _addr = (u32 *) get_property(dev, "i2c-address", NULL);
+                       if (!_addr)
+                               continue;
+                       addr = ((*_addr) >> 1) & 0x7f;
+                       /* now, if the address doesn't match any of the two
+                        * that a tas3004 can have, we cannot handle this.
+                        * I doubt it ever happens but hey. */
+                       if (addr != 0x34 && addr != 0x35)
+                               continue;
+                       return tas_create(adapter, dev, addr);
+               }
+       }
+       return -ENODEV;
+}
+
+static int tas_i2c_detach(struct i2c_client *client)
+{
+       struct tas *tas = container_of(client, struct tas, i2c);
+       int err;
+       u8 tmp = TAS_ACR_ANALOG_PDOWN;
+
+       if ((err = i2c_detach_client(client)))
+               return err;
+       aoa_codec_unregister(&tas->codec);
+       of_node_put(tas->codec.node);
+
+       /* power down codec chip */
+       tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
+
+       kfree(tas);
+       return 0;
+}
+
+static struct i2c_driver tas_driver = {
+       .driver = {
+               .name = "aoa_codec_tas",
+               .owner = THIS_MODULE,
+       },
+       .attach_adapter = tas_i2c_attach,
+       .detach_client = tas_i2c_detach,
+};
+
+static int __init tas_init(void)
+{
+       return i2c_add_driver(&tas_driver);
+}
+
+static void __exit tas_exit(void)
+{
+       i2c_del_driver(&tas_driver);
+}
+
+module_init(tas_init);
+module_exit(tas_exit);
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h
new file mode 100644 (file)
index 0000000..ae177e3
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Apple Onboard Audio driver for tas codec (header)
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __SND_AOA_CODECTASH
+#define __SND_AOA_CODECTASH
+
+#define TAS_REG_MCS    0x01    /* main control */
+#      define TAS_MCS_FASTLOAD         (1<<7)
+#      define TAS_MCS_SCLK64           (1<<6)
+#      define TAS_MCS_SPORT_MODE_MASK  (3<<4)
+#      define TAS_MCS_SPORT_MODE_I2S   (2<<4)
+#      define TAS_MCS_SPORT_MODE_RJ    (1<<4)
+#      define TAS_MCS_SPORT_MODE_LJ    (0<<4)
+#      define TAS_MCS_SPORT_WL_MASK    (3<<0)
+#      define TAS_MCS_SPORT_WL_16BIT   (0<<0)
+#      define TAS_MCS_SPORT_WL_18BIT   (1<<0)
+#      define TAS_MCS_SPORT_WL_20BIT   (2<<0)
+#      define TAS_MCS_SPORT_WL_24BIT   (3<<0)
+
+#define TAS_REG_DRC    0x02
+#define TAS_REG_VOL    0x04
+#define TAS_REG_TREBLE 0x05
+#define TAS_REG_BASS   0x06
+#define TAS_REG_LMIX   0x07
+#define TAS_REG_RMIX   0x08
+
+#define TAS_REG_ACR    0x40    /* analog control */
+#      define TAS_ACR_B_MONAUREAL      (1<<7)
+#      define TAS_ACR_B_MON_SEL_RIGHT  (1<<6)
+#      define TAS_ACR_DEEMPH_MASK      (3<<2)
+#      define TAS_ACR_DEEMPH_OFF       (0<<2)
+#      define TAS_ACR_DEEMPH_48KHz     (1<<2)
+#      define TAS_ACR_DEEMPH_44KHz     (2<<2)
+#      define TAS_ACR_INPUT_B          (1<<1)
+#      define TAS_ACR_ANALOG_PDOWN     (1<<0)
+
+#define TAS_REG_MCS2   0x43    /* main control 2 */
+#      define TAS_MCS2_ALLPASS         (1<<1)
+
+#define TAS_REG_LEFT_BIQUAD6   0x10
+#define TAS_REG_RIGHT_BIQUAD6  0x19
+
+#define TAS_REG_LEFT_LOUDNESS          0x21
+#define TAS_REG_RIGHT_LOUDNESS         0x22
+#define TAS_REG_LEFT_LOUDNESS_GAIN     0x23
+#define TAS_REG_RIGHT_LOUDNESS_GAIN    0x24
+
+#define TAS3001_DRC_MAX                0x5f
+#define TAS3004_DRC_MAX                0xef
+
+#endif /* __SND_AOA_CODECTASH */
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
new file mode 100644 (file)
index 0000000..3c7d1d8
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Apple Onboard Audio driver for Toonie codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This is a driver for the toonie codec chip. This chip is present
+ * on the Mac Mini and is nothing but a DAC.
+ */
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("toonie codec driver for snd-aoa");
+
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+
+#define PFX "snd-aoa-codec-toonie: "
+
+struct toonie {
+       struct aoa_codec        codec;
+};
+#define codec_to_toonie(c) container_of(c, struct toonie, codec)
+
+static int toonie_dev_register(struct snd_device *dev)
+{
+       return 0;
+}
+
+static struct snd_device_ops ops = {
+       .dev_register = toonie_dev_register,
+};
+
+static struct transfer_info toonie_transfers[] = {
+       /* This thing *only* has analog output,
+        * the rates are taken from Info.plist
+        * from Darwin. */
+       {
+               .formats = SNDRV_PCM_FMTBIT_S16_BE |
+                          SNDRV_PCM_FMTBIT_S24_BE,
+               .rates = SNDRV_PCM_RATE_32000 |
+                        SNDRV_PCM_RATE_44100 |
+                        SNDRV_PCM_RATE_48000 |
+                        SNDRV_PCM_RATE_88200 |
+                        SNDRV_PCM_RATE_96000,
+       },
+       {}
+};
+
+static int toonie_usable(struct codec_info_item *cii,
+                        struct transfer_info *ti,
+                        struct transfer_info *out)
+{
+       return 1;
+}
+
+#ifdef CONFIG_PM
+static int toonie_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+       /* can we turn it off somehow? */
+       return 0;
+}
+
+static int toonie_resume(struct codec_info_item *cii)
+{
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct codec_info toonie_codec_info = {
+       .transfers = toonie_transfers,
+       .sysclock_factor = 256,
+       .bus_factor = 64,
+       .owner = THIS_MODULE,
+       .usable = toonie_usable,
+#ifdef CONFIG_PM
+       .suspend = toonie_suspend,
+       .resume = toonie_resume,
+#endif
+};
+
+static int toonie_init_codec(struct aoa_codec *codec)
+{
+       struct toonie *toonie = codec_to_toonie(codec);
+
+       /* nothing connected? what a joke! */
+       if (toonie->codec.connected != 1)
+               return -ENOTCONN;
+
+       if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) {
+               printk(KERN_ERR PFX "failed to create toonie snd device!\n");
+               return -ENODEV;
+       }
+
+       if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev,
+                                                    aoa_get_card(),
+                                                    &toonie_codec_info, toonie)) {
+               printk(KERN_ERR PFX "error creating toonie pcm\n");
+               snd_device_free(aoa_get_card(), toonie);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void toonie_exit_codec(struct aoa_codec *codec)
+{
+       struct toonie *toonie = codec_to_toonie(codec);
+
+       if (!toonie->codec.soundbus_dev) {
+               printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n");
+               return;
+       }
+       toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie);
+}
+
+static struct toonie *toonie;
+
+static int __init toonie_init(void)
+{
+       toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL);
+
+       if (!toonie)
+               return -ENOMEM;
+
+       strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
+       toonie->codec.owner = THIS_MODULE;
+       toonie->codec.init = toonie_init_codec;
+       toonie->codec.exit = toonie_exit_codec;
+                                        
+       if (aoa_codec_register(&toonie->codec)) {
+               kfree(toonie);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void __exit toonie_exit(void)
+{
+       aoa_codec_unregister(&toonie->codec);
+       kfree(toonie);
+}
+
+module_init(toonie_init);
+module_exit(toonie_exit);
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile
new file mode 100644 (file)
index 0000000..62dc728
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_SND_AOA) += snd-aoa.o
+snd-aoa-objs := snd-aoa-core.o \
+               snd-aoa-alsa.o \
+               snd-aoa-gpio-pmf.o \
+               snd-aoa-gpio-feature.o
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c
new file mode 100644 (file)
index 0000000..b42fdea
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Apple Onboard Audio Alsa helpers
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#include <linux/module.h>
+#include "snd-aoa-alsa.h"
+
+static int index = -1;
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "index for AOA sound card.");
+
+static struct aoa_card *aoa_card;
+
+int aoa_alsa_init(char *name, struct module *mod)
+{
+       struct snd_card *alsa_card;
+       int err;
+
+       if (aoa_card)
+               /* cannot be EEXIST due to usage in aoa_fabric_register */
+               return -EBUSY;
+
+       alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card));
+       if (!alsa_card)
+               return -ENOMEM;
+       aoa_card = alsa_card->private_data;
+       aoa_card->alsa_card = alsa_card;
+       strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
+       strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
+       strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
+       strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
+       err = snd_card_register(aoa_card->alsa_card);
+       if (err < 0) {
+               printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");
+               snd_card_free(aoa_card->alsa_card);
+               aoa_card = NULL;
+               return err;
+       }
+       return 0;
+}
+
+struct snd_card *aoa_get_card(void)
+{
+       if (aoa_card)
+               return aoa_card->alsa_card;
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(aoa_get_card);
+
+void aoa_alsa_cleanup(void)
+{
+       if (aoa_card) {
+               snd_card_free(aoa_card->alsa_card);
+               aoa_card = NULL;
+       }
+}
+
+int aoa_snd_device_new(snd_device_type_t type,
+        void * device_data, struct snd_device_ops * ops)
+{
+       struct snd_card *card = aoa_get_card();
+       int err;
+       
+       if (!card) return -ENOMEM;
+
+       err = snd_device_new(card, type, device_data, ops);
+       if (err) {
+               printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err);
+               return err;
+       }
+       err = snd_device_register(card, device_data);
+       if (err) {
+               printk(KERN_ERR "snd-aoa: failed to register "
+                               "snd device (%d)\n", err);
+               printk(KERN_ERR "snd-aoa: have you forgotten the "
+                               "dev_register callback?\n");
+               snd_device_free(card, device_data);
+       }
+       return err;
+}
+EXPORT_SYMBOL_GPL(aoa_snd_device_new);
+
+int aoa_snd_ctl_add(struct snd_kcontrol* control)
+{
+       int err;
+
+       if (!aoa_card) return -ENODEV;
+
+       err = snd_ctl_add(aoa_card->alsa_card, control);
+       if (err)
+               printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n",
+                      err);
+       return err;
+}
+EXPORT_SYMBOL_GPL(aoa_snd_ctl_add);
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h
new file mode 100644 (file)
index 0000000..660d2f1
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Apple Onboard Audio Alsa private helpers
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#ifndef __SND_AOA_ALSA_H
+#define __SND_AOA_ALSA_H
+#include "../aoa.h"
+
+extern int aoa_alsa_init(char *name, struct module *mod);
+extern void aoa_alsa_cleanup(void);
+
+#endif /* __SND_AOA_ALSA_H */
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c
new file mode 100644 (file)
index 0000000..ecd2d82
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Apple Onboard Audio driver core
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include "../aoa.h"
+#include "snd-aoa-alsa.h"
+
+MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+
+/* We allow only one fabric. This simplifies things,
+ * and more don't really make that much sense */
+static struct aoa_fabric *fabric;
+static LIST_HEAD(codec_list);
+
+static int attach_codec_to_fabric(struct aoa_codec *c)
+{
+       int err;
+
+       if (!try_module_get(c->owner))
+               return -EBUSY;
+       /* found_codec has to be assigned */
+       err = -ENOENT;
+       if (fabric->found_codec)
+               err = fabric->found_codec(c);
+       if (err) {
+               module_put(c->owner);
+               printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n",
+                               c->name);
+               return err;
+       }
+       c->fabric = fabric;
+
+       err = 0;
+       if (c->init)
+               err = c->init(c);
+       if (err) {
+               printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name);
+               c->fabric = NULL;
+               if (fabric->remove_codec)
+                       fabric->remove_codec(c);
+               module_put(c->owner);
+               return err;
+       }
+       if (fabric->attached_codec)
+               fabric->attached_codec(c);
+       return 0;
+}
+
+int aoa_codec_register(struct aoa_codec *codec)
+{
+       int err = 0;
+
+       /* if there's a fabric already, we can tell if we
+        * will want to have this codec, so propagate error
+        * through. Otherwise, this will happen later... */
+       if (fabric)
+               err = attach_codec_to_fabric(codec);
+       if (!err)
+               list_add(&codec->list, &codec_list);
+       return err;
+}
+EXPORT_SYMBOL_GPL(aoa_codec_register);
+
+void aoa_codec_unregister(struct aoa_codec *codec)
+{
+       list_del(&codec->list);
+       if (codec->fabric && codec->exit)
+               codec->exit(codec);
+       if (fabric && fabric->remove_codec)
+               fabric->remove_codec(codec);
+       codec->fabric = NULL;
+       module_put(codec->owner);
+}
+EXPORT_SYMBOL_GPL(aoa_codec_unregister);
+
+int aoa_fabric_register(struct aoa_fabric *new_fabric)
+{
+       struct aoa_codec *c;
+       int err;
+
+       /* allow querying for presence of fabric
+        * (i.e. do this test first!) */
+       if (new_fabric == fabric) {
+               err = -EALREADY;
+               goto attach;
+       }
+       if (fabric)
+               return -EEXIST;
+       if (!new_fabric)
+               return -EINVAL;
+
+       err = aoa_alsa_init(new_fabric->name, new_fabric->owner);
+       if (err)
+               return err;
+
+       fabric = new_fabric;
+
+ attach:
+       list_for_each_entry(c, &codec_list, list) {
+               if (c->fabric != fabric)
+                       attach_codec_to_fabric(c);
+       }
+       return err;
+}
+EXPORT_SYMBOL_GPL(aoa_fabric_register);
+
+void aoa_fabric_unregister(struct aoa_fabric *old_fabric)
+{
+       struct aoa_codec *c;
+
+       if (fabric != old_fabric)
+               return;
+
+       list_for_each_entry(c, &codec_list, list) {
+               if (c->fabric)
+                       aoa_fabric_unlink_codec(c);
+       }
+
+       aoa_alsa_cleanup();
+
+       fabric = NULL;
+}
+EXPORT_SYMBOL_GPL(aoa_fabric_unregister);
+
+void aoa_fabric_unlink_codec(struct aoa_codec *codec)
+{
+       if (!codec->fabric) {
+               printk(KERN_ERR "snd-aoa: fabric unassigned "
+                               "in aoa_fabric_unlink_codec\n");
+               dump_stack();
+               return;
+       }
+       if (codec->exit)
+               codec->exit(codec);
+       if (codec->fabric->remove_codec)
+               codec->fabric->remove_codec(codec);
+       codec->fabric = NULL;
+       module_put(codec->owner);
+}
+EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec);
+
+static int __init aoa_init(void)
+{
+       return 0;
+}
+
+static void __exit aoa_exit(void)
+{
+       aoa_alsa_cleanup();
+}
+
+module_init(aoa_init);
+module_exit(aoa_exit);
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
new file mode 100644 (file)
index 0000000..f69d333
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Apple Onboard Audio feature call GPIO control
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ * This file contains the GPIO control routines for 
+ * direct (through feature calls) access to the GPIO
+ * registers.
+ */
+
+#include <asm/pmac_feature.h>
+#include <linux/interrupt.h>
+#include "../aoa.h"
+
+/* TODO: these are 20 global variables
+ * that aren't used on most machines...
+ * Move them into a dynamically allocated
+ * structure and use that.
+ */
+
+/* these are the GPIO numbers (register addresses as offsets into
+ * the GPIO space) */
+static int headphone_mute_gpio;
+static int amp_mute_gpio;
+static int lineout_mute_gpio;
+static int hw_reset_gpio;
+static int lineout_detect_gpio;
+static int headphone_detect_gpio;
+static int linein_detect_gpio;
+
+/* see the SWITCH_GPIO macro */
+static int headphone_mute_gpio_activestate;
+static int amp_mute_gpio_activestate;
+static int lineout_mute_gpio_activestate;
+static int hw_reset_gpio_activestate;
+static int lineout_detect_gpio_activestate;
+static int headphone_detect_gpio_activestate;
+static int linein_detect_gpio_activestate;
+
+/* node pointers that we save when getting the GPIO number
+ * to get the interrupt later */
+static struct device_node *lineout_detect_node;
+static struct device_node *linein_detect_node;
+static struct device_node *headphone_detect_node;
+
+static int lineout_detect_irq;
+static int linein_detect_irq;
+static int headphone_detect_irq;
+
+static struct device_node *get_gpio(char *name,
+                                   char *altname,
+                                   int *gpioptr,
+                                   int *gpioactiveptr)
+{
+       struct device_node *np, *gpio;
+       u32 *reg;
+       char *audio_gpio;
+
+       *gpioptr = -1;
+
+       /* check if we can get it the easy way ... */
+       np = of_find_node_by_name(NULL, name);
+       if (!np) {
+               /* some machines have only gpioX/extint-gpioX nodes,
+                * and an audio-gpio property saying what it is ...
+                * So what we have to do is enumerate all children
+                * of the gpio node and check them all. */
+               gpio = of_find_node_by_name(NULL, "gpio");
+               if (!gpio)
+                       return NULL;
+               while ((np = of_get_next_child(gpio, np))) {
+                       audio_gpio = get_property(np, "audio-gpio", NULL);
+                       if (!audio_gpio)
+                               continue;
+                       if (strcmp(audio_gpio, name) == 0)
+                               break;
+                       if (altname && (strcmp(audio_gpio, altname) == 0))
+                               break;
+               }
+               /* still not found, assume not there */
+               if (!np)
+                       return NULL;
+       }
+
+       reg = (u32 *)get_property(np, "reg", NULL);
+       if (!reg)
+               return NULL;
+
+       *gpioptr = *reg;
+
+       /* this is a hack, usually the GPIOs 'reg' property
+        * should have the offset based from the GPIO space
+        * which is at 0x50, but apparently not always... */
+       if (*gpioptr < 0x50)
+               *gpioptr += 0x50;
+
+       reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
+       if (!reg)
+               /* Apple seems to default to 1, but
+                * that doesn't seem right at least on most
+                * machines. So until proven that the opposite
+                * is necessary, we default to 0
+                * (which, incidentally, snd-powermac also does...) */
+               *gpioactiveptr = 0;
+       else
+               *gpioactiveptr = *reg;
+
+       return np;
+}
+
+static void get_irq(struct device_node * np, int *irqptr)
+{
+       if (np)
+               *irqptr = irq_of_parse_and_map(np, 0);
+       else
+               *irqptr = NO_IRQ;
+}
+
+/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */
+#define SWITCH_GPIO(name, v, on)                               \
+       (((v)&~1) | ((on)?                                      \
+                       (name##_gpio_activestate==0?4:5):       \
+                       (name##_gpio_activestate==0?5:4)))
+
+#define FTR_GPIO(name, bit)                                    \
+static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\
+{                                                              \
+       int v;                                                  \
+                                                               \
+       if (unlikely(!rt)) return;                              \
+                                                               \
+       if (name##_mute_gpio < 0)                               \
+               return;                                         \
+                                                               \
+       v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL,         \
+                             name##_mute_gpio,                 \
+                             0);                               \
+                                                               \
+       /* muted = !on... */                                    \
+       v = SWITCH_GPIO(name##_mute, v, !on);                   \
+                                                               \
+       pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,            \
+                         name##_mute_gpio, v);                 \
+                                                               \
+       rt->implementation_private &= ~(1<<bit);                \
+       rt->implementation_private |= (!!on << bit);            \
+}                                                              \
+static int ftr_gpio_get_##name(struct gpio_runtime *rt)                \
+{                                                              \
+       if (unlikely(!rt)) return 0;                            \
+       return (rt->implementation_private>>bit)&1;             \
+}
+
+FTR_GPIO(headphone, 0);
+FTR_GPIO(amp, 1);
+FTR_GPIO(lineout, 2);
+
+static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
+{
+       int v;
+
+       if (unlikely(!rt)) return;
+       if (hw_reset_gpio < 0)
+               return;
+
+       v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL,
+                             hw_reset_gpio, 0);
+       v = SWITCH_GPIO(hw_reset, v, on);
+       pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+                         hw_reset_gpio, v);
+}
+
+static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
+{
+       int saved;
+
+       if (unlikely(!rt)) return;
+       saved = rt->implementation_private;
+       ftr_gpio_set_headphone(rt, 0);
+       ftr_gpio_set_amp(rt, 0);
+       ftr_gpio_set_lineout(rt, 0);
+       rt->implementation_private = saved;
+}
+
+static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
+{
+       int s;
+
+       if (unlikely(!rt)) return;
+       s = rt->implementation_private;
+       ftr_gpio_set_headphone(rt, (s>>0)&1);
+       ftr_gpio_set_amp(rt, (s>>1)&1);
+       ftr_gpio_set_lineout(rt, (s>>2)&1);
+}
+
+static void ftr_handle_notify(void *data)
+{
+       struct gpio_notification *notif = data;
+
+       mutex_lock(&notif->mutex);
+       if (notif->notify)
+               notif->notify(notif->data);
+       mutex_unlock(&notif->mutex);
+}
+
+static void gpio_enable_dual_edge(int gpio)
+{
+       int v;
+
+       if (gpio == -1)
+               return;
+       v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0);
+       v |= 0x80; /* enable dual edge */
+       pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio, v);
+}
+
+static void ftr_gpio_init(struct gpio_runtime *rt)
+{
+       get_gpio("headphone-mute", NULL,
+                &headphone_mute_gpio,
+                &headphone_mute_gpio_activestate);
+       get_gpio("amp-mute", NULL,
+                &amp_mute_gpio,
+                &amp_mute_gpio_activestate);
+       get_gpio("lineout-mute", NULL,
+                &lineout_mute_gpio,
+                &lineout_mute_gpio_activestate);
+       get_gpio("hw-reset", "audio-hw-reset",
+                &hw_reset_gpio,
+                &hw_reset_gpio_activestate);
+
+       headphone_detect_node = get_gpio("headphone-detect", NULL,
+                                        &headphone_detect_gpio,
+                                        &headphone_detect_gpio_activestate);
+       /* go Apple, and thanks for giving these different names
+        * across the board... */
+       lineout_detect_node = get_gpio("lineout-detect", "line-output-detect",
+                                      &lineout_detect_gpio,
+                                      &lineout_detect_gpio_activestate);
+       linein_detect_node = get_gpio("linein-detect", "line-input-detect",
+                                     &linein_detect_gpio,
+                                     &linein_detect_gpio_activestate);
+
+       gpio_enable_dual_edge(headphone_detect_gpio);
+       gpio_enable_dual_edge(lineout_detect_gpio);
+       gpio_enable_dual_edge(linein_detect_gpio);
+
+       get_irq(headphone_detect_node, &headphone_detect_irq);
+       get_irq(lineout_detect_node, &lineout_detect_irq);
+       get_irq(linein_detect_node, &linein_detect_irq);
+
+       ftr_gpio_all_amps_off(rt);
+       rt->implementation_private = 0;
+       INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify,
+                 &rt->headphone_notify);
+       INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify,
+                 &rt->line_in_notify);
+       INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify,
+                 &rt->line_out_notify);
+       mutex_init(&rt->headphone_notify.mutex);
+       mutex_init(&rt->line_in_notify.mutex);
+       mutex_init(&rt->line_out_notify.mutex);
+}
+
+static void ftr_gpio_exit(struct gpio_runtime *rt)
+{
+       ftr_gpio_all_amps_off(rt);
+       rt->implementation_private = 0;
+       if (rt->headphone_notify.notify)
+               free_irq(headphone_detect_irq, &rt->headphone_notify);
+       if (rt->line_in_notify.gpio_private)
+               free_irq(linein_detect_irq, &rt->line_in_notify);
+       if (rt->line_out_notify.gpio_private)
+               free_irq(lineout_detect_irq, &rt->line_out_notify);
+       cancel_delayed_work(&rt->headphone_notify.work);
+       cancel_delayed_work(&rt->line_in_notify.work);
+       cancel_delayed_work(&rt->line_out_notify.work);
+       flush_scheduled_work();
+       mutex_destroy(&rt->headphone_notify.mutex);
+       mutex_destroy(&rt->line_in_notify.mutex);
+       mutex_destroy(&rt->line_out_notify.mutex);
+}
+
+static irqreturn_t ftr_handle_notify_irq(int xx,
+                                        void *data,
+                                        struct pt_regs *regs)
+{
+       struct gpio_notification *notif = data;
+
+       schedule_work(&notif->work);
+
+       return IRQ_HANDLED;
+}
+
+static int ftr_set_notify(struct gpio_runtime *rt,
+                         enum notify_type type,
+                         notify_func_t notify,
+                         void *data)
+{
+       struct gpio_notification *notif;
+       notify_func_t old;
+       int irq;
+       char *name;
+       int err = -EBUSY;
+
+       switch (type) {
+       case AOA_NOTIFY_HEADPHONE:
+               notif = &rt->headphone_notify;
+               name = "headphone-detect";
+               irq = headphone_detect_irq;
+               break;
+       case AOA_NOTIFY_LINE_IN:
+               notif = &rt->line_in_notify;
+               name = "linein-detect";
+               irq = linein_detect_irq;
+               break;
+       case AOA_NOTIFY_LINE_OUT:
+               notif = &rt->line_out_notify;
+               name = "lineout-detect";
+               irq = lineout_detect_irq;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (irq == NO_IRQ)
+               return -ENODEV;
+
+       mutex_lock(&notif->mutex);
+
+       old = notif->notify;
+
+       if (!old && !notify) {
+               err = 0;
+               goto out_unlock;
+       }
+
+       if (old && notify) {
+               if (old == notify && notif->data == data)
+                       err = 0;
+               goto out_unlock;
+       }
+
+       if (old && !notify)
+               free_irq(irq, notif);
+
+       if (!old && notify) {
+               err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif);
+               if (err)
+                       goto out_unlock;
+       }
+
+       notif->notify = notify;
+       notif->data = data;
+
+       err = 0;
+ out_unlock:
+       mutex_unlock(&notif->mutex);
+       return err;
+}
+
+static int ftr_get_detect(struct gpio_runtime *rt,
+                         enum notify_type type)
+{
+       int gpio, ret, active;
+
+       switch (type) {
+       case AOA_NOTIFY_HEADPHONE:
+               gpio = headphone_detect_gpio;
+               active = headphone_detect_gpio_activestate;
+               break;
+       case AOA_NOTIFY_LINE_IN:
+               gpio = linein_detect_gpio;
+               active = linein_detect_gpio_activestate;
+               break;
+       case AOA_NOTIFY_LINE_OUT:
+               gpio = lineout_detect_gpio;
+               active = lineout_detect_gpio_activestate;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (gpio == -1)
+               return -ENODEV;
+
+       ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0);
+       if (ret < 0)
+               return ret;
+       return ((ret >> 1) & 1) == active;
+}
+
+static struct gpio_methods methods = {
+       .init                   = ftr_gpio_init,
+       .exit                   = ftr_gpio_exit,
+       .all_amps_off           = ftr_gpio_all_amps_off,
+       .all_amps_restore       = ftr_gpio_all_amps_restore,
+       .set_headphone          = ftr_gpio_set_headphone,
+       .set_speakers           = ftr_gpio_set_amp,
+       .set_lineout            = ftr_gpio_set_lineout,
+       .set_hw_reset           = ftr_gpio_set_hw_reset,
+       .get_headphone          = ftr_gpio_get_headphone,
+       .get_speakers           = ftr_gpio_get_amp,
+       .get_lineout            = ftr_gpio_get_lineout,
+       .set_notify             = ftr_set_notify,
+       .get_detect             = ftr_get_detect,
+};
+
+struct gpio_methods *ftr_gpio_methods = &methods;
+EXPORT_SYMBOL_GPL(ftr_gpio_methods);
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
new file mode 100644 (file)
index 0000000..2836c32
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Apple Onboard Audio pmf GPIOs
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+#include "../aoa.h"
+
+#define PMF_GPIO(name, bit)                                    \
+static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\
+{                                                              \
+       struct pmf_args args = { .count = 1, .u[0].v = !on };   \
+       int rc;                                                 \
+                                                       \
+       if (unlikely(!rt)) return;                              \
+       rc = pmf_call_function(rt->node, #name "-mute", &args); \
+       if (rc && rc != -ENODEV)                                \
+               printk(KERN_WARNING "pmf_gpio_set_" #name       \
+               " failed, rc: %d\n", rc);                       \
+       rt->implementation_private &= ~(1<<bit);                \
+       rt->implementation_private |= (!!on << bit);            \
+}                                                              \
+static int pmf_gpio_get_##name(struct gpio_runtime *rt)                \
+{                                                              \
+       if (unlikely(!rt)) return 0;                            \
+       return (rt->implementation_private>>bit)&1;             \
+}
+
+PMF_GPIO(headphone, 0);
+PMF_GPIO(amp, 1);
+PMF_GPIO(lineout, 2);
+
+static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
+{
+       struct pmf_args args = { .count = 1, .u[0].v = !!on };
+       int rc;
+
+       if (unlikely(!rt)) return;
+       rc = pmf_call_function(rt->node, "hw-reset", &args);
+       if (rc)
+               printk(KERN_WARNING "pmf_gpio_set_hw_reset"
+                      " failed, rc: %d\n", rc);
+}
+
+static void pmf_gpio_all_amps_off(struct gpio_runtime *rt)
+{
+       int saved;
+
+       if (unlikely(!rt)) return;
+       saved = rt->implementation_private;
+       pmf_gpio_set_headphone(rt, 0);
+       pmf_gpio_set_amp(rt, 0);
+       pmf_gpio_set_lineout(rt, 0);
+       rt->implementation_private = saved;
+}
+
+static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt)
+{
+       int s;
+
+       if (unlikely(!rt)) return;
+       s = rt->implementation_private;
+       pmf_gpio_set_headphone(rt, (s>>0)&1);
+       pmf_gpio_set_amp(rt, (s>>1)&1);
+       pmf_gpio_set_lineout(rt, (s>>2)&1);
+}
+
+static void pmf_handle_notify(void *data)
+{
+       struct gpio_notification *notif = data;
+
+       mutex_lock(&notif->mutex);
+       if (notif->notify)
+               notif->notify(notif->data);
+       mutex_unlock(&notif->mutex);
+}
+
+static void pmf_gpio_init(struct gpio_runtime *rt)
+{
+       pmf_gpio_all_amps_off(rt);
+       rt->implementation_private = 0;
+       INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify,
+                 &rt->headphone_notify);
+       INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify,
+                 &rt->line_in_notify);
+       INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify,
+                 &rt->line_out_notify);
+       mutex_init(&rt->headphone_notify.mutex);
+       mutex_init(&rt->line_in_notify.mutex);
+       mutex_init(&rt->line_out_notify.mutex);
+}
+
+static void pmf_gpio_exit(struct gpio_runtime *rt)
+{
+       pmf_gpio_all_amps_off(rt);
+       rt->implementation_private = 0;
+
+       if (rt->headphone_notify.gpio_private)
+               pmf_unregister_irq_client(rt->headphone_notify.gpio_private);
+       if (rt->line_in_notify.gpio_private)
+               pmf_unregister_irq_client(rt->line_in_notify.gpio_private);
+       if (rt->line_out_notify.gpio_private)
+               pmf_unregister_irq_client(rt->line_out_notify.gpio_private);
+
+       /* make sure no work is pending before freeing
+        * all things */
+       cancel_delayed_work(&rt->headphone_notify.work);
+       cancel_delayed_work(&rt->line_in_notify.work);
+       cancel_delayed_work(&rt->line_out_notify.work);
+       flush_scheduled_work();
+
+       mutex_destroy(&rt->headphone_notify.mutex);
+       mutex_destroy(&rt->line_in_notify.mutex);
+       mutex_destroy(&rt->line_out_notify.mutex);
+
+       if (rt->headphone_notify.gpio_private)
+               kfree(rt->headphone_notify.gpio_private);
+       if (rt->line_in_notify.gpio_private)
+               kfree(rt->line_in_notify.gpio_private);
+       if (rt->line_out_notify.gpio_private)
+               kfree(rt->line_out_notify.gpio_private);
+}
+
+static void pmf_handle_notify_irq(void *data)
+{
+       struct gpio_notification *notif = data;
+
+       schedule_work(&notif->work);
+}
+
+static int pmf_set_notify(struct gpio_runtime *rt,
+                         enum notify_type type,
+                         notify_func_t notify,
+                         void *data)
+{
+       struct gpio_notification *notif;
+       notify_func_t old;
+       struct pmf_irq_client *irq_client;
+       char *name;
+       int err = -EBUSY;
+
+       switch (type) {
+       case AOA_NOTIFY_HEADPHONE:
+               notif = &rt->headphone_notify;
+               name = "headphone-detect";
+               break;
+       case AOA_NOTIFY_LINE_IN:
+               notif = &rt->line_in_notify;
+               name = "linein-detect";
+               break;
+       case AOA_NOTIFY_LINE_OUT:
+               notif = &rt->line_out_notify;
+               name = "lineout-detect";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       mutex_lock(&notif->mutex);
+
+       old = notif->notify;
+
+       if (!old && !notify) {
+               err = 0;
+               goto out_unlock;
+       }
+
+       if (old && notify) {
+               if (old == notify && notif->data == data)
+                       err = 0;
+               goto out_unlock;
+       }
+
+       if (old && !notify) {
+               irq_client = notif->gpio_private;
+               pmf_unregister_irq_client(irq_client);
+               kfree(irq_client);
+               notif->gpio_private = NULL;
+       }
+       if (!old && notify) {
+               irq_client = kzalloc(sizeof(struct pmf_irq_client),
+                                    GFP_KERNEL);
+               irq_client->data = notif;
+               irq_client->handler = pmf_handle_notify_irq;
+               irq_client->owner = THIS_MODULE;
+               err = pmf_register_irq_client(rt->node,
+                                             name,
+                                             irq_client);
+               if (err) {
+                       printk(KERN_ERR "snd-aoa: gpio layer failed to"
+                                       " register %s irq (%d)\n", name, err);
+                       kfree(irq_client);
+                       goto out_unlock;
+               }
+               notif->gpio_private = irq_client;
+       }
+       notif->notify = notify;
+       notif->data = data;
+
+       err = 0;
+ out_unlock:
+       mutex_unlock(&notif->mutex);
+       return err;
+}
+
+static int pmf_get_detect(struct gpio_runtime *rt,
+                         enum notify_type type)
+{
+       char *name;
+       int err = -EBUSY, ret;
+       struct pmf_args args = { .count = 1, .u[0].p = &ret };
+
+       switch (type) {
+       case AOA_NOTIFY_HEADPHONE:
+               name = "headphone-detect";
+               break;
+       case AOA_NOTIFY_LINE_IN:
+               name = "linein-detect";
+               break;
+       case AOA_NOTIFY_LINE_OUT:
+               name = "lineout-detect";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = pmf_call_function(rt->node, name, &args);
+       if (err)
+               return err;
+       return ret;
+}
+
+static struct gpio_methods methods = {
+       .init                   = pmf_gpio_init,
+       .exit                   = pmf_gpio_exit,
+       .all_amps_off           = pmf_gpio_all_amps_off,
+       .all_amps_restore       = pmf_gpio_all_amps_restore,
+       .set_headphone          = pmf_gpio_set_headphone,
+       .set_speakers           = pmf_gpio_set_amp,
+       .set_lineout            = pmf_gpio_set_lineout,
+       .set_hw_reset           = pmf_gpio_set_hw_reset,
+       .get_headphone          = pmf_gpio_get_headphone,
+       .get_speakers           = pmf_gpio_get_amp,
+       .get_lineout            = pmf_gpio_get_lineout,
+       .set_notify             = pmf_set_notify,
+       .get_detect             = pmf_get_detect,
+};
+
+struct gpio_methods *pmf_gpio_methods = &methods;
+EXPORT_SYMBOL_GPL(pmf_gpio_methods);
diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig
new file mode 100644 (file)
index 0000000..c3bc770
--- /dev/null
@@ -0,0 +1,12 @@
+config SND_AOA_FABRIC_LAYOUT
+       tristate "layout-id fabric"
+       depends SND_AOA
+       select SND_AOA_SOUNDBUS
+       select SND_AOA_SOUNDBUS_I2S
+       ---help---
+       This enables the layout-id fabric for the Apple Onboard
+       Audio driver, the module holding it all together
+       based on the device-tree's layout-id property.
+       
+       If you are unsure and have a later Apple machine,
+       compile it as a module.
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile
new file mode 100644 (file)
index 0000000..55fc5e7
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
new file mode 100644 (file)
index 0000000..172eb95
--- /dev/null
@@ -0,0 +1,1129 @@
+/*
+ * Apple Onboard Audio driver -- layout fabric
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This fabric module looks for sound codecs
+ * based on the layout-id property in the device tree.
+ *
+ */
+
+#include <asm/prom.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa");
+
+#define MAX_CODECS_PER_BUS     2
+
+/* These are the connections the layout fabric
+ * knows about. It doesn't really care about the
+ * input ones, but I thought I'd separate them
+ * to give them proper names. The thing is that
+ * Apple usually will distinguish the active output
+ * by GPIOs, while the active input is set directly
+ * on the codec. Hence we here tell the codec what
+ * we think is connected. This information is hard-
+ * coded below ... */
+#define CC_SPEAKERS    (1<<0)
+#define CC_HEADPHONE   (1<<1)
+#define CC_LINEOUT     (1<<2)
+#define CC_DIGITALOUT  (1<<3)
+#define CC_LINEIN      (1<<4)
+#define CC_MICROPHONE  (1<<5)
+#define CC_DIGITALIN   (1<<6)
+/* pretty bogus but users complain...
+ * This is a flag saying that the LINEOUT
+ * should be renamed to HEADPHONE.
+ * be careful with input detection! */
+#define CC_LINEOUT_LABELLED_HEADPHONE  (1<<7)
+
+struct codec_connection {
+       /* CC_ flags from above */
+       int connected;
+       /* codec dependent bit to be set in the aoa_codec.connected field.
+        * This intentionally doesn't have any generic flags because the
+        * fabric has to know the codec anyway and all codecs might have
+        * different connectors */
+       int codec_bit;
+};
+
+struct codec_connect_info {
+       char *name;
+       struct codec_connection *connections;
+};
+
+#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF        (1<<0)
+
+struct layout {
+       unsigned int layout_id;
+       struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
+       int flags;
+       
+       /* if busname is not assigned, we use 'Master' below,
+        * so that our layout table doesn't need to be filled
+        * too much.
+        * We only assign these two if we expect to find more
+        * than one soundbus, i.e. on those machines with
+        * multiple layout-ids */
+       char *busname;
+       int pcmid;
+};
+
+MODULE_ALIAS("sound-layout-36");
+MODULE_ALIAS("sound-layout-41");
+MODULE_ALIAS("sound-layout-45");
+MODULE_ALIAS("sound-layout-47");
+MODULE_ALIAS("sound-layout-48");
+MODULE_ALIAS("sound-layout-49");
+MODULE_ALIAS("sound-layout-50");
+MODULE_ALIAS("sound-layout-51");
+MODULE_ALIAS("sound-layout-56");
+MODULE_ALIAS("sound-layout-57");
+MODULE_ALIAS("sound-layout-58");
+MODULE_ALIAS("sound-layout-60");
+MODULE_ALIAS("sound-layout-61");
+MODULE_ALIAS("sound-layout-62");
+MODULE_ALIAS("sound-layout-64");
+MODULE_ALIAS("sound-layout-65");
+MODULE_ALIAS("sound-layout-66");
+MODULE_ALIAS("sound-layout-67");
+MODULE_ALIAS("sound-layout-68");
+MODULE_ALIAS("sound-layout-69");
+MODULE_ALIAS("sound-layout-70");
+MODULE_ALIAS("sound-layout-72");
+MODULE_ALIAS("sound-layout-76");
+MODULE_ALIAS("sound-layout-80");
+MODULE_ALIAS("sound-layout-82");
+MODULE_ALIAS("sound-layout-84");
+MODULE_ALIAS("sound-layout-86");
+MODULE_ALIAS("sound-layout-90");
+MODULE_ALIAS("sound-layout-92");
+MODULE_ALIAS("sound-layout-94");
+MODULE_ALIAS("sound-layout-96");
+MODULE_ALIAS("sound-layout-98");
+MODULE_ALIAS("sound-layout-100");
+
+/* onyx with all but microphone connected */
+static struct codec_connection onyx_connections_nomic[] = {
+       {
+               .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_DIGITALOUT,
+               .codec_bit = 1,
+       },
+       {
+               .connected = CC_LINEIN,
+               .codec_bit = 2,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+/* onyx on machines without headphone */
+static struct codec_connection onyx_connections_noheadphones[] = {
+       {
+               .connected = CC_SPEAKERS | CC_LINEOUT |
+                            CC_LINEOUT_LABELLED_HEADPHONE,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_DIGITALOUT,
+               .codec_bit = 1,
+       },
+       /* FIXME: are these correct? probably not for all the machines
+        * below ... If not this will need separating. */
+       {
+               .connected = CC_LINEIN,
+               .codec_bit = 2,
+       },
+       {
+               .connected = CC_MICROPHONE,
+               .codec_bit = 3,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+/* onyx on machines with real line-out */
+static struct codec_connection onyx_connections_reallineout[] = {
+       {
+               .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_DIGITALOUT,
+               .codec_bit = 1,
+       },
+       {
+               .connected = CC_LINEIN,
+               .codec_bit = 2,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines without line out */
+static struct codec_connection tas_connections_nolineout[] = {
+       {
+               .connected = CC_SPEAKERS | CC_HEADPHONE,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_LINEIN,
+               .codec_bit = 2,
+       },
+       {
+               .connected = CC_MICROPHONE,
+               .codec_bit = 3,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines with neither line out nor line in */
+static struct codec_connection tas_connections_noline[] = {
+       {
+               .connected = CC_SPEAKERS | CC_HEADPHONE,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_MICROPHONE,
+               .codec_bit = 3,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines without microphone */
+static struct codec_connection tas_connections_nomic[] = {
+       {
+               .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_LINEIN,
+               .codec_bit = 2,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines with everything connected */
+static struct codec_connection tas_connections_all[] = {
+       {
+               .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_LINEIN,
+               .codec_bit = 2,
+       },
+       {
+               .connected = CC_MICROPHONE,
+               .codec_bit = 3,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection toonie_connections[] = {
+       {
+               .connected = CC_SPEAKERS | CC_HEADPHONE,
+               .codec_bit = 0,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection topaz_input[] = {
+       {
+               .connected = CC_DIGITALIN,
+               .codec_bit = 0,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection topaz_output[] = {
+       {
+               .connected = CC_DIGITALOUT,
+               .codec_bit = 1,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection topaz_inout[] = {
+       {
+               .connected = CC_DIGITALIN,
+               .codec_bit = 0,
+       },
+       {
+               .connected = CC_DIGITALOUT,
+               .codec_bit = 1,
+       },
+       {} /* terminate array by .connected == 0 */
+};
+
+static struct layout layouts[] = {
+       /* last PowerBooks (15" Oct 2005) */
+       { .layout_id = 82,
+         .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       /* PowerMac9,1 */
+       { .layout_id = 60,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_reallineout,
+         },
+       },
+       /* PowerMac9,1 */
+       { .layout_id = 61,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       /* PowerBook5,7 */
+       { .layout_id = 64,
+         .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       /* PowerBook5,7 */
+       { .layout_id = 65,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       /* PowerBook5,9 [17" Oct 2005] */
+       { .layout_id = 84,
+         .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       /* PowerMac8,1 */
+       { .layout_id = 45,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       /* Quad PowerMac (analog in, analog/digital out) */
+       { .layout_id = 68,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_nomic,
+         },
+       },
+       /* Quad PowerMac (digital in) */
+       { .layout_id = 69,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+         .busname = "digital in", .pcmid = 1 },
+       /* Early 2005 PowerBook (PowerBook 5,6) */
+       { .layout_id = 70,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nolineout,
+         },
+       },
+       /* PowerBook 5,4 */
+       { .layout_id = 51,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nolineout,
+         },
+       },
+       /* PowerBook6,7 */
+       { .layout_id = 80,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_noline,
+         },
+       },
+       /* PowerBook6,8 */
+       { .layout_id = 72,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nolineout,
+         },
+       },
+       /* PowerMac8,2 */
+       { .layout_id = 86,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_nomic,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       /* PowerBook6,7 */
+       { .layout_id = 92,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nolineout,
+         },
+       },
+       /* PowerMac10,1 (Mac Mini) */
+       { .layout_id = 58,
+         .codecs[0] = {
+               .name = "toonie",
+               .connections = toonie_connections,
+         },
+       },
+       {
+         .layout_id = 96,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       /* unknown, untested, but this comes from Apple */
+       { .layout_id = 41,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_all,
+         },
+       },
+       { .layout_id = 36,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nomic,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_inout,
+         },
+       },
+       { .layout_id = 47,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       { .layout_id = 48,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       { .layout_id = 49,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_nomic,
+         },
+       },
+       { .layout_id = 50,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       { .layout_id = 56,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       { .layout_id = 57,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       { .layout_id = 62,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_output,
+         },
+       },
+       { .layout_id = 66,
+         .codecs[0] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       { .layout_id = 67,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+       },
+       { .layout_id = 76,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_nomic,
+         },
+         .codecs[1] = {
+               .name = "topaz",
+               .connections = topaz_inout,
+         },
+       },
+       { .layout_id = 90,
+         .codecs[0] = {
+               .name = "tas",
+               .connections = tas_connections_noline,
+         },
+       },
+       { .layout_id = 94,
+         .codecs[0] = {
+               .name = "onyx",
+               /* but it has an external mic?? how to select? */
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       { .layout_id = 98,
+         .codecs[0] = {
+               .name = "toonie",
+               .connections = toonie_connections,
+         },
+       },
+       { .layout_id = 100,
+         .codecs[0] = {
+               .name = "topaz",
+               .connections = topaz_input,
+         },
+         .codecs[1] = {
+               .name = "onyx",
+               .connections = onyx_connections_noheadphones,
+         },
+       },
+       {}
+};
+
+static struct layout *find_layout_by_id(unsigned int id)
+{
+       struct layout *l;
+
+       l = layouts;
+       while (l->layout_id) {
+               if (l->layout_id == id)
+                       return l;
+               l++;
+       }
+       return NULL;
+}
+
+static void use_layout(struct layout *l)
+{
+       int i;
+
+       for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+               if (l->codecs[i].name) {
+                       request_module("snd-aoa-codec-%s", l->codecs[i].name);
+               }
+       }
+       /* now we wait for the codecs to call us back */
+}
+
+struct layout_dev;
+
+struct layout_dev_ptr {
+       struct layout_dev *ptr;
+};
+
+struct layout_dev {
+       struct list_head list;
+       struct soundbus_dev *sdev;
+       struct device_node *sound;
+       struct aoa_codec *codecs[MAX_CODECS_PER_BUS];
+       struct layout *layout;
+       struct gpio_runtime gpio;
+
+       /* we need these for headphone/lineout detection */
+       struct snd_kcontrol *headphone_ctrl;
+       struct snd_kcontrol *lineout_ctrl;
+       struct snd_kcontrol *speaker_ctrl;
+       struct snd_kcontrol *headphone_detected_ctrl;
+       struct snd_kcontrol *lineout_detected_ctrl;
+
+       struct layout_dev_ptr selfptr_headphone;
+       struct layout_dev_ptr selfptr_lineout;
+
+       u32 have_lineout_detect:1,
+           have_headphone_detect:1,
+           switch_on_headphone:1,
+           switch_on_lineout:1;
+};
+
+static LIST_HEAD(layouts_list);
+static int layouts_list_items;
+/* this can go away but only if we allow multiple cards,
+ * make the fabric handle all the card stuff, etc... */
+static struct layout_dev *layout_device;
+
+static int control_info(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+#define AMP_CONTROL(n, description)                                    \
+static int n##_control_get(struct snd_kcontrol *kcontrol,              \
+                          struct snd_ctl_elem_value *ucontrol)         \
+{                                                                      \
+       struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol);        \
+       if (gpio->methods && gpio->methods->get_##n)                    \
+               ucontrol->value.integer.value[0] =                      \
+                       gpio->methods->get_##n(gpio);                   \
+       return 0;                                                       \
+}                                                                      \
+static int n##_control_put(struct snd_kcontrol *kcontrol,              \
+                          struct snd_ctl_elem_value *ucontrol)         \
+{                                                                      \
+       struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol);        \
+       if (gpio->methods && gpio->methods->get_##n)                    \
+               gpio->methods->set_##n(gpio,                            \
+                       ucontrol->value.integer.value[0]);              \
+       return 1;                                                       \
+}                                                                      \
+static struct snd_kcontrol_new n##_ctl = {                             \
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                            \
+       .name = description,                                            \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                      \
+       .info = control_info,                                           \
+       .get = n##_control_get,                                         \
+       .put = n##_control_put,                                         \
+}
+
+AMP_CONTROL(headphone, "Headphone Switch");
+AMP_CONTROL(speakers, "Speakers Switch");
+AMP_CONTROL(lineout, "Line-Out Switch");
+
+static int detect_choice_get(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
+
+       switch (kcontrol->private_value) {
+       case 0:
+               ucontrol->value.integer.value[0] = ldev->switch_on_headphone;
+               break;
+       case 1:
+               ucontrol->value.integer.value[0] = ldev->switch_on_lineout;
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int detect_choice_put(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
+
+       switch (kcontrol->private_value) {
+       case 0:
+               ldev->switch_on_headphone = !!ucontrol->value.integer.value[0];
+               break;
+       case 1:
+               ldev->switch_on_lineout = !!ucontrol->value.integer.value[0];
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 1;
+}
+
+static struct snd_kcontrol_new headphone_detect_choice = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Headphone Detect Autoswitch",
+       .info = control_info,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .get = detect_choice_get,
+       .put = detect_choice_put,
+       .private_value = 0,
+};
+
+static struct snd_kcontrol_new lineout_detect_choice = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Line-Out Detect Autoswitch",
+       .info = control_info,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .get = detect_choice_get,
+       .put = detect_choice_put,
+       .private_value = 1,
+};
+
+static int detected_get(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
+       int v;
+
+       switch (kcontrol->private_value) {
+       case 0:
+               v = ldev->gpio.methods->get_detect(&ldev->gpio,
+                                                  AOA_NOTIFY_HEADPHONE);
+               break;
+       case 1:
+               v = ldev->gpio.methods->get_detect(&ldev->gpio,
+                                                  AOA_NOTIFY_LINE_OUT);
+               break;
+       default:
+               return -ENODEV;
+       }
+       ucontrol->value.integer.value[0] = v;
+       return 0;
+}
+
+static struct snd_kcontrol_new headphone_detected = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Headphone Detected",
+       .info = control_info,
+       .access = SNDRV_CTL_ELEM_ACCESS_READ,
+       .get = detected_get,
+       .private_value = 0,
+};
+
+static struct snd_kcontrol_new lineout_detected = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Line-Out Detected",
+       .info = control_info,
+       .access = SNDRV_CTL_ELEM_ACCESS_READ,
+       .get = detected_get,
+       .private_value = 1,
+};
+
+static int check_codec(struct aoa_codec *codec,
+                      struct layout_dev *ldev,
+                      struct codec_connect_info *cci)
+{
+       u32 *ref;
+       char propname[32];
+       struct codec_connection *cc;
+
+       /* if the codec has a 'codec' node, we require a reference */
+       if (codec->node && (strcmp(codec->node->name, "codec") == 0)) {
+               snprintf(propname, sizeof(propname),
+                        "platform-%s-codec-ref", codec->name);
+               ref = (u32*)get_property(ldev->sound, propname, NULL);
+               if (!ref) {
+                       printk(KERN_INFO "snd-aoa-fabric-layout: "
+                               "required property %s not present\n", propname);
+                       return -ENODEV;
+               }
+               if (*ref != codec->node->linux_phandle) {
+                       printk(KERN_INFO "snd-aoa-fabric-layout: "
+                               "%s doesn't match!\n", propname);
+                       return -ENODEV;
+               }
+       } else {
+               if (layouts_list_items != 1) {
+                       printk(KERN_INFO "snd-aoa-fabric-layout: "
+                               "more than one soundbus, but no references.\n");
+                       return -ENODEV;
+               }
+       }
+       codec->soundbus_dev = ldev->sdev;
+       codec->gpio = &ldev->gpio;
+
+       cc = cci->connections;
+       if (!cc)
+               return -EINVAL;
+
+       printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n");
+
+       codec->connected = 0;
+       codec->fabric_data = cc;
+
+       while (cc->connected) {
+               codec->connected |= 1<<cc->codec_bit;
+               cc++;
+       }
+
+       return 0;
+}
+
+static int layout_found_codec(struct aoa_codec *codec)
+{
+       struct layout_dev *ldev;
+       int i;
+
+       list_for_each_entry(ldev, &layouts_list, list) {
+               for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+                       if (!ldev->layout->codecs[i].name)
+                               continue;
+                       if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) {
+                               if (check_codec(codec,
+                                               ldev,
+                                               &ldev->layout->codecs[i]) == 0)
+                                       return 0;
+                       }
+               }
+       }
+       return -ENODEV;
+}
+
+static void layout_remove_codec(struct aoa_codec *codec)
+{
+       int i;
+       /* here remove the codec from the layout dev's
+        * codec reference */
+
+       codec->soundbus_dev = NULL;
+       codec->gpio = NULL;
+       for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+       }
+}
+
+static void layout_notify(void *data)
+{
+       struct layout_dev_ptr *dptr = data;
+       struct layout_dev *ldev;
+       int v, update;
+       struct snd_kcontrol *detected, *c;
+       struct snd_card *card = aoa_get_card();
+
+       ldev = dptr->ptr;
+       if (data == &ldev->selfptr_headphone) {
+               v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE);
+               detected = ldev->headphone_detected_ctrl;
+               update = ldev->switch_on_headphone;
+               if (update) {
+                       ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
+                       ldev->gpio.methods->set_headphone(&ldev->gpio, v);
+                       ldev->gpio.methods->set_lineout(&ldev->gpio, 0);
+               }
+       } else if (data == &ldev->selfptr_lineout) {
+               v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT);
+               detected = ldev->lineout_detected_ctrl;
+               update = ldev->switch_on_lineout;
+               if (update) {
+                       ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
+                       ldev->gpio.methods->set_headphone(&ldev->gpio, 0);
+                       ldev->gpio.methods->set_lineout(&ldev->gpio, v);
+               }
+       } else
+               return;
+
+       if (detected)
+               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id);
+       if (update) {
+               c = ldev->headphone_ctrl;
+               if (c)
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
+               c = ldev->speaker_ctrl;
+               if (c)
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
+               c = ldev->lineout_ctrl;
+               if (c)
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
+       }
+}
+
+static void layout_attached_codec(struct aoa_codec *codec)
+{
+       struct codec_connection *cc;
+       struct snd_kcontrol *ctl;
+       int headphones, lineout;
+       struct layout_dev *ldev = layout_device;
+
+       /* need to add this codec to our codec array! */
+
+       cc = codec->fabric_data;
+
+       headphones = codec->gpio->methods->get_detect(codec->gpio,
+                                                     AOA_NOTIFY_HEADPHONE);
+       lineout = codec->gpio->methods->get_detect(codec->gpio,
+                                                  AOA_NOTIFY_LINE_OUT);
+
+       while (cc->connected) {
+               if (cc->connected & CC_SPEAKERS) {
+                       if (headphones <= 0 && lineout <= 0)
+                               ldev->gpio.methods->set_speakers(codec->gpio, 1);
+                       ctl = snd_ctl_new1(&speakers_ctl, codec->gpio);
+                       ldev->speaker_ctrl = ctl;
+                       aoa_snd_ctl_add(ctl);
+               }
+               if (cc->connected & CC_HEADPHONE) {
+                       if (headphones == 1)
+                               ldev->gpio.methods->set_headphone(codec->gpio, 1);
+                       ctl = snd_ctl_new1(&headphone_ctl, codec->gpio);
+                       ldev->headphone_ctrl = ctl;
+                       aoa_snd_ctl_add(ctl);
+                       ldev->have_headphone_detect =
+                               !ldev->gpio.methods
+                                       ->set_notify(&ldev->gpio,
+                                                    AOA_NOTIFY_HEADPHONE,
+                                                    layout_notify,
+                                                    &ldev->selfptr_headphone);
+                       if (ldev->have_headphone_detect) {
+                               ctl = snd_ctl_new1(&headphone_detect_choice,
+                                                  ldev);
+                               aoa_snd_ctl_add(ctl);
+                               ctl = snd_ctl_new1(&headphone_detected,
+                                                  ldev);
+                               ldev->headphone_detected_ctrl = ctl;
+                               aoa_snd_ctl_add(ctl);
+                       }
+               }
+               if (cc->connected & CC_LINEOUT) {
+                       if (lineout == 1)
+                               ldev->gpio.methods->set_lineout(codec->gpio, 1);
+                       ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
+                       if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
+                               strlcpy(ctl->id.name,
+                                       "Headphone Switch", sizeof(ctl->id.name));
+                       ldev->lineout_ctrl = ctl;
+                       aoa_snd_ctl_add(ctl);
+                       ldev->have_lineout_detect =
+                               !ldev->gpio.methods
+                                       ->set_notify(&ldev->gpio,
+                                                    AOA_NOTIFY_LINE_OUT,
+                                                    layout_notify,
+                                                    &ldev->selfptr_lineout);
+                       if (ldev->have_lineout_detect) {
+                               ctl = snd_ctl_new1(&lineout_detect_choice,
+                                                  ldev);
+                               if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
+                                       strlcpy(ctl->id.name,
+                                               "Headphone Detect Autoswitch",
+                                               sizeof(ctl->id.name));
+                               aoa_snd_ctl_add(ctl);
+                               ctl = snd_ctl_new1(&lineout_detected,
+                                                  ldev);
+                               if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
+                                       strlcpy(ctl->id.name,
+                                               "Headphone Detected",
+                                               sizeof(ctl->id.name));
+                               ldev->lineout_detected_ctrl = ctl;
+                               aoa_snd_ctl_add(ctl);
+                       }
+               }
+               cc++;
+       }
+       /* now update initial state */
+       if (ldev->have_headphone_detect)
+               layout_notify(&ldev->selfptr_headphone);
+       if (ldev->have_lineout_detect)
+               layout_notify(&ldev->selfptr_lineout);
+}
+
+static struct aoa_fabric layout_fabric = {
+       .name = "SoundByLayout",
+       .owner = THIS_MODULE,
+       .found_codec = layout_found_codec,
+       .remove_codec = layout_remove_codec,
+       .attached_codec = layout_attached_codec,
+};
+
+static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
+{
+       struct device_node *sound = NULL;
+       unsigned int *layout_id;
+       struct layout *layout;
+       struct layout_dev *ldev = NULL;
+       int err;
+
+       /* hm, currently we can only have one ... */
+       if (layout_device)
+               return -ENODEV;
+
+       /* by breaking out we keep a reference */
+       while ((sound = of_get_next_child(sdev->ofdev.node, sound))) {
+               if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
+                       break;
+       }
+       if (!sound) return -ENODEV;
+
+       layout_id = (unsigned int *) get_property(sound, "layout-id", NULL);
+       if (!layout_id)
+               goto outnodev;
+       printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n",
+              *layout_id);
+
+       layout = find_layout_by_id(*layout_id);
+       if (!layout) {
+               printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n");
+               goto outnodev;
+       }
+
+       ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL);
+       if (!ldev)
+               goto outnodev;
+
+       layout_device = ldev;
+       ldev->sdev = sdev;
+       ldev->sound = sound;
+       ldev->layout = layout;
+       ldev->gpio.node = sound->parent;
+       switch (layout->layout_id) {
+       case 41: /* that unknown machine no one seems to have */
+       case 51: /* PowerBook5,4 */
+       case 58: /* Mac Mini */
+               ldev->gpio.methods = ftr_gpio_methods;
+               printk(KERN_DEBUG
+                      "snd-aoa-fabric-layout: Using direct GPIOs\n");
+               break;
+       default:
+               ldev->gpio.methods = pmf_gpio_methods;
+               printk(KERN_DEBUG
+                      "snd-aoa-fabric-layout: Using PMF GPIOs\n");
+       }
+       ldev->selfptr_headphone.ptr = ldev;
+       ldev->selfptr_lineout.ptr = ldev;
+       sdev->ofdev.dev.driver_data = ldev;
+       list_add(&ldev->list, &layouts_list);
+       layouts_list_items++;
+
+       /* assign these before registering ourselves, so
+        * callbacks that are done during registration
+        * already have the values */
+       sdev->pcmid = ldev->layout->pcmid;
+       if (ldev->layout->busname) {
+               sdev->pcmname = ldev->layout->busname;
+       } else {
+               sdev->pcmname = "Master";
+       }
+
+       ldev->gpio.methods->init(&ldev->gpio);
+
+       err = aoa_fabric_register(&layout_fabric);
+       if (err && err != -EALREADY) {
+               printk(KERN_INFO "snd-aoa-fabric-layout: can't use,"
+                                " another fabric is active!\n");
+               goto outlistdel;
+       }
+
+       use_layout(layout);
+       ldev->switch_on_headphone = 1;
+       ldev->switch_on_lineout = 1;
+       return 0;
+ outlistdel:
+       /* we won't be using these then... */
+       ldev->gpio.methods->exit(&ldev->gpio);
+       /* reset if we didn't use it */
+       sdev->pcmname = NULL;
+       sdev->pcmid = -1;
+       list_del(&ldev->list);
+       layouts_list_items--;
+ outnodev:
+       if (sound) of_node_put(sound);
+       layout_device = NULL;
+       if (ldev) kfree(ldev);
+       return -ENODEV;
+}
+
+static int aoa_fabric_layout_remove(struct soundbus_dev *sdev)
+{
+       struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+       int i;
+
+       for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+               if (ldev->codecs[i]) {
+                       aoa_fabric_unlink_codec(ldev->codecs[i]);
+               }
+               ldev->codecs[i] = NULL;
+       }
+       list_del(&ldev->list);
+       layouts_list_items--;
+       of_node_put(ldev->sound);
+
+       ldev->gpio.methods->set_notify(&ldev->gpio,
+                                      AOA_NOTIFY_HEADPHONE,
+                                      NULL,
+                                      NULL);
+       ldev->gpio.methods->set_notify(&ldev->gpio,
+                                      AOA_NOTIFY_LINE_OUT,
+                                      NULL,
+                                      NULL);
+
+       ldev->gpio.methods->exit(&ldev->gpio);
+       layout_device = NULL;
+       kfree(ldev);
+       sdev->pcmid = -1;
+       sdev->pcmname = NULL;
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state)
+{
+       struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+
+       printk("aoa_fabric_layout_suspend()\n");
+
+       if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
+               ldev->gpio.methods->all_amps_off(&ldev->gpio);
+
+       return 0;
+}
+
+static int aoa_fabric_layout_resume(struct soundbus_dev *sdev)
+{
+       struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+
+       printk("aoa_fabric_layout_resume()\n");
+
+       if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
+               ldev->gpio.methods->all_amps_restore(&ldev->gpio);
+
+       return 0;
+}
+#endif
+
+static struct soundbus_driver aoa_soundbus_driver = {
+       .name = "snd_aoa_soundbus_drv",
+       .owner = THIS_MODULE,
+       .probe = aoa_fabric_layout_probe,
+       .remove = aoa_fabric_layout_remove,
+#ifdef CONFIG_PM
+       .suspend = aoa_fabric_layout_suspend,
+       .resume = aoa_fabric_layout_resume,
+#endif
+};
+
+static int __init aoa_fabric_layout_init(void)
+{
+       int err;
+
+       err = soundbus_register_driver(&aoa_soundbus_driver);
+       if (err)
+               return err;
+       return 0;
+}
+
+static void __exit aoa_fabric_layout_exit(void)
+{
+       soundbus_unregister_driver(&aoa_soundbus_driver);
+       aoa_fabric_unregister(&layout_fabric);
+}
+
+module_init(aoa_fabric_layout_init);
+module_exit(aoa_fabric_layout_exit);
diff --git a/sound/aoa/soundbus/Kconfig b/sound/aoa/soundbus/Kconfig
new file mode 100644 (file)
index 0000000..7368b7d
--- /dev/null
@@ -0,0 +1,15 @@
+config SND_AOA_SOUNDBUS
+       tristate "Apple Soundbus support"
+       depends on SOUND
+       select SND_PCM
+       ---help---
+       This option enables the generic driver for the soundbus
+       support on Apple machines.
+       
+       It is required for the sound bus implementations.
+
+config SND_AOA_SOUNDBUS_I2S
+       tristate "I2S bus support"
+       depends on SND_AOA_SOUNDBUS && PCI
+       ---help---
+       This option enables support for Apple I2S busses.
diff --git a/sound/aoa/soundbus/Makefile b/sound/aoa/soundbus/Makefile
new file mode 100644 (file)
index 0000000..0e61f5a
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o
+snd-aoa-soundbus-objs := core.o sysfs.o
+obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
new file mode 100644 (file)
index 0000000..47b3e37
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * soundbus
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/module.h>
+#include "soundbus.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Apple Soundbus");
+
+struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev)
+{
+       struct device *tmp;
+
+       if (!dev)
+               return NULL;
+       tmp = get_device(&dev->ofdev.dev);
+       if (tmp)
+               return to_soundbus_device(tmp);
+       else
+               return NULL;
+}
+EXPORT_SYMBOL_GPL(soundbus_dev_get);
+
+void soundbus_dev_put(struct soundbus_dev *dev)
+{
+       if (dev)
+               put_device(&dev->ofdev.dev);
+}
+EXPORT_SYMBOL_GPL(soundbus_dev_put);
+
+static int soundbus_probe(struct device *dev)
+{
+       int error = -ENODEV;
+       struct soundbus_driver *drv;
+       struct soundbus_dev *soundbus_dev;
+
+       drv = to_soundbus_driver(dev->driver);
+       soundbus_dev = to_soundbus_device(dev);
+
+       if (!drv->probe)
+               return error;
+
+       soundbus_dev_get(soundbus_dev);
+
+       error = drv->probe(soundbus_dev);
+       if (error)
+               soundbus_dev_put(soundbus_dev);
+
+       return error;
+}
+
+
+static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
+                          char *buffer, int buffer_size)
+{
+       struct soundbus_dev * soundbus_dev;
+       struct of_device * of;
+       char *scratch, *compat, *compat2;
+       int i = 0;
+       int length, cplen, cplen2, seen = 0;
+
+       if (!dev)
+               return -ENODEV;
+
+       soundbus_dev = to_soundbus_device(dev);
+       if (!soundbus_dev)
+               return -ENODEV;
+
+       of = &soundbus_dev->ofdev;
+
+       /* stuff we want to pass to /sbin/hotplug */
+       envp[i++] = scratch = buffer;
+       length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
+       ++length;
+       buffer_size -= length;
+       if ((buffer_size <= 0) || (i >= num_envp))
+               return -ENOMEM;
+       scratch += length;
+
+       envp[i++] = scratch;
+       length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
+       ++length;
+       buffer_size -= length;
+       if ((buffer_size <= 0) || (i >= num_envp))
+               return -ENOMEM;
+       scratch += length;
+
+       /* Since the compatible field can contain pretty much anything
+        * it's not really legal to split it out with commas. We split it
+        * up using a number of environment variables instead. */
+
+       compat = (char *) get_property(of->node, "compatible", &cplen);
+       compat2 = compat;
+       cplen2= cplen;
+       while (compat && cplen > 0) {
+               envp[i++] = scratch;
+               length = scnprintf (scratch, buffer_size,
+                                    "OF_COMPATIBLE_%d=%s", seen, compat);
+               ++length;
+               buffer_size -= length;
+               if ((buffer_size <= 0) || (i >= num_envp))
+                       return -ENOMEM;
+               scratch += length;
+               length = strlen (compat) + 1;
+               compat += length;
+               cplen -= length;
+               seen++;
+       }
+
+       envp[i++] = scratch;
+       length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
+       ++length;
+       buffer_size -= length;
+       if ((buffer_size <= 0) || (i >= num_envp))
+               return -ENOMEM;
+       scratch += length;
+
+       envp[i++] = scratch;
+       length = scnprintf (scratch, buffer_size, "MODALIAS=%s",
+                       soundbus_dev->modalias);
+
+       buffer_size -= length;
+       if ((buffer_size <= 0) || (i >= num_envp))
+               return -ENOMEM;
+
+       envp[i] = NULL;
+
+       return 0;
+}
+
+static int soundbus_device_remove(struct device *dev)
+{
+       struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+       struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+       if (dev->driver && drv->remove)
+               drv->remove(soundbus_dev);
+       soundbus_dev_put(soundbus_dev);
+
+       return 0;
+}
+
+static void soundbus_device_shutdown(struct device *dev)
+{
+       struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+       struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+       if (dev->driver && drv->shutdown)
+               drv->shutdown(soundbus_dev);
+}
+
+#ifdef CONFIG_PM
+
+static int soundbus_device_suspend(struct device *dev, pm_message_t state)
+{
+       struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+       struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+       if (dev->driver && drv->suspend)
+               return drv->suspend(soundbus_dev, state);
+       return 0;
+}
+
+static int soundbus_device_resume(struct device * dev)
+{
+       struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+       struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+       if (dev->driver && drv->resume)
+               return drv->resume(soundbus_dev);
+       return 0;
+}
+
+#endif /* CONFIG_PM */
+
+extern struct device_attribute soundbus_dev_attrs[];
+
+static struct bus_type soundbus_bus_type = {
+       .name           = "aoa-soundbus",
+       .probe          = soundbus_probe,
+       .uevent         = soundbus_uevent,
+       .remove         = soundbus_device_remove,
+       .shutdown       = soundbus_device_shutdown,
+#ifdef CONFIG_PM
+       .suspend        = soundbus_device_suspend,
+       .resume         = soundbus_device_resume,
+#endif
+       .dev_attrs      = soundbus_dev_attrs,
+};
+
+int soundbus_add_one(struct soundbus_dev *dev)
+{
+       static int devcount;
+
+       /* sanity checks */
+       if (!dev->attach_codec ||
+           !dev->ofdev.node ||
+           dev->pcmname ||
+           dev->pcmid != -1) {
+               printk(KERN_ERR "soundbus: adding device failed sanity check!\n");
+               return -EINVAL;
+       }
+
+       snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount);
+       dev->ofdev.dev.bus = &soundbus_bus_type;
+       return of_device_register(&dev->ofdev);
+}
+EXPORT_SYMBOL_GPL(soundbus_add_one);
+
+void soundbus_remove_one(struct soundbus_dev *dev)
+{
+       of_device_unregister(&dev->ofdev);
+}
+EXPORT_SYMBOL_GPL(soundbus_remove_one);
+
+int soundbus_register_driver(struct soundbus_driver *drv)
+{
+       /* initialize common driver fields */
+       drv->driver.name = drv->name;
+       drv->driver.bus = &soundbus_bus_type;
+
+       /* register with core */
+       return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(soundbus_register_driver);
+
+void soundbus_unregister_driver(struct soundbus_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(soundbus_unregister_driver);
+
+static int __init soundbus_init(void)
+{
+       return bus_register(&soundbus_bus_type);
+}
+
+static void __exit soundbus_exit(void)
+{
+       bus_unregister(&soundbus_bus_type);
+}
+
+subsys_initcall(soundbus_init);
+module_exit(soundbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile
new file mode 100644 (file)
index 0000000..e57a5cf
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o
+snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
new file mode 100644 (file)
index 0000000..87beb4a
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * i2sbus driver -- bus control routines
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/macio.h>
+#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+#include <asm/keylargo.h>
+
+#include "i2sbus.h"
+
+int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
+{
+       *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
+       if (!*c)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&(*c)->list);
+
+       (*c)->macio = dev->bus->chip;
+       return 0;
+}
+
+void i2sbus_control_destroy(struct i2sbus_control *c)
+{
+       kfree(c);
+}
+
+/* this is serialised externally */
+int i2sbus_control_add_dev(struct i2sbus_control *c,
+                          struct i2sbus_dev *i2sdev)
+{
+       struct device_node *np;
+
+       np = i2sdev->sound.ofdev.node;
+       i2sdev->enable = pmf_find_function(np, "enable");
+       i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
+       i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
+       i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
+       i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
+
+       /* if the bus number is not 0 or 1 we absolutely need to use
+        * the platform functions -- there's nothing in Darwin that
+        * would allow seeing a system behind what the FCRs are then,
+        * and I don't want to go parsing a bunch of platform functions
+        * by hand to try finding a system... */
+       if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
+           (!i2sdev->enable ||
+            !i2sdev->cell_enable || !i2sdev->clock_enable ||
+            !i2sdev->cell_disable || !i2sdev->clock_disable)) {
+               pmf_put_function(i2sdev->enable);
+               pmf_put_function(i2sdev->cell_enable);
+               pmf_put_function(i2sdev->clock_enable);
+               pmf_put_function(i2sdev->cell_disable);
+               pmf_put_function(i2sdev->clock_disable);
+               return -ENODEV;
+       }
+
+       list_add(&i2sdev->item, &c->list);
+
+       return 0;
+}
+
+void i2sbus_control_remove_dev(struct i2sbus_control *c,
+                              struct i2sbus_dev *i2sdev)
+{
+       /* this is serialised externally */
+       list_del(&i2sdev->item);
+       if (list_empty(&c->list))
+               i2sbus_control_destroy(c);
+}
+
+int i2sbus_control_enable(struct i2sbus_control *c,
+                         struct i2sbus_dev *i2sdev)
+{
+       struct pmf_args args = { .count = 0 };
+       struct macio_chip *macio = c->macio;
+
+       if (i2sdev->enable)
+               return pmf_call_one(i2sdev->enable, &args);
+
+       if (macio == NULL || macio->base == NULL)
+               return -ENODEV;
+
+       switch (i2sdev->bus_number) {
+       case 0:
+               /* these need to be locked or done through
+                * newly created feature calls! */
+               MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
+               break;
+       case 1:
+               MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
+
+int i2sbus_control_cell(struct i2sbus_control *c,
+                       struct i2sbus_dev *i2sdev,
+                       int enable)
+{
+       struct pmf_args args = { .count = 0 };
+       struct macio_chip *macio = c->macio;
+
+       switch (enable) {
+       case 0:
+               if (i2sdev->cell_disable)
+                       return pmf_call_one(i2sdev->cell_disable, &args);
+               break;
+       case 1:
+               if (i2sdev->cell_enable)
+                       return pmf_call_one(i2sdev->cell_enable, &args);
+               break;
+       default:
+               printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
+               return -ENODEV;
+       }
+
+       if (macio == NULL || macio->base == NULL)
+               return -ENODEV;
+
+       switch (i2sdev->bus_number) {
+       case 0:
+               if (enable)
+                       MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
+               else
+                       MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
+               break;
+       case 1:
+               if (enable)
+                       MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
+               else
+                       MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
+
+int i2sbus_control_clock(struct i2sbus_control *c,
+                        struct i2sbus_dev *i2sdev,
+                        int enable)
+{
+       struct pmf_args args = { .count = 0 };
+       struct macio_chip *macio = c->macio;
+
+       switch (enable) {
+       case 0:
+               if (i2sdev->clock_disable)
+                       return pmf_call_one(i2sdev->clock_disable, &args);
+               break;
+       case 1:
+               if (i2sdev->clock_enable)
+                       return pmf_call_one(i2sdev->clock_enable, &args);
+               break;
+       default:
+               printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
+               return -ENODEV;
+       }
+
+       if (macio == NULL || macio->base == NULL)
+               return -ENODEV;
+
+       switch (i2sdev->bus_number) {
+       case 0:
+               if (enable)
+                       MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
+               else
+                       MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
+               break;
+       case 1:
+               if (enable)
+                       MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
+               else
+                       MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
new file mode 100644 (file)
index 0000000..23190aa
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * i2sbus driver
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+
+#include <asm/macio.h>
+#include <asm/dbdma.h>
+
+#include "../soundbus.h"
+#include "i2sbus.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_DESCRIPTION("Apple Soundbus: I2S support");
+/* for auto-loading, declare that we handle this weird
+ * string that macio puts into the relevant device */
+MODULE_ALIAS("of:Ni2sTi2sC");
+
+static int force;
+module_param(force, int, 0444);
+MODULE_PARM_DESC(force, "Force loading i2sbus even when"
+                       " no layout-id property is present");
+
+static struct of_device_id i2sbus_match[] = {
+       { .name = "i2s" },
+       { }
+};
+
+static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
+                                      struct dbdma_command_mem *r,
+                                      int numcmds)
+{
+       /* one more for rounding */
+       r->size = (numcmds+1) * sizeof(struct dbdma_cmd);
+       /* We use the PCI APIs for now until the generic one gets fixed
+        * enough or until we get some macio-specific versions
+        */
+       r->space = dma_alloc_coherent(
+                       &macio_get_pci_dev(i2sdev->macio)->dev,
+                       r->size,
+                       &r->bus_addr,
+                       GFP_KERNEL);
+
+       if (!r->space) return -ENOMEM;
+
+       memset(r->space, 0, r->size);
+       r->cmds = (void*)DBDMA_ALIGN(r->space);
+       r->bus_cmd_start = r->bus_addr +
+                          (dma_addr_t)((char*)r->cmds - (char*)r->space);
+
+       return 0;
+}
+
+static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
+                                      struct dbdma_command_mem *r)
+{
+       if (!r->space) return;
+       
+       dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+                           r->size, r->space, r->bus_addr);
+}
+
+static void i2sbus_release_dev(struct device *dev)
+{
+       struct i2sbus_dev *i2sdev;
+       int i;
+
+       i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev);
+
+       if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
+       if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
+       if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
+       for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
+               if (i2sdev->allocated_resource[i])
+                       release_and_free_resource(i2sdev->allocated_resource[i]);
+       free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
+       free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
+       for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
+               free_irq(i2sdev->interrupts[i], i2sdev);
+       i2sbus_control_remove_dev(i2sdev->control, i2sdev);
+       mutex_destroy(&i2sdev->lock);
+       kfree(i2sdev);
+}
+
+static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
+{
+       struct i2sbus_dev *dev = devid;
+       u32 intreg;
+
+       spin_lock(&dev->low_lock);
+       intreg = in_le32(&dev->intfregs->intr_ctl);
+
+       /* acknowledge interrupt reasons */
+       out_le32(&dev->intfregs->intr_ctl, intreg);
+
+       spin_unlock(&dev->low_lock);
+
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * XXX FIXME: We test the layout_id's here to get the proper way of
+ * mapping in various registers, thanks to bugs in Apple device-trees.
+ * We could instead key off the machine model and the name of the i2s
+ * node (i2s-a). This we'll do when we move it all to macio_asic.c
+ * and have that export items for each sub-node too.
+ */
+static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index,
+                                    int layout, struct resource *res)
+{
+       struct device_node *parent;
+       int pindex, rc = -ENXIO;
+       u32 *reg;
+
+       /* Machines with layout 76 and 36 (K2 based) have a weird device
+        * tree what we need to special case.
+        * Normal machines just fetch the resource from the i2s-X node.
+        * Darwin further divides normal machines into old and new layouts
+        * with a subtely different code path but that doesn't seem necessary
+        * in practice, they just bloated it. In addition, even on our K2
+        * case the i2s-modem node, if we ever want to handle it, uses the
+        * normal layout
+        */
+       if (layout != 76 && layout != 36)
+               return of_address_to_resource(np, index, res);
+
+       parent = of_get_parent(np);
+       pindex = (index == aoa_resource_i2smmio) ? 0 : 1;
+       rc = of_address_to_resource(parent, pindex, res);
+       if (rc)
+               goto bail;
+       reg = (u32 *)get_property(np, "reg", NULL);
+       if (reg == NULL) {
+               rc = -ENXIO;
+               goto bail;
+       }
+       res->start += reg[index * 2];
+       res->end = res->start + reg[index * 2 + 1] - 1;
+ bail:
+       of_node_put(parent);
+       return rc;
+}
+
+/* FIXME: look at device node refcounting */
+static int i2sbus_add_dev(struct macio_dev *macio,
+                         struct i2sbus_control *control,
+                         struct device_node *np)
+{
+       struct i2sbus_dev *dev;
+       struct device_node *child = NULL, *sound = NULL;
+       struct resource *r;
+       int i, layout = 0, rlen;
+       static const char *rnames[] = { "i2sbus: %s (control)",
+                                       "i2sbus: %s (tx)",
+                                       "i2sbus: %s (rx)" };
+       static irqreturn_t (*ints[])(int irq, void *devid,
+                                    struct pt_regs *regs) = {
+               i2sbus_bus_intr,
+               i2sbus_tx_intr,
+               i2sbus_rx_intr
+       };
+
+       if (strlen(np->name) != 5)
+               return 0;
+       if (strncmp(np->name, "i2s-", 4))
+               return 0;
+
+       dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
+       if (!dev)
+               return 0;
+
+       i = 0;
+       while ((child = of_get_next_child(np, child))) {
+               if (strcmp(child->name, "sound") == 0) {
+                       i++;
+                       sound = child;
+               }
+       }
+       if (i == 1) {
+               u32 *layout_id;
+               layout_id = (u32*) get_property(sound, "layout-id", NULL);
+               if (layout_id) {
+                       layout = *layout_id;
+                       snprintf(dev->sound.modalias, 32,
+                                "sound-layout-%d", layout);
+                       force = 1;
+               }
+       }
+       /* for the time being, until we can handle non-layout-id
+        * things in some fabric, refuse to attach if there is no
+        * layout-id property or we haven't been forced to attach.
+        * When there are two i2s busses and only one has a layout-id,
+        * then this depends on the order, but that isn't important
+        * either as the second one in that case is just a modem. */
+       if (!force) {
+               kfree(dev);
+               return -ENODEV;
+       }
+
+       mutex_init(&dev->lock);
+       spin_lock_init(&dev->low_lock);
+       dev->sound.ofdev.node = np;
+       dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask;
+       dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask;
+       dev->sound.ofdev.dev.parent = &macio->ofdev.dev;
+       dev->sound.ofdev.dev.release = i2sbus_release_dev;
+       dev->sound.attach_codec = i2sbus_attach_codec;
+       dev->sound.detach_codec = i2sbus_detach_codec;
+       dev->sound.pcmid = -1;
+       dev->macio = macio;
+       dev->control = control;
+       dev->bus_number = np->name[4] - 'a';
+       INIT_LIST_HEAD(&dev->sound.codec_list);
+
+       for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
+               dev->interrupts[i] = -1;
+               snprintf(dev->rnames[i], sizeof(dev->rnames[i]),
+                        rnames[i], np->name);
+       }
+       for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
+               int irq = irq_of_parse_and_map(np, i);
+               if (request_irq(irq, ints[i], 0, dev->rnames[i], dev))
+                       goto err;
+               dev->interrupts[i] = irq;
+       }
+
+
+       /* Resource handling is problematic as some device-trees contain
+        * useless crap (ugh ugh ugh). We work around that here by calling
+        * specific functions for calculating the appropriate resources.
+        *
+        * This will all be moved to macio_asic.c at one point
+        */
+       for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
+               if (i2sbus_get_and_fixup_rsrc(np,i,layout,&dev->resources[i]))
+                       goto err;
+               /* If only we could use our resource dev->resources[i]...
+                * but request_resource doesn't know about parents and
+                * contained resources...
+                */
+               dev->allocated_resource[i] = 
+                       request_mem_region(dev->resources[i].start,
+                                          dev->resources[i].end -
+                                          dev->resources[i].start + 1,
+                                          dev->rnames[i]);
+               if (!dev->allocated_resource[i]) {
+                       printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
+                       goto err;
+               }
+       }
+
+       r = &dev->resources[aoa_resource_i2smmio];
+       rlen = r->end - r->start + 1;
+       if (rlen < sizeof(struct i2s_interface_regs))
+               goto err;
+       dev->intfregs = ioremap(r->start, rlen);
+
+       r = &dev->resources[aoa_resource_txdbdma];
+       rlen = r->end - r->start + 1;
+       if (rlen < sizeof(struct dbdma_regs))
+               goto err;
+       dev->out.dbdma = ioremap(r->start, rlen);
+
+       r = &dev->resources[aoa_resource_rxdbdma];
+       rlen = r->end - r->start + 1;
+       if (rlen < sizeof(struct dbdma_regs))
+               goto err;
+       dev->in.dbdma = ioremap(r->start, rlen);
+
+       if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma)
+               goto err;
+
+       if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring,
+                                       MAX_DBDMA_COMMANDS))
+               goto err;
+       if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring,
+                                       MAX_DBDMA_COMMANDS))
+               goto err;
+
+       if (i2sbus_control_add_dev(dev->control, dev)) {
+               printk(KERN_ERR "i2sbus: control layer didn't like bus\n");
+               goto err;
+       }
+
+       if (soundbus_add_one(&dev->sound)) {
+               printk(KERN_DEBUG "i2sbus: device registration error!\n");
+               goto err;
+       }
+
+       /* enable this cell */
+       i2sbus_control_cell(dev->control, dev, 1);
+       i2sbus_control_enable(dev->control, dev);
+       i2sbus_control_clock(dev->control, dev, 1);
+
+       return 1;
+ err:
+       for (i=0;i<3;i++)
+               if (dev->interrupts[i] != -1)
+                       free_irq(dev->interrupts[i], dev);
+       free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring);
+       free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring);
+       if (dev->intfregs) iounmap(dev->intfregs);
+       if (dev->out.dbdma) iounmap(dev->out.dbdma);
+       if (dev->in.dbdma) iounmap(dev->in.dbdma);
+       for (i=0;i<3;i++)
+               if (dev->allocated_resource[i])
+                       release_and_free_resource(dev->allocated_resource[i]);
+       mutex_destroy(&dev->lock);
+       kfree(dev);
+       return 0;
+}
+
+static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
+{
+       struct device_node *np = NULL;
+       int got = 0, err;
+       struct i2sbus_control *control = NULL;
+
+       err = i2sbus_control_init(dev, &control);
+       if (err)
+               return err;
+       if (!control) {
+               printk(KERN_ERR "i2sbus_control_init API breakage\n");
+               return -ENODEV;
+       }
+
+       while ((np = of_get_next_child(dev->ofdev.node, np))) {
+               if (device_is_compatible(np, "i2sbus") ||
+                   device_is_compatible(np, "i2s-modem")) {
+                       got += i2sbus_add_dev(dev, control, np);
+               }
+       }
+
+       if (!got) {
+               /* found none, clean up */
+               i2sbus_control_destroy(control);
+               return -ENODEV;
+       }
+
+       dev->ofdev.dev.driver_data = control;
+
+       return 0;
+}
+
+static int i2sbus_remove(struct macio_dev* dev)
+{
+       struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+       struct i2sbus_dev *i2sdev, *tmp;
+
+       list_for_each_entry_safe(i2sdev, tmp, &control->list, item)
+               soundbus_remove_one(&i2sdev->sound);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
+{
+       struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+       struct codec_info_item *cii;
+       struct i2sbus_dev* i2sdev;
+       int err, ret = 0;
+
+       list_for_each_entry(i2sdev, &control->list, item) {
+               /* Notify Alsa */
+               if (i2sdev->sound.pcm) {
+                       /* Suspend PCM streams */
+                       snd_pcm_suspend_all(i2sdev->sound.pcm);
+                       /* Probably useless as we handle
+                        * power transitions ourselves */
+                       snd_power_change_state(i2sdev->sound.pcm->card,
+                                              SNDRV_CTL_POWER_D3hot);
+               }
+               /* Notify codecs */
+               list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+                       err = 0;
+                       if (cii->codec->suspend)
+                               err = cii->codec->suspend(cii, state);
+                       if (err)
+                               ret = err;
+               }
+       }
+       return ret;
+}
+
+static int i2sbus_resume(struct macio_dev* dev)
+{
+       struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+       struct codec_info_item *cii;
+       struct i2sbus_dev* i2sdev;
+       int err, ret = 0;
+
+       list_for_each_entry(i2sdev, &control->list, item) {
+               /* Notify codecs so they can re-initialize */
+               list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+                       err = 0;
+                       if (cii->codec->resume)
+                               err = cii->codec->resume(cii);
+                       if (err)
+                               ret = err;
+               }
+               /* Notify Alsa */
+               if (i2sdev->sound.pcm) {
+                       /* Same comment as above, probably useless */
+                       snd_power_change_state(i2sdev->sound.pcm->card,
+                                              SNDRV_CTL_POWER_D0);
+               }
+       }
+
+       return ret;
+}
+#endif /* CONFIG_PM */
+
+static int i2sbus_shutdown(struct macio_dev* dev)
+{
+       return 0;
+}
+
+static struct macio_driver i2sbus_drv = {
+       .name = "soundbus-i2s",
+       .owner = THIS_MODULE,
+       .match_table = i2sbus_match,
+       .probe = i2sbus_probe,
+       .remove = i2sbus_remove,
+#ifdef CONFIG_PM
+       .suspend = i2sbus_suspend,
+       .resume = i2sbus_resume,
+#endif
+       .shutdown = i2sbus_shutdown,
+};
+
+static int __init soundbus_i2sbus_init(void)
+{
+       return macio_register_driver(&i2sbus_drv);
+}
+
+static void __exit soundbus_i2sbus_exit(void)
+{
+       macio_unregister_driver(&i2sbus_drv);
+}
+
+module_init(soundbus_i2sbus_init);
+module_exit(soundbus_i2sbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
new file mode 100644 (file)
index 0000000..c6b5f54
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * i2sbus driver -- interface register definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __I2SBUS_INTERFACE_H
+#define __I2SBUS_INTERFACE_H
+
+/* i2s bus control registers, at least what we know about them */
+
+#define __PAD(m,n) u8 __pad##m[n]
+#define _PAD(line, n) __PAD(line, n)
+#define PAD(n) _PAD(__LINE__, (n))
+struct i2s_interface_regs {
+       __le32 intr_ctl;        /* 0x00 */
+       PAD(12);
+       __le32 serial_format;   /* 0x10 */
+       PAD(12);
+       __le32 codec_msg_out;   /* 0x20 */
+       PAD(12);
+       __le32 codec_msg_in;    /* 0x30 */
+       PAD(12);
+       __le32 frame_count;     /* 0x40 */
+       PAD(12);
+       __le32 frame_match;     /* 0x50 */
+       PAD(12);
+       __le32 data_word_sizes; /* 0x60 */
+       PAD(12);
+       __le32 peak_level_sel;  /* 0x70 */
+       PAD(12);
+       __le32 peak_level_in0;  /* 0x80 */
+       PAD(12);
+       __le32 peak_level_in1;  /* 0x90 */
+       PAD(12);
+       /* total size: 0x100 bytes */
+}  __attribute__((__packed__));
+
+/* interrupt register is just a bitfield with
+ * interrupt enable and pending bits */
+#define I2S_REG_INTR_CTL               0x00
+#      define I2S_INT_FRAME_COUNT              (1<<31)
+#      define I2S_PENDING_FRAME_COUNT          (1<<30)
+#      define I2S_INT_MESSAGE_FLAG             (1<<29)
+#      define I2S_PENDING_MESSAGE_FLAG         (1<<28)
+#      define I2S_INT_NEW_PEAK                 (1<<27)
+#      define I2S_PENDING_NEW_PEAK             (1<<26)
+#      define I2S_INT_CLOCKS_STOPPED           (1<<25)
+#      define I2S_PENDING_CLOCKS_STOPPED       (1<<24)
+#      define I2S_INT_EXTERNAL_SYNC_ERROR      (1<<23)
+#      define I2S_PENDING_EXTERNAL_SYNC_ERROR  (1<<22)
+#      define I2S_INT_EXTERNAL_SYNC_OK         (1<<21)
+#      define I2S_PENDING_EXTERNAL_SYNC_OK     (1<<20)
+#      define I2S_INT_NEW_SAMPLE_RATE          (1<<19)
+#      define I2S_PENDING_NEW_SAMPLE_RATE      (1<<18)
+#      define I2S_INT_STATUS_FLAG              (1<<17)
+#      define I2S_PENDING_STATUS_FLAG          (1<<16)
+
+/* serial format register is more interesting :)
+ * It contains:
+ *  - clock source
+ *  - MClk divisor
+ *  - SClk divisor
+ *  - SClk master flag
+ *  - serial format (sony, i2s 64x, i2s 32x, dav, silabs)
+ *  - external sample frequency interrupt (don't understand)
+ *  - external sample frequency
+ */
+#define I2S_REG_SERIAL_FORMAT          0x10
+/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */
+#      define I2S_SF_CLOCK_SOURCE_SHIFT        30
+#      define I2S_SF_CLOCK_SOURCE_MASK         (3<<I2S_SF_CLOCK_SOURCE_SHIFT)
+#      define I2S_SF_CLOCK_SOURCE_18MHz        (0<<I2S_SF_CLOCK_SOURCE_SHIFT)
+#      define I2S_SF_CLOCK_SOURCE_45MHz        (1<<I2S_SF_CLOCK_SOURCE_SHIFT)
+#      define I2S_SF_CLOCK_SOURCE_49MHz        (2<<I2S_SF_CLOCK_SOURCE_SHIFT)
+/* also, let's define the exact clock speeds here, in Hz */
+#define I2S_CLOCK_SPEED_18MHz  18432000
+#define I2S_CLOCK_SPEED_45MHz  45158400
+#define I2S_CLOCK_SPEED_49MHz  49152000
+/* MClk is the clock that drives the codec, usually called its 'system clock'.
+ * It is derived by taking only every 'divisor' tick of the clock.
+ */
+#      define I2S_SF_MCLKDIV_SHIFT             24
+#      define I2S_SF_MCLKDIV_MASK              (0x1F<<I2S_SF_MCLKDIV_SHIFT)
+#      define I2S_SF_MCLKDIV_1                 (0x14<<I2S_SF_MCLKDIV_SHIFT)
+#      define I2S_SF_MCLKDIV_3                 (0x13<<I2S_SF_MCLKDIV_SHIFT)
+#      define I2S_SF_MCLKDIV_5                 (0x12<<I2S_SF_MCLKDIV_SHIFT)
+#      define I2S_SF_MCLKDIV_14                (0x0E<<I2S_SF_MCLKDIV_SHIFT)
+#      define I2S_SF_MCLKDIV_OTHER(div)        (((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK)
+static inline int i2s_sf_mclkdiv(int div, int *out)
+{
+       int d;
+
+       switch(div) {
+       case 1: *out |= I2S_SF_MCLKDIV_1; return 0;
+       case 3: *out |= I2S_SF_MCLKDIV_3; return 0;
+       case 5: *out |= I2S_SF_MCLKDIV_5; return 0;
+       case 14: *out |= I2S_SF_MCLKDIV_14; return 0;
+       default:
+               if (div%2) return -1;
+               d = div/2-1;
+               if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E)
+                       return -1;
+               *out |= I2S_SF_MCLKDIV_OTHER(div);
+               return 0;
+       }
+}
+/* SClk is the clock that drives the i2s wire bus. Note that it is
+ * derived from the MClk above by taking only every 'divisor' tick
+ * of MClk.
+ */
+#      define I2S_SF_SCLKDIV_SHIFT             20
+#      define I2S_SF_SCLKDIV_MASK              (0xF<<I2S_SF_SCLKDIV_SHIFT)
+#      define I2S_SF_SCLKDIV_1                 (8<<I2S_SF_SCLKDIV_SHIFT)
+#      define I2S_SF_SCLKDIV_3                 (9<<I2S_SF_SCLKDIV_SHIFT)
+#      define I2S_SF_SCLKDIV_OTHER(div)        (((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK)
+static inline int i2s_sf_sclkdiv(int div, int *out)
+{
+       int d;
+
+       switch(div) {
+       case 1: *out |= I2S_SF_SCLKDIV_1; return 0;
+       case 3: *out |= I2S_SF_SCLKDIV_3; return 0;
+       default:
+               if (div%2) return -1;
+               d = div/2-1;
+               if (d == 8 || d == 9) return -1;
+               *out |= I2S_SF_SCLKDIV_OTHER(div);
+               return 0;
+       }
+}
+#      define I2S_SF_SCLK_MASTER               (1<<19)
+/* serial format is the way the data is put to the i2s wire bus */
+#      define I2S_SF_SERIAL_FORMAT_SHIFT       16
+#      define I2S_SF_SERIAL_FORMAT_MASK        (7<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#      define I2S_SF_SERIAL_FORMAT_SONY        (0<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#      define I2S_SF_SERIAL_FORMAT_I2S_64X     (1<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#      define I2S_SF_SERIAL_FORMAT_I2S_32X     (2<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#      define I2S_SF_SERIAL_FORMAT_I2S_DAV     (4<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#      define I2S_SF_SERIAL_FORMAT_I2S_SILABS  (5<<I2S_SF_SERIAL_FORMAT_SHIFT)
+/* unknown */
+#      define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT 12
+#      define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK  (0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT)
+/* probably gives external frequency? */
+#      define I2S_SF_EXT_SAMPLE_FREQ_MASK      0xFFF
+
+/* used to send codec messages, but how isn't clear */
+#define I2S_REG_CODEC_MSG_OUT          0x20
+
+/* used to receive codec messages, but how isn't clear */
+#define I2S_REG_CODEC_MSG_IN           0x30
+
+/* frame count reg isn't clear to me yet, but probably useful */
+#define I2S_REG_FRAME_COUNT            0x40
+
+/* program to some value, and get interrupt if frame count reaches it */
+#define I2S_REG_FRAME_MATCH            0x50
+
+/* this register describes how the bus transfers data */
+#define I2S_REG_DATA_WORD_SIZES                0x60
+/* number of interleaved input channels */
+#      define I2S_DWS_NUM_CHANNELS_IN_SHIFT    24
+#      define I2S_DWS_NUM_CHANNELS_IN_MASK     (0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT)
+/* word size of input data */
+#      define I2S_DWS_DATA_IN_SIZE_SHIFT       16
+#      define I2S_DWS_DATA_IN_16BIT            (0<<I2S_DWS_DATA_IN_SIZE_SHIFT)
+#      define I2S_DWS_DATA_IN_24BIT            (3<<I2S_DWS_DATA_IN_SIZE_SHIFT)
+/* number of interleaved output channels */
+#      define I2S_DWS_NUM_CHANNELS_OUT_SHIFT   8
+#      define I2S_DWS_NUM_CHANNELS_OUT_MASK    (0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT)
+/* word size of output data */
+#      define I2S_DWS_DATA_OUT_SIZE_SHIFT      0
+#      define I2S_DWS_DATA_OUT_16BIT           (0<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
+#      define I2S_DWS_DATA_OUT_24BIT           (3<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
+
+
+/* unknown */
+#define I2S_REG_PEAK_LEVEL_SEL         0x70
+
+/* unknown */
+#define I2S_REG_PEAK_LEVEL_IN0         0x80
+
+/* unknown */
+#define I2S_REG_PEAK_LEVEL_IN1         0x90
+
+#endif /* __I2SBUS_INTERFACE_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
new file mode 100644 (file)
index 0000000..3049015
--- /dev/null
@@ -0,0 +1,1021 @@
+/*
+ * i2sbus driver -- pcm routines
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+/* So apparently there's a reason for requiring driver.h
+ * to be included first, even if I don't know it... */
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <asm/macio.h>
+#include <linux/pci.h>
+#include "../soundbus.h"
+#include "i2sbus.h"
+
+static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in,
+                               struct pcm_info **pi, struct pcm_info **other)
+{
+       if (in) {
+               if (pi)
+                       *pi = &i2sdev->in;
+               if (other)
+                       *other = &i2sdev->out;
+       } else {
+               if (pi)
+                       *pi = &i2sdev->out;
+               if (other)
+                       *other = &i2sdev->in;
+       }
+}
+
+static int clock_and_divisors(int mclk, int sclk, int rate, int *out)
+{
+       /* sclk must be derived from mclk! */
+       if (mclk % sclk)
+               return -1;
+       /* derive sclk register value */
+       if (i2s_sf_sclkdiv(mclk / sclk, out))
+               return -1;
+
+       if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) {
+               if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) {
+                       *out |= I2S_SF_CLOCK_SOURCE_18MHz;
+                       return 0;
+               }
+       }
+       if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) {
+               if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) {
+                       *out |= I2S_SF_CLOCK_SOURCE_45MHz;
+                       return 0;
+               }
+       }
+       if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) {
+               if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) {
+                       *out |= I2S_SF_CLOCK_SOURCE_49MHz;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+#define CHECK_RATE(rate)                                               \
+       do { if (rates & SNDRV_PCM_RATE_ ##rate) {                      \
+               int dummy;                                              \
+               if (clock_and_divisors(sysclock_factor,                 \
+                                      bus_factor, rate, &dummy))       \
+                       rates &= ~SNDRV_PCM_RATE_ ##rate;               \
+       } } while (0)
+
+static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
+{
+       struct pcm_info *pi, *other;
+       struct soundbus_dev *sdev;
+       int masks_inited = 0, err;
+       struct codec_info_item *cii, *rev;
+       struct snd_pcm_hardware *hw;
+       u64 formats = 0;
+       unsigned int rates = 0;
+       struct transfer_info v;
+       int result = 0;
+       int bus_factor = 0, sysclock_factor = 0;
+       int found_this;
+
+       mutex_lock(&i2sdev->lock);
+
+       get_pcm_info(i2sdev, in, &pi, &other);
+
+       hw = &pi->substream->runtime->hw;
+       sdev = &i2sdev->sound;
+
+       if (pi->active) {
+               /* alsa messed up */
+               result = -EBUSY;
+               goto out_unlock;
+       }
+
+       /* we now need to assign the hw */
+       list_for_each_entry(cii, &sdev->codec_list, list) {
+               struct transfer_info *ti = cii->codec->transfers;
+               bus_factor = cii->codec->bus_factor;
+               sysclock_factor = cii->codec->sysclock_factor;
+               while (ti->formats && ti->rates) {
+                       v = *ti;
+                       if (ti->transfer_in == in
+                           && cii->codec->usable(cii, ti, &v)) {
+                               if (masks_inited) {
+                                       formats &= v.formats;
+                                       rates &= v.rates;
+                               } else {
+                                       formats = v.formats;
+                                       rates = v.rates;
+                                       masks_inited = 1;
+                               }
+                       }
+                       ti++;
+               }
+       }
+       if (!masks_inited || !bus_factor || !sysclock_factor) {
+               result = -ENODEV;
+               goto out_unlock;
+       }
+       /* bus dependent stuff */
+       hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                  SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME;
+
+       CHECK_RATE(5512);
+       CHECK_RATE(8000);
+       CHECK_RATE(11025);
+       CHECK_RATE(16000);
+       CHECK_RATE(22050);
+       CHECK_RATE(32000);
+       CHECK_RATE(44100);
+       CHECK_RATE(48000);
+       CHECK_RATE(64000);
+       CHECK_RATE(88200);
+       CHECK_RATE(96000);
+       CHECK_RATE(176400);
+       CHECK_RATE(192000);
+       hw->rates = rates;
+
+       /* well. the codec might want 24 bits only, and we'll
+        * ever only transfer 24 bits, but they are top-aligned!
+        * So for alsa, we claim that we're doing full 32 bit
+        * while in reality we'll ignore the lower 8 bits of
+        * that when doing playback (they're transferred as 0
+        * as far as I know, no codecs we have are 32-bit capable
+        * so I can't really test) and when doing recording we'll
+        * always have those lower 8 bits recorded as 0 */
+       if (formats & SNDRV_PCM_FMTBIT_S24_BE)
+               formats |= SNDRV_PCM_FMTBIT_S32_BE;
+       if (formats & SNDRV_PCM_FMTBIT_U24_BE)
+               formats |= SNDRV_PCM_FMTBIT_U32_BE;
+       /* now mask off what we can support. I suppose we could
+        * also support S24_3LE and some similar formats, but I
+        * doubt there's a codec that would be able to use that,
+        * so we don't support it here. */
+       hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE |
+                                SNDRV_PCM_FMTBIT_U16_BE |
+                                SNDRV_PCM_FMTBIT_S32_BE |
+                                SNDRV_PCM_FMTBIT_U32_BE);
+
+       /* we need to set the highest and lowest rate possible.
+        * These are the highest and lowest rates alsa can
+        * support properly in its bitfield.
+        * Below, we'll use that to restrict to the rate
+        * currently in use (if any). */
+       hw->rate_min = 5512;
+       hw->rate_max = 192000;
+       /* if the other stream is active, then we can only
+        * support what it is currently using.
+        * FIXME: I lied. This comment is wrong. We can support
+        * anything that works with the same serial format, ie.
+        * when recording 24 bit sound we can well play 16 bit
+        * sound at the same time iff using the same transfer mode.
+        */
+       if (other->active) {
+               /* FIXME: is this guaranteed by the alsa api? */
+               hw->formats &= (1ULL << i2sdev->format);
+               /* see above, restrict rates to the one we already have */
+               hw->rate_min = i2sdev->rate;
+               hw->rate_max = i2sdev->rate;
+       }
+
+       hw->channels_min = 2;
+       hw->channels_max = 2;
+       /* these are somewhat arbitrary */
+       hw->buffer_bytes_max = 131072;
+       hw->period_bytes_min = 256;
+       hw->period_bytes_max = 16384;
+       hw->periods_min = 3;
+       hw->periods_max = MAX_DBDMA_COMMANDS;
+       list_for_each_entry(cii, &sdev->codec_list, list) {
+               if (cii->codec->open) {
+                       err = cii->codec->open(cii, pi->substream);
+                       if (err) {
+                               result = err;
+                               /* unwind */
+                               found_this = 0;
+                               list_for_each_entry_reverse(rev,
+                                   &sdev->codec_list, list) {
+                                       if (found_this && rev->codec->close) {
+                                               rev->codec->close(rev,
+                                                               pi->substream);
+                                       }
+                                       if (rev == cii)
+                                               found_this = 1;
+                               }
+                               goto out_unlock;
+                       }
+               }
+       }
+
+ out_unlock:
+       mutex_unlock(&i2sdev->lock);
+       return result;
+}
+
+#undef CHECK_RATE
+
+static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
+{
+       struct codec_info_item *cii;
+       struct pcm_info *pi;
+       int err = 0, tmp;
+
+       mutex_lock(&i2sdev->lock);
+
+       get_pcm_info(i2sdev, in, &pi, NULL);
+
+       list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+               if (cii->codec->close) {
+                       tmp = cii->codec->close(cii, pi->substream);
+                       if (tmp)
+                               err = tmp;
+               }
+       }
+
+       pi->substream = NULL;
+       pi->active = 0;
+       mutex_unlock(&i2sdev->lock);
+       return err;
+}
+
+static int i2sbus_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params)
+{
+       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+}
+
+static int i2sbus_hw_free(struct snd_pcm_substream *substream)
+{
+       snd_pcm_lib_free_pages(substream);
+       return 0;
+}
+
+static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
+{
+       /* whee. Hard work now. The user has selected a bitrate
+        * and bit format, so now we have to program our
+        * I2S controller appropriately. */
+       struct snd_pcm_runtime *runtime;
+       struct dbdma_cmd *command;
+       int i, periodsize;
+       dma_addr_t offset;
+       struct bus_info bi;
+       struct codec_info_item *cii;
+       int sfr = 0;            /* serial format register */
+       int dws = 0;            /* data word sizes reg */
+       int input_16bit;
+       struct pcm_info *pi, *other;
+       int cnt;
+       int result = 0;
+
+       mutex_lock(&i2sdev->lock);
+
+       get_pcm_info(i2sdev, in, &pi, &other);
+
+       if (pi->dbdma_ring.running) {
+               result = -EBUSY;
+               goto out_unlock;
+       }
+
+       runtime = pi->substream->runtime;
+       pi->active = 1;
+       if (other->active &&
+           ((i2sdev->format != runtime->format)
+            || (i2sdev->rate != runtime->rate))) {
+               result = -EINVAL;
+               goto out_unlock;
+       }
+
+       i2sdev->format = runtime->format;
+       i2sdev->rate = runtime->rate;
+
+       periodsize = snd_pcm_lib_period_bytes(pi->substream);
+       pi->current_period = 0;
+
+       /* generate dbdma command ring first */
+       command = pi->dbdma_ring.cmds;
+       offset = runtime->dma_addr;
+       for (i = 0; i < pi->substream->runtime->periods;
+            i++, command++, offset += periodsize) {
+               memset(command, 0, sizeof(struct dbdma_cmd));
+               command->command =
+                   cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS);
+               command->phy_addr = cpu_to_le32(offset);
+               command->req_count = cpu_to_le16(periodsize);
+               command->xfer_status = cpu_to_le16(0);
+       }
+       /* last one branches back to first */
+       command--;
+       command->command |= cpu_to_le16(BR_ALWAYS);
+       command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start);
+
+       /* ok, let's set the serial format and stuff */
+       switch (runtime->format) {
+       /* 16 bit formats */
+       case SNDRV_PCM_FORMAT_S16_BE:
+       case SNDRV_PCM_FORMAT_U16_BE:
+               /* FIXME: if we add different bus factors we need to
+                * do more here!! */
+               bi.bus_factor = 0;
+               list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+                       bi.bus_factor = cii->codec->bus_factor;
+                       break;
+               }
+               if (!bi.bus_factor) {
+                       result = -ENODEV;
+                       goto out_unlock;
+               }
+               input_16bit = 1;
+               break;
+       case SNDRV_PCM_FORMAT_S32_BE:
+       case SNDRV_PCM_FORMAT_U32_BE:
+               /* force 64x bus speed, otherwise the data cannot be
+                * transferred quickly enough! */
+               bi.bus_factor = 64;
+               input_16bit = 0;
+               break;
+       default:
+               result = -EINVAL;
+               goto out_unlock;
+       }
+       /* we assume all sysclocks are the same! */
+       list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+               bi.sysclock_factor = cii->codec->sysclock_factor;
+               break;
+       }
+
+       if (clock_and_divisors(bi.sysclock_factor,
+                              bi.bus_factor,
+                              runtime->rate,
+                              &sfr) < 0) {
+               result = -EINVAL;
+               goto out_unlock;
+       }
+       switch (bi.bus_factor) {
+       case 32:
+               sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X;
+               break;
+       case 64:
+               sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X;
+               break;
+       }
+       /* FIXME: THIS ASSUMES MASTER ALL THE TIME */
+       sfr |= I2S_SF_SCLK_MASTER;
+
+       list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+               int err = 0;
+               if (cii->codec->prepare)
+                       err = cii->codec->prepare(cii, &bi, pi->substream);
+               if (err) {
+                       result = err;
+                       goto out_unlock;
+               }
+       }
+       /* codecs are fine with it, so set our clocks */
+       if (input_16bit)
+               dws =   (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) |
+                       (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) |
+                       I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT;
+       else
+               dws =   (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) |
+                       (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) |
+                       I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT;
+
+       /* early exit if already programmed correctly */
+       /* not locking these is fine since we touch them only in this function */
+       if (in_le32(&i2sdev->intfregs->serial_format) == sfr
+        && in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
+               goto out_unlock;
+
+       /* let's notify the codecs about clocks going away.
+        * For now we only do mastering on the i2s cell... */
+       list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+               if (cii->codec->switch_clock)
+                       cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE);
+
+       i2sbus_control_enable(i2sdev->control, i2sdev);
+       i2sbus_control_cell(i2sdev->control, i2sdev, 1);
+
+       out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED);
+
+       i2sbus_control_clock(i2sdev->control, i2sdev, 0);
+
+       msleep(1);
+
+       /* wait for clock stopped. This can apparently take a while... */
+       cnt = 100;
+       while (cnt-- &&
+           !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) {
+               msleep(5);
+       }
+       out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED);
+
+       /* not locking these is fine since we touch them only in this function */
+       out_le32(&i2sdev->intfregs->serial_format, sfr);
+       out_le32(&i2sdev->intfregs->data_word_sizes, dws);
+
+        i2sbus_control_enable(i2sdev->control, i2sdev);
+        i2sbus_control_cell(i2sdev->control, i2sdev, 1);
+        i2sbus_control_clock(i2sdev->control, i2sdev, 1);
+       msleep(1);
+
+       list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+               if (cii->codec->switch_clock)
+                       cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
+
+ out_unlock:
+       mutex_unlock(&i2sdev->lock);
+       return result;
+}
+
+static struct dbdma_cmd STOP_CMD = {
+       .command = __constant_cpu_to_le16(DBDMA_STOP),
+};
+
+static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
+{
+       struct codec_info_item *cii;
+       struct pcm_info *pi;
+       int timeout;
+       struct dbdma_cmd tmp;
+       int result = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&i2sdev->low_lock, flags);
+
+       get_pcm_info(i2sdev, in, &pi, NULL);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               if (pi->dbdma_ring.running) {
+                       result = -EALREADY;
+                       goto out_unlock;
+               }
+               list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+                       if (cii->codec->start)
+                               cii->codec->start(cii, pi->substream);
+               pi->dbdma_ring.running = 1;
+
+               /* reset dma engine */
+               out_le32(&pi->dbdma->control,
+                        0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
+               timeout = 100;
+               while (in_le32(&pi->dbdma->status) & RUN && timeout--)
+                       udelay(1);
+               if (timeout <= 0) {
+                       printk(KERN_ERR
+                              "i2sbus: error waiting for dma reset\n");
+                       result = -ENXIO;
+                       goto out_unlock;
+               }
+
+               /* write dma command buffer address to the dbdma chip */
+               out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
+               /* post PCI write */
+               mb();
+               (void)in_le32(&pi->dbdma->status);
+
+               /* change first command to STOP */
+               tmp = *pi->dbdma_ring.cmds;
+               *pi->dbdma_ring.cmds = STOP_CMD;
+
+               /* set running state, remember that the first command is STOP */
+               out_le32(&pi->dbdma->control, RUN | (RUN << 16));
+               timeout = 100;
+               /* wait for STOP to be executed */
+               while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--)
+                       udelay(1);
+               if (timeout <= 0) {
+                       printk(KERN_ERR "i2sbus: error waiting for dma stop\n");
+                       result = -ENXIO;
+                       goto out_unlock;
+               }
+               /* again, write dma command buffer address to the dbdma chip,
+                * this time of the first real command */
+               *pi->dbdma_ring.cmds = tmp;
+               out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
+               /* post write */
+               mb();
+               (void)in_le32(&pi->dbdma->status);
+
+               /* reset dma engine again */
+               out_le32(&pi->dbdma->control,
+                        0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
+               timeout = 100;
+               while (in_le32(&pi->dbdma->status) & RUN && timeout--)
+                       udelay(1);
+               if (timeout <= 0) {
+                       printk(KERN_ERR
+                              "i2sbus: error waiting for dma reset\n");
+                       result = -ENXIO;
+                       goto out_unlock;
+               }
+
+               /* wake up the chip with the next descriptor */
+               out_le32(&pi->dbdma->control,
+                        (RUN | WAKE) | ((RUN | WAKE) << 16));
+               /* get the frame count  */
+               pi->frame_count = in_le32(&i2sdev->intfregs->frame_count);
+
+               /* off you go! */
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               if (!pi->dbdma_ring.running) {
+                       result = -EALREADY;
+                       goto out_unlock;
+               }
+
+               /* turn off all relevant bits */
+               out_le32(&pi->dbdma->control,
+                        (RUN | WAKE | FLUSH | PAUSE) << 16);
+               {
+                       /* FIXME: move to own function */
+                       int timeout = 5000;
+                       while ((in_le32(&pi->dbdma->status) & RUN)
+                              && --timeout > 0)
+                               udelay(1);
+                       if (!timeout)
+                               printk(KERN_ERR
+                                      "i2sbus: timed out turning "
+                                      "off dbdma engine!\n");
+               }
+
+               pi->dbdma_ring.running = 0;
+               list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+                       if (cii->codec->stop)
+                               cii->codec->stop(cii, pi->substream);
+               break;
+       default:
+               result = -EINVAL;
+               goto out_unlock;
+       }
+
+ out_unlock:
+       spin_unlock_irqrestore(&i2sdev->low_lock, flags);
+       return result;
+}
+
+static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
+{
+       struct pcm_info *pi;
+       u32 fc;
+
+       get_pcm_info(i2sdev, in, &pi, NULL);
+
+       fc = in_le32(&i2sdev->intfregs->frame_count);
+       fc = fc - pi->frame_count;
+
+       return (bytes_to_frames(pi->substream->runtime,
+                       pi->current_period *
+                       snd_pcm_lib_period_bytes(pi->substream))
+               + fc) % pi->substream->runtime->buffer_size;
+}
+
+static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
+{
+       struct pcm_info *pi;
+       u32 fc;
+       u32 delta;
+
+       spin_lock(&i2sdev->low_lock);
+       get_pcm_info(i2sdev, in, &pi, NULL);
+
+       if (!pi->dbdma_ring.running) {
+               /* there was still an interrupt pending
+                * while we stopped. or maybe another
+                * processor (not the one that was stopping
+                * the DMA engine) was spinning above
+                * waiting for the lock. */
+               goto out_unlock;
+       }
+
+       fc = in_le32(&i2sdev->intfregs->frame_count);
+       /* a counter overflow does not change the calculation. */
+       delta = fc - pi->frame_count;
+
+       /* update current_period */
+       while (delta >= pi->substream->runtime->period_size) {
+               pi->current_period++;
+               delta = delta - pi->substream->runtime->period_size;
+       }
+
+       if (unlikely(delta)) {
+               /* Some interrupt came late, so check the dbdma.
+                * This special case exists to syncronize the frame_count with
+                * the dbdma transfer, but is hit every once in a while. */
+               int period;
+
+               period = (in_le32(&pi->dbdma->cmdptr)
+                       - pi->dbdma_ring.bus_cmd_start)
+                               / sizeof(struct dbdma_cmd);
+               pi->current_period = pi->current_period
+                                       % pi->substream->runtime->periods;
+
+               while (pi->current_period != period) {
+                       pi->current_period++;
+                       pi->current_period %= pi->substream->runtime->periods;
+                       /* Set delta to zero, as the frame_count value is too
+                        * high (otherwise the code path will not be executed).
+                        * This corrects the fact that the frame_count is too
+                        * low at the beginning due to buffering. */
+                       delta = 0;
+               }
+       }
+
+       pi->frame_count = fc - delta;
+       pi->current_period %= pi->substream->runtime->periods;
+
+       spin_unlock(&i2sdev->low_lock);
+       /* may call _trigger again, hence needs to be unlocked */
+       snd_pcm_period_elapsed(pi->substream);
+       return;
+ out_unlock:
+       spin_unlock(&i2sdev->low_lock);
+}
+
+irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs)
+{
+       handle_interrupt((struct i2sbus_dev *)devid, 0);
+       return IRQ_HANDLED;
+}
+
+irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs)
+{
+       handle_interrupt((struct i2sbus_dev *)devid, 1);
+       return IRQ_HANDLED;
+}
+
+static int i2sbus_playback_open(struct snd_pcm_substream *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       i2sdev->out.substream = substream;
+       return i2sbus_pcm_open(i2sdev, 0);
+}
+
+static int i2sbus_playback_close(struct snd_pcm_substream *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+       int err;
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->out.substream != substream)
+               return -EINVAL;
+       err = i2sbus_pcm_close(i2sdev, 0);
+       if (!err)
+               i2sdev->out.substream = NULL;
+       return err;
+}
+
+static int i2sbus_playback_prepare(struct snd_pcm_substream *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->out.substream != substream)
+               return -EINVAL;
+       return i2sbus_pcm_prepare(i2sdev, 0);
+}
+
+static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->out.substream != substream)
+               return -EINVAL;
+       return i2sbus_pcm_trigger(i2sdev, 0, cmd);
+}
+
+static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
+                                                *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->out.substream != substream)
+               return 0;
+       return i2sbus_pcm_pointer(i2sdev, 0);
+}
+
+static struct snd_pcm_ops i2sbus_playback_ops = {
+       .open =         i2sbus_playback_open,
+       .close =        i2sbus_playback_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    i2sbus_hw_params,
+       .hw_free =      i2sbus_hw_free,
+       .prepare =      i2sbus_playback_prepare,
+       .trigger =      i2sbus_playback_trigger,
+       .pointer =      i2sbus_playback_pointer,
+};
+
+static int i2sbus_record_open(struct snd_pcm_substream *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       i2sdev->in.substream = substream;
+       return i2sbus_pcm_open(i2sdev, 1);
+}
+
+static int i2sbus_record_close(struct snd_pcm_substream *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+       int err;
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->in.substream != substream)
+               return -EINVAL;
+       err = i2sbus_pcm_close(i2sdev, 1);
+       if (!err)
+               i2sdev->in.substream = NULL;
+       return err;
+}
+
+static int i2sbus_record_prepare(struct snd_pcm_substream *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->in.substream != substream)
+               return -EINVAL;
+       return i2sbus_pcm_prepare(i2sdev, 1);
+}
+
+static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->in.substream != substream)
+               return -EINVAL;
+       return i2sbus_pcm_trigger(i2sdev, 1, cmd);
+}
+
+static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
+                                              *substream)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+       if (!i2sdev)
+               return -EINVAL;
+       if (i2sdev->in.substream != substream)
+               return 0;
+       return i2sbus_pcm_pointer(i2sdev, 1);
+}
+
+static struct snd_pcm_ops i2sbus_record_ops = {
+       .open =         i2sbus_record_open,
+       .close =        i2sbus_record_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    i2sbus_hw_params,
+       .hw_free =      i2sbus_hw_free,
+       .prepare =      i2sbus_record_prepare,
+       .trigger =      i2sbus_record_trigger,
+       .pointer =      i2sbus_record_pointer,
+};
+
+static void i2sbus_private_free(struct snd_pcm *pcm)
+{
+       struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm);
+       struct codec_info_item *p, *tmp;
+
+       i2sdev->sound.pcm = NULL;
+       i2sdev->out.created = 0;
+       i2sdev->in.created = 0;
+       list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) {
+               printk(KERN_ERR "i2sbus: a codec didn't unregister!\n");
+               list_del(&p->list);
+               module_put(p->codec->owner);
+               kfree(p);
+       }
+       soundbus_dev_put(&i2sdev->sound);
+       module_put(THIS_MODULE);
+}
+
+/* FIXME: this function needs an error handling strategy with labels */
+int
+i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
+                   struct codec_info *ci, void *data)
+{
+       int err, in = 0, out = 0;
+       struct transfer_info *tmp;
+       struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev);
+       struct codec_info_item *cii;
+
+       if (!dev->pcmname || dev->pcmid == -1) {
+               printk(KERN_ERR "i2sbus: pcm name and id must be set!\n");
+               return -EINVAL;
+       }
+
+       list_for_each_entry(cii, &dev->codec_list, list) {
+               if (cii->codec_data == data)
+                       return -EALREADY;
+       }
+
+       if (!ci->transfers || !ci->transfers->formats
+           || !ci->transfers->rates || !ci->usable)
+               return -EINVAL;
+
+       /* we currently code the i2s transfer on the clock, and support only
+        * 32 and 64 */
+       if (ci->bus_factor != 32 && ci->bus_factor != 64)
+               return -EINVAL;
+
+       /* If you want to fix this, you need to keep track of what transport infos
+        * are to be used, which codecs they belong to, and then fix all the
+        * sysclock/busclock stuff above to depend on which is usable */
+       list_for_each_entry(cii, &dev->codec_list, list) {
+               if (cii->codec->sysclock_factor != ci->sysclock_factor) {
+                       printk(KERN_DEBUG
+                              "cannot yet handle multiple different sysclocks!\n");
+                       return -EINVAL;
+               }
+               if (cii->codec->bus_factor != ci->bus_factor) {
+                       printk(KERN_DEBUG
+                              "cannot yet handle multiple different bus clocks!\n");
+                       return -EINVAL;
+               }
+       }
+
+       tmp = ci->transfers;
+       while (tmp->formats && tmp->rates) {
+               if (tmp->transfer_in)
+                       in = 1;
+               else
+                       out = 1;
+               tmp++;
+       }
+
+       cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL);
+       if (!cii) {
+               printk(KERN_DEBUG "i2sbus: failed to allocate cii\n");
+               return -ENOMEM;
+       }
+
+       /* use the private data to point to the codec info */
+       cii->sdev = soundbus_dev_get(dev);
+       cii->codec = ci;
+       cii->codec_data = data;
+
+       if (!cii->sdev) {
+               printk(KERN_DEBUG
+                      "i2sbus: failed to get soundbus dev reference\n");
+               kfree(cii);
+               return -ENODEV;
+       }
+
+       if (!try_module_get(THIS_MODULE)) {
+               printk(KERN_DEBUG "i2sbus: failed to get module reference!\n");
+               soundbus_dev_put(dev);
+               kfree(cii);
+               return -EBUSY;
+       }
+
+       if (!try_module_get(ci->owner)) {
+               printk(KERN_DEBUG
+                      "i2sbus: failed to get module reference to codec owner!\n");
+               module_put(THIS_MODULE);
+               soundbus_dev_put(dev);
+               kfree(cii);
+               return -EBUSY;
+       }
+
+       if (!dev->pcm) {
+               err = snd_pcm_new(card,
+                                 dev->pcmname,
+                                 dev->pcmid,
+                                 0,
+                                 0,
+                                 &dev->pcm);
+               if (err) {
+                       printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
+                       kfree(cii);
+                       module_put(ci->owner);
+                       soundbus_dev_put(dev);
+                       module_put(THIS_MODULE);
+                       return err;
+               }
+       }
+
+       /* ALSA yet again sucks.
+        * If it is ever fixed, remove this line. See below. */
+       out = in = 1;
+
+       if (!i2sdev->out.created && out) {
+               if (dev->pcm->card != card) {
+                       /* eh? */
+                       printk(KERN_ERR
+                              "Can't attach same bus to different cards!\n");
+                       module_put(ci->owner);
+                       kfree(cii);
+                       soundbus_dev_put(dev);
+                       module_put(THIS_MODULE);
+                       return -EINVAL;
+               }
+               if ((err =
+                    snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) {
+                       module_put(ci->owner);
+                       kfree(cii);
+                       soundbus_dev_put(dev);
+                       module_put(THIS_MODULE);
+                       return err;
+               }
+               snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                               &i2sbus_playback_ops);
+               i2sdev->out.created = 1;
+       }
+
+       if (!i2sdev->in.created && in) {
+               if (dev->pcm->card != card) {
+                       printk(KERN_ERR
+                              "Can't attach same bus to different cards!\n");
+                       module_put(ci->owner);
+                       kfree(cii);
+                       soundbus_dev_put(dev);
+                       module_put(THIS_MODULE);
+                       return -EINVAL;
+               }
+               if ((err =
+                    snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) {
+                       module_put(ci->owner);
+                       kfree(cii);
+                       soundbus_dev_put(dev);
+                       module_put(THIS_MODULE);
+                       return err;
+               }
+               snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
+                               &i2sbus_record_ops);
+               i2sdev->in.created = 1;
+       }
+
+       /* so we have to register the pcm after adding any substream
+        * to it because alsa doesn't create the devices for the
+        * substreams when we add them later.
+        * Therefore, force in and out on both busses (above) and
+        * register the pcm now instead of just after creating it.
+        */
+       err = snd_device_register(card, dev->pcm);
+       if (err) {
+               printk(KERN_ERR "i2sbus: error registering new pcm\n");
+               module_put(ci->owner);
+               kfree(cii);
+               soundbus_dev_put(dev);
+               module_put(THIS_MODULE);
+               return err;
+       }
+       /* no errors any more, so let's add this to our list */
+       list_add(&cii->list, &dev->codec_list);
+
+       dev->pcm->private_data = i2sdev;
+       dev->pcm->private_free = i2sbus_private_free;
+
+       /* well, we really should support scatter/gather DMA */
+       snd_pcm_lib_preallocate_pages_for_all(
+               dev->pcm, SNDRV_DMA_TYPE_DEV,
+               snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)),
+               64 * 1024, 64 * 1024);
+
+       return 0;
+}
+
+void i2sbus_detach_codec(struct soundbus_dev *dev, void *data)
+{
+       struct codec_info_item *cii = NULL, *i;
+
+       list_for_each_entry(i, &dev->codec_list, list) {
+               if (i->codec_data == data) {
+                       cii = i;
+                       break;
+               }
+       }
+       if (cii) {
+               list_del(&cii->list);
+               module_put(cii->codec->owner);
+               kfree(cii);
+       }
+       /* no more codecs, but still a pcm? */
+       if (list_empty(&dev->codec_list) && dev->pcm) {
+               /* the actual cleanup is done by the callback above! */
+               snd_device_free(dev->pcm->card, dev->pcm);
+       }
+}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
new file mode 100644 (file)
index 0000000..0c69d20
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * i2sbus driver -- private definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __I2SBUS_H
+#define __I2SBUS_H
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
+#include <sound/pcm.h>
+
+#include <asm/prom.h>
+#include <asm/pmac_feature.h>
+#include <asm/dbdma.h>
+
+#include "i2sbus-interface.h"
+#include "../soundbus.h"
+
+struct i2sbus_control {
+       struct list_head list;
+       struct macio_chip *macio;
+};
+
+#define MAX_DBDMA_COMMANDS     32
+
+struct dbdma_command_mem {
+       dma_addr_t bus_addr;
+       dma_addr_t bus_cmd_start;
+       struct dbdma_cmd *cmds;
+       void *space;
+       int size;
+       u32 running:1;
+};
+
+struct pcm_info {
+       u32 created:1, /* has this direction been created with alsa? */
+           active:1;  /* is this stream active? */
+       /* runtime information */
+       struct snd_pcm_substream *substream;
+       int current_period;
+       u32 frame_count;
+       struct dbdma_command_mem dbdma_ring;
+       volatile struct dbdma_regs __iomem *dbdma;
+};
+
+enum {
+       aoa_resource_i2smmio = 0,
+       aoa_resource_txdbdma,
+       aoa_resource_rxdbdma,
+};
+
+struct i2sbus_dev {
+       struct soundbus_dev sound;
+       struct macio_dev *macio;
+       struct i2sbus_control *control;
+       volatile struct i2s_interface_regs __iomem *intfregs;
+
+       struct resource resources[3];
+       struct resource *allocated_resource[3];
+       int interrupts[3];
+       char rnames[3][32];
+
+       /* info about currently active substreams */
+       struct pcm_info out, in;
+       snd_pcm_format_t format;
+       unsigned int rate;
+
+       /* list for a single controller */
+       struct list_head item;
+       /* number of bus on controller */
+       int bus_number;
+       /* for use by control layer */
+       struct pmf_function *enable,
+                           *cell_enable,
+                           *cell_disable,
+                           *clock_enable,
+                           *clock_disable;
+
+       /* locks */
+       /* spinlock for low-level interrupt locking */
+       spinlock_t low_lock;
+       /* mutex for high-level consistency */
+       struct mutex lock;
+};
+
+#define soundbus_dev_to_i2sbus_dev(sdev) \
+               container_of(sdev, struct i2sbus_dev, sound)
+
+/* pcm specific functions */
+extern int
+i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
+                   struct codec_info *ci, void *data);
+extern void
+i2sbus_detach_codec(struct soundbus_dev *dev, void *data);
+extern irqreturn_t
+i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs);
+extern irqreturn_t
+i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs);
+
+/* control specific functions */
+extern int i2sbus_control_init(struct macio_dev* dev,
+                              struct i2sbus_control **c);
+extern void i2sbus_control_destroy(struct i2sbus_control *c);
+extern int i2sbus_control_add_dev(struct i2sbus_control *c,
+                                 struct i2sbus_dev *i2sdev);
+extern void i2sbus_control_remove_dev(struct i2sbus_control *c,
+                                     struct i2sbus_dev *i2sdev);
+extern int i2sbus_control_enable(struct i2sbus_control *c,
+                                struct i2sbus_dev *i2sdev);
+extern int i2sbus_control_cell(struct i2sbus_control *c,
+                              struct i2sbus_dev *i2sdev,
+                              int enable);
+extern int i2sbus_control_clock(struct i2sbus_control *c,
+                               struct i2sbus_dev *i2sdev,
+                               int enable);
+#endif /* __I2SBUS_H */
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h
new file mode 100644 (file)
index 0000000..5c27297
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * soundbus generic definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __SOUNDBUS_H
+#define __SOUNDBUS_H
+
+#include <asm/of_device.h>
+#include <sound/pcm.h>
+#include <linux/list.h>
+
+
+/* When switching from master to slave or the other way around,
+ * you don't want to have the codec chip acting as clock source
+ * while the bus still is.
+ * More importantly, while switch from slave to master, you need
+ * to turn off the chip's master function first, but then there's
+ * no clock for a while and other chips might reset, so we notify
+ * their drivers after having switched.
+ * The constants here are codec-point of view, so when we switch
+ * the soundbus to master we tell the codec we're going to switch
+ * and give it CLOCK_SWITCH_PREPARE_SLAVE!
+ */
+enum clock_switch {
+       CLOCK_SWITCH_PREPARE_SLAVE,
+       CLOCK_SWITCH_PREPARE_MASTER,
+       CLOCK_SWITCH_SLAVE,
+       CLOCK_SWITCH_MASTER,
+       CLOCK_SWITCH_NOTIFY,
+};
+
+/* information on a transfer the codec can take */
+struct transfer_info {
+       u64 formats;            /* SNDRV_PCM_FMTBIT_* */
+       unsigned int rates;     /* SNDRV_PCM_RATE_* */
+       /* flags */
+       u32 transfer_in:1, /* input = 1, output = 0 */
+           must_be_clock_source:1;
+       /* for codecs to distinguish among their TIs */
+       int tag;
+};
+
+struct codec_info_item {
+       struct codec_info *codec;
+       void *codec_data;
+       struct soundbus_dev *sdev;
+       /* internal, to be used by the soundbus provider */
+       struct list_head list;
+};
+
+/* for prepare, where the codecs need to know
+ * what we're going to drive the bus with */
+struct bus_info {
+       /* see below */
+       int sysclock_factor;
+       int bus_factor;
+};
+
+/* information on the codec itself, plus function pointers */
+struct codec_info {
+       /* the module this lives in */
+       struct module *owner;
+
+       /* supported transfer possibilities, array terminated by
+        * formats or rates being 0. */
+       struct transfer_info *transfers;
+
+       /* Master clock speed factor
+        * to be used (master clock speed = sysclock_factor * sampling freq)
+        * Unused if the soundbus provider has no such notion.
+        */
+       int sysclock_factor;
+
+       /* Bus factor, bus clock speed = bus_factor * sampling freq)
+        * Unused if the soundbus provider has no such notion.
+        */
+       int bus_factor;
+
+       /* operations */
+       /* clock switching, see above */
+       int (*switch_clock)(struct codec_info_item *cii,
+                           enum clock_switch clock);
+
+       /* called for each transfer_info when the user
+        * opens the pcm device to determine what the
+        * hardware can support at this point in time.
+        * That can depend on other user-switchable controls.
+        * Return 1 if usable, 0 if not.
+        * out points to another instance of a transfer_info
+        * which is initialised to the values in *ti, and
+        * it's format and rate values can be modified by
+        * the callback if it is necessary to further restrict
+        * the formats that can be used at the moment, for
+        * example when one codec has multiple logical codec
+        * info structs for multiple inputs.
+        */
+       int (*usable)(struct codec_info_item *cii,
+                     struct transfer_info *ti,
+                     struct transfer_info *out);
+
+       /* called when pcm stream is opened, probably not implemented
+        * most of the time since it isn't too useful */
+       int (*open)(struct codec_info_item *cii,
+                   struct snd_pcm_substream *substream);
+
+       /* called when the pcm stream is closed, at this point
+        * the user choices can all be unlocked (see below) */
+       int (*close)(struct codec_info_item *cii,
+                    struct snd_pcm_substream *substream);
+
+       /* if the codec must forbid some user choices because
+        * they are not valid with the substream/transfer info,
+        * it must do so here. Example: no digital output for
+        * incompatible framerate, say 8KHz, on Onyx.
+        * If the selected stuff in the substream is NOT
+        * compatible, you have to reject this call! */
+       int (*prepare)(struct codec_info_item *cii,
+                      struct bus_info *bi,
+                      struct snd_pcm_substream *substream);
+
+       /* start() is called before data is pushed to the codec.
+        * Note that start() must be atomic! */
+       int (*start)(struct codec_info_item *cii,
+                    struct snd_pcm_substream *substream);
+
+       /* stop() is called after data is no longer pushed to the codec.
+        * Note that stop() must be atomic! */
+       int (*stop)(struct codec_info_item *cii,
+                   struct snd_pcm_substream *substream);
+
+       int (*suspend)(struct codec_info_item *cii, pm_message_t state);
+       int (*resume)(struct codec_info_item *cii);
+};
+
+/* information on a soundbus device */
+struct soundbus_dev {
+       /* the bus it belongs to */
+       struct list_head onbuslist;
+
+       /* the of device it represents */
+       struct of_device ofdev;
+
+       /* what modules go by */
+       char modalias[32];
+
+       /* These fields must be before attach_codec can be called.
+        * They should be set by the owner of the alsa card object
+        * that is needed, and whoever sets them must make sure
+        * that they are unique within that alsa card object. */
+       char *pcmname;
+       int pcmid;
+
+       /* this is assigned by the soundbus provider in attach_codec */
+       struct snd_pcm *pcm;
+
+       /* operations */
+       /* attach a codec to this soundbus, give the alsa
+        * card object the PCMs for this soundbus should be in.
+        * The 'data' pointer must be unique, it is used as the
+        * key for detach_codec(). */
+       int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card,
+                           struct codec_info *ci, void *data);
+       void (*detach_codec)(struct soundbus_dev *dev, void *data);
+       /* TODO: suspend/resume */
+
+       /* private for the soundbus provider */
+       struct list_head codec_list;
+       u32 have_out:1, have_in:1;
+};
+#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev)
+#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev)
+
+extern int soundbus_add_one(struct soundbus_dev *dev);
+extern void soundbus_remove_one(struct soundbus_dev *dev);
+
+extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev);
+extern void soundbus_dev_put(struct soundbus_dev *dev);
+
+struct soundbus_driver {
+       char *name;
+       struct module *owner;
+
+       /* we don't implement any matching at all */
+
+       int     (*probe)(struct soundbus_dev* dev);
+       int     (*remove)(struct soundbus_dev* dev);
+
+       int     (*suspend)(struct soundbus_dev* dev, pm_message_t state);
+       int     (*resume)(struct soundbus_dev* dev);
+       int     (*shutdown)(struct soundbus_dev* dev);
+
+       struct device_driver driver;
+};
+#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver)
+
+extern int soundbus_register_driver(struct soundbus_driver *drv);
+extern void soundbus_unregister_driver(struct soundbus_driver *drv);
+
+#endif /* __SOUNDBUS_H */
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c
new file mode 100644 (file)
index 0000000..f580942
--- /dev/null
@@ -0,0 +1,42 @@
+#include <linux/kernel.h>
+#include <linux/stat.h>
+/* FIX UP */
+#include "soundbus.h"
+
+#define soundbus_config_of_attr(field, format_string)                  \
+static ssize_t                                                         \
+field##_show (struct device *dev, struct device_attribute *attr,       \
+              char *buf)                                               \
+{                                                                      \
+       struct soundbus_dev *mdev = to_soundbus_device (dev);           \
+       return sprintf (buf, format_string, mdev->ofdev.node->field);   \
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct soundbus_dev *sdev = to_soundbus_device(dev);
+       struct of_device *of = &sdev->ofdev;
+       int length;
+
+       if (*sdev->modalias) {
+               strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
+               strcat(buf, "\n");
+               length = strlen(buf);
+       } else {
+               length = sprintf(buf, "of:N%sT%s\n",
+                                of->node->name, of->node->type);
+       }
+
+       return length;
+}
+
+soundbus_config_of_attr (name, "%s\n");
+soundbus_config_of_attr (type, "%s\n");
+
+struct device_attribute soundbus_dev_attrs[] = {
+       __ATTR_RO(name),
+       __ATTR_RO(type),
+       __ATTR_RO(modalias),
+       __ATTR_NULL
+};
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
new file mode 100644 (file)
index 0000000..aad0e69
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Power management for audio on multifunction CS5535 companion device
+ * Copyright (C) Jaya Kumar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/asoundef.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include "cs5535audio.h"
+
+static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
+{
+       /* 
+       we depend on snd_ac97_suspend to tell the
+       AC97 codec to shutdown. the amd spec suggests
+       that the LNK_SHUTDOWN be done at the same time
+       that the codec power-down is issued. instead,
+       we do it just after rather than at the same 
+       time. excluding codec specific build_ops->suspend
+       ac97 powerdown hits:
+       0x8000 EAPD 
+       0x4000 Headphone amplifier 
+       0x0300 ADC & DAC 
+       0x0400 Analog Mixer powerdown (Vref on) 
+       I am not sure if this is the best that we can do.
+       The remainder to be investigated are:
+       - analog mixer (vref off) 0x0800
+       - AC-link powerdown 0x1000
+       - codec internal clock 0x2000
+       */
+
+       /* set LNK_SHUTDOWN to shutdown AC link */
+       cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN);
+
+}
+
+int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct cs5535audio *cs5535au = card->private_data;
+       int i;
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+       for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
+               struct cs5535audio_dma *dma = &cs5535au->dmas[i];
+               if (dma && dma->substream && !dma->suspended) 
+                       dma->saved_prd = dma->ops->read_prd(cs5535au);
+       }
+       snd_pcm_suspend_all(cs5535au->pcm);
+       snd_ac97_suspend(cs5535au->ac97);
+       /* save important regs, then disable aclink in hw */
+       snd_cs5535audio_stop_hardware(cs5535au);
+       pci_disable_device(pci);
+       pci_save_state(pci);
+
+       return 0;
+}
+
+int snd_cs5535audio_resume(struct pci_dev *pci)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct cs5535audio *cs5535au = card->private_data;
+       u32 tmp;
+       int timeout;
+       int i;
+
+       pci_restore_state(pci);
+       pci_enable_device(pci);
+       pci_set_master(pci);
+
+       /* set LNK_WRM_RST to reset AC link */
+       cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
+
+       timeout = 50;
+       do {
+               tmp = cs_readl(cs5535au, ACC_CODEC_STATUS);
+               if (tmp & PRM_RDY_STS)
+                       break;
+               udelay(1);
+       } while (--timeout);
+
+       if (!timeout)
+               snd_printk(KERN_ERR "Failure getting AC Link ready\n");
+
+       /* we depend on ac97 to perform the codec power up */
+       snd_ac97_resume(cs5535au->ac97);
+       /* set up rate regs, dma. actual initiation is done in trig */
+       for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
+               struct cs5535audio_dma *dma = &cs5535au->dmas[i];
+               if (dma && dma->substream && dma->suspended) {
+                       dma->substream->ops->prepare(dma->substream);
+                       dma->ops->setup_prd(cs5535au, dma->saved_prd);
+               }
+       }
+               
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+
+       return 0;
+}
+
diff --git a/sound/pci/echoaudio/Makefile b/sound/pci/echoaudio/Makefile
new file mode 100644 (file)
index 0000000..7b576ae
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# Makefile for ALSA Echoaudio soundcard drivers
+# Copyright (c) 2003 by Giuliano Pochini <pochini@shiny.it>
+#
+
+snd-darla20-objs := darla20.o
+snd-gina20-objs := gina20.o
+snd-layla20-objs := layla20.o
+snd-darla24-objs := darla24.o
+snd-gina24-objs := gina24.o
+snd-layla24-objs := layla24.o
+snd-mona-objs := mona.o
+snd-mia-objs := mia.o
+snd-echo3g-objs := echo3g.o
+snd-indigo-objs := indigo.o
+snd-indigoio-objs := indigoio.o
+snd-indigodj-objs := indigodj.o
+
+obj-$(CONFIG_SND_DARLA20) += snd-darla20.o
+obj-$(CONFIG_SND_GINA20) += snd-gina20.o
+obj-$(CONFIG_SND_LAYLA20) += snd-layla20.o
+obj-$(CONFIG_SND_DARLA24) += snd-darla24.o
+obj-$(CONFIG_SND_GINA24) += snd-gina24.o
+obj-$(CONFIG_SND_LAYLA24) += snd-layla24.o
+obj-$(CONFIG_SND_MONA) += snd-mona.o
+obj-$(CONFIG_SND_MIA) += snd-mia.o
+obj-$(CONFIG_SND_ECHO3G) += snd-echo3g.o
+obj-$(CONFIG_SND_INDIGO) += snd-indigo.o
+obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o
+obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
new file mode 100644 (file)
index 0000000..b7108e2
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHOGALS_FAMILY
+#define ECHOCARD_DARLA20
+#define ECHOCARD_NAME "Darla20"
+#define ECHOCARD_HAS_MONITOR
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 0 */
+#define PX_ANALOG_IN   8       /* 2 */
+#define PX_DIGITAL_IN  10      /* 0 */
+#define PX_NUM         10
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 8 */
+#define BX_DIGITAL_OUT 8       /* 0 */
+#define BX_ANALOG_IN   8       /* 2 */
+#define BX_DIGITAL_IN  10      /* 0 */
+#define BX_NUM         10
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_DARLA20_DSP 0
+
+static const struct firmware card_fw[] = {
+       {0, "darla20_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0},      /* DSP 56301 Darla20 rev.0 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+       .rate_min = 44100,
+       .rate_max = 48000,
+       .channels_min = 1,
+       .channels_max = 2,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+
+#include "darla20_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
diff --git a/sound/pci/echoaudio/darla20_dsp.c b/sound/pci/echoaudio/darla20_dsp.c
new file mode 100644 (file)
index 0000000..4159e3b
--- /dev/null
@@ -0,0 +1,125 @@
+/***************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Darla20\n"));
+       snd_assert((subdevice_id & 0xfff0) == DARLA20, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_DARLA20_DSP];
+       chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
+       chip->clock_state = GD_CLOCK_UNDEF;
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+/* The Darla20 has no external clock sources */
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       return ECHO_CLOCK_BIT_INTERNAL;
+}
+
+
+
+/* The Darla20 has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u8 clock_state, spdif_status;
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       switch (rate) {
+       case 44100:
+               clock_state = GD_CLOCK_44;
+               spdif_status = GD_SPDIF_STATUS_44;
+               break;
+       case 48000:
+               clock_state = GD_CLOCK_48;
+               spdif_status = GD_SPDIF_STATUS_48;
+               break;
+       default:
+               clock_state = GD_CLOCK_NOCHANGE;
+               spdif_status = GD_SPDIF_STATUS_NOCHANGE;
+               break;
+       }
+
+       if (chip->clock_state == clock_state)
+               clock_state = GD_CLOCK_NOCHANGE;
+       if (spdif_status == chip->spdif_status)
+               spdif_status = GD_SPDIF_STATUS_NOCHANGE;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);
+       chip->comm_page->gd_clock_state = clock_state;
+       chip->comm_page->gd_spdif_status = spdif_status;
+       chip->comm_page->gd_resampler_state = 3;        /* magic number - should always be 3 */
+
+       /* Save the new audio state if it changed */
+       if (clock_state != GD_CLOCK_NOCHANGE)
+               chip->clock_state = clock_state;
+       if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
+               chip->spdif_status = spdif_status;
+       chip->sample_rate = rate;
+
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
+}
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
new file mode 100644 (file)
index 0000000..e59a982
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHOGALS_FAMILY
+#define ECHOCARD_DARLA24
+#define ECHOCARD_NAME "Darla24"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 0 */
+#define PX_ANALOG_IN   8       /* 2 */
+#define PX_DIGITAL_IN  10      /* 0 */
+#define PX_NUM         10
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 8 */
+#define BX_DIGITAL_OUT 8       /* 0 */
+#define BX_ANALOG_IN   8       /* 2 */
+#define BX_DIGITAL_IN  10      /* 0 */
+#define BX_NUM         10
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_DARLA24_DSP 0
+
+static const struct firmware card_fw[] = {
+       {0, "darla24_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0},      /* DSP 56301 Darla24 rev.0 */
+       {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0},      /* DSP 56301 Darla24 rev.1 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_8000_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+
+#include "darla24_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
diff --git a/sound/pci/echoaudio/darla24_dsp.c b/sound/pci/echoaudio/darla24_dsp.c
new file mode 100644 (file)
index 0000000..79938ee
--- /dev/null
@@ -0,0 +1,156 @@
+/***************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Darla24\n"));
+       snd_assert((subdevice_id & 0xfff0) == DARLA24, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_DARLA24_DSP];
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
+               ECHO_CLOCK_BIT_ESYNC;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock
+          detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_ESYNC)
+               clock_bits |= ECHO_CLOCK_BIT_ESYNC;
+
+       return clock_bits;
+}
+
+
+
+/* The Darla24 has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u8 clock;
+
+       switch (rate) {
+       case 96000:
+               clock = GD24_96000;
+               break;
+       case 88200:
+               clock = GD24_88200;
+               break;
+       case 48000:
+               clock = GD24_48000;
+               break;
+       case 44100:
+               clock = GD24_44100;
+               break;
+       case 32000:
+               clock = GD24_32000;
+               break;
+       case 22050:
+               clock = GD24_22050;
+               break;
+       case 16000:
+               clock = GD24_16000;
+               break;
+       case 11025:
+               clock = GD24_11025;
+               break;
+       case 8000:
+               clock = GD24_8000;
+               break;
+       default:
+               DE_ACT(("set_sample_rate: Error, invalid sample rate %d\n",
+                       rate));
+               return -EINVAL;
+       }
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock));
+       chip->sample_rate = rate;
+
+       /* Override the sample rate if this card is set to Echo sync. */
+       if (chip->input_clock == ECHO_CLOCK_ESYNC)
+               clock = GD24_EXT_SYNC;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP ? */
+       chip->comm_page->gd_clock_state = clock;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       snd_assert(clock == ECHO_CLOCK_INTERNAL ||
+                  clock == ECHO_CLOCK_ESYNC, return -EINVAL);
+       chip->input_clock = clock;
+       return set_sample_rate(chip, chip->sample_rate);
+}
+
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
new file mode 100644 (file)
index 0000000..12099fe
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHO3G_FAMILY
+#define ECHOCARD_ECHO3G
+#define ECHOCARD_NAME "Echo3G"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_ASIC
+#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+#define ECHOCARD_HAS_ADAT      6
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+#define ECHOCARD_HAS_MIDI
+#define ECHOCARD_HAS_PHANTOM_POWER
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0
+#define PX_DIGITAL_OUT chip->px_digital_out
+#define PX_ANALOG_IN   chip->px_analog_in
+#define PX_DIGITAL_IN  chip->px_digital_in
+#define PX_NUM         chip->px_num
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0
+#define BX_DIGITAL_OUT chip->bx_digital_out
+#define BX_ANALOG_IN   chip->bx_analog_in
+#define BX_DIGITAL_IN  chip->bx_digital_in
+#define BX_NUM         chip->bx_num
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER  0
+#define FW_ECHO3G_DSP  1
+#define FW_3G_ASIC     2
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "echo3g_dsp.fw"},
+       {0, "3g_asic.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0},      /* Echo 3G */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_32000 |
+                       SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000 |
+                       SNDRV_PCM_RATE_CONTINUOUS,
+       .rate_min = 32000,
+       .rate_max = 100000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+};
+
+#include "echo3g_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio_3g.c"
+#include "echoaudio.c"
+#include "midi.c"
diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c
new file mode 100644 (file)
index 0000000..d26a1d1
--- /dev/null
@@ -0,0 +1,131 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+static int load_asic(struct echoaudio *chip);
+static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode);
+static int set_digital_mode(struct echoaudio *chip, u8 mode);
+static int check_asic_status(struct echoaudio *chip);
+static int set_sample_rate(struct echoaudio *chip, u32 rate);
+static int set_input_clock(struct echoaudio *chip, u16 clock);
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int set_phantom_power(struct echoaudio *chip, char on);
+static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
+                            char force);
+
+#include <linux/irq.h>
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       local_irq_enable();
+       DE_INIT(("init_hw() - Echo3G\n"));
+       snd_assert((subdevice_id & 0xfff0) == ECHO3G, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->comm_page->e3g_frq_register =
+               __constant_cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2);
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->has_midi = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_ECHO3G_DSP];
+
+       /* Load the DSP code and the ASIC on the PCI card and get
+       what type of external box is attached */
+       err = load_firmware(chip);
+
+       if (err < 0) {
+               return err;
+       } else if (err == E3G_GINA3G_BOX_TYPE) {
+               chip->input_clock_types =       ECHO_CLOCK_BIT_INTERNAL |
+                                               ECHO_CLOCK_BIT_SPDIF |
+                                               ECHO_CLOCK_BIT_ADAT;
+               chip->card_name = "Gina3G";
+               chip->px_digital_out = chip->bx_digital_out = 6;
+               chip->px_analog_in = chip->bx_analog_in = 14;
+               chip->px_digital_in = chip->bx_digital_in = 16;
+               chip->px_num = chip->bx_num = 24;
+               chip->has_phantom_power = TRUE;
+               chip->hasnt_input_nominal_level = TRUE;
+       } else if (err == E3G_LAYLA3G_BOX_TYPE) {
+               chip->input_clock_types =       ECHO_CLOCK_BIT_INTERNAL |
+                                               ECHO_CLOCK_BIT_SPDIF |
+                                               ECHO_CLOCK_BIT_ADAT |
+                                               ECHO_CLOCK_BIT_WORD;
+               chip->card_name = "Layla3G";
+               chip->px_digital_out = chip->bx_digital_out = 8;
+               chip->px_analog_in = chip->bx_analog_in = 16;
+               chip->px_digital_in = chip->bx_digital_in = 24;
+               chip->px_num = chip->bx_num = 32;
+       } else {
+               return -ENODEV;
+       }
+
+       chip->digital_modes =   ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
+                               ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
+                               ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
+       chip->digital_mode =    DIGITAL_MODE_SPDIF_RCA;
+       chip->professional_spdif = FALSE;
+       chip->non_audio_spdif = FALSE;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+       err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA);
+       snd_assert(err >= 0, return err);
+       err = set_phantom_power(chip, 0);
+       snd_assert(err >= 0, return err);
+       err = set_professional_spdif(chip, TRUE);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static int set_phantom_power(struct echoaudio *chip, char on)
+{
+       u32 control_reg = le32_to_cpu(chip->comm_page->control_register);
+
+       if (on)
+               control_reg |= E3G_PHANTOM_POWER;
+       else
+               control_reg &= ~E3G_PHANTOM_POWER;
+
+       chip->phantom_power = on;
+       return write_control_reg(chip, control_reg,
+                                le32_to_cpu(chip->comm_page->e3g_frq_register),
+                                0);
+}
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
new file mode 100644 (file)
index 0000000..c3dafa2
--- /dev/null
@@ -0,0 +1,2196 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+MODULE_AUTHOR("Giuliano Pochini <pochini@shiny.it>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Echoaudio " ECHOCARD_NAME " soundcards driver");
+MODULE_SUPPORTED_DEVICE("{{Echoaudio," ECHOCARD_NAME "}}");
+MODULE_DEVICE_TABLE(pci, snd_echo_ids);
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for " ECHOCARD_NAME " soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for " ECHOCARD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard.");
+
+static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
+
+static int get_firmware(const struct firmware **fw_entry,
+                       const struct firmware *frm, struct echoaudio *chip)
+{
+       int err;
+       char name[30];
+       DE_ACT(("firmware requested: %s\n", frm->data));
+       snprintf(name, sizeof(name), "ea/%s", frm->data);
+       if ((err = request_firmware(fw_entry, name, pci_device(chip))) < 0)
+               snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err);
+       return err;
+}
+
+static void free_firmware(const struct firmware *fw_entry)
+{
+       release_firmware(fw_entry);
+       DE_ACT(("firmware released\n"));
+}
+
+
+
+/******************************************************************************
+       PCM interface
+******************************************************************************/
+
+static void audiopipe_free(struct snd_pcm_runtime *runtime)
+{
+       struct audiopipe *pipe = runtime->private_data;
+
+       if (pipe->sgpage.area)
+               snd_dma_free_pages(&pipe->sgpage);
+       kfree(pipe);
+}
+
+
+
+static int hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
+                                             struct snd_pcm_hw_rule *rule)
+{
+       struct snd_interval *c = hw_param_interval(params,
+                                                  SNDRV_PCM_HW_PARAM_CHANNELS);
+       struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_mask fmt;
+
+       snd_mask_any(&fmt);
+
+#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+       /* >=2 channels cannot be S32_BE */
+       if (c->min == 2) {
+               fmt.bits[0] &= ~SNDRV_PCM_FMTBIT_S32_BE;
+               return snd_mask_refine(f, &fmt);
+       }
+#endif
+       /* > 2 channels cannot be U8 and S32_BE */
+       if (c->min > 2) {
+               fmt.bits[0] &= ~(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_BE);
+               return snd_mask_refine(f, &fmt);
+       }
+       /* Mono is ok with any format */
+       return 0;
+}
+
+
+
+static int hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
+                                             struct snd_pcm_hw_rule *rule)
+{
+       struct snd_interval *c = hw_param_interval(params,
+                                                  SNDRV_PCM_HW_PARAM_CHANNELS);
+       struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_interval ch;
+
+       snd_interval_any(&ch);
+
+       /* S32_BE is mono (and stereo) only */
+       if (f->bits[0] == SNDRV_PCM_FMTBIT_S32_BE) {
+               ch.min = 1;
+#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+               ch.max = 2;
+#else
+               ch.max = 1;
+#endif
+               ch.integer = 1;
+               return snd_interval_refine(c, &ch);
+       }
+       /* U8 can be only mono or stereo */
+       if (f->bits[0] == SNDRV_PCM_FMTBIT_U8) {
+               ch.min = 1;
+               ch.max = 2;
+               ch.integer = 1;
+               return snd_interval_refine(c, &ch);
+       }
+       /* S16_LE, S24_3LE and S32_LE support any number of channels. */
+       return 0;
+}
+
+
+
+static int hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
+                                              struct snd_pcm_hw_rule *rule)
+{
+       struct snd_interval *c = hw_param_interval(params,
+                                                  SNDRV_PCM_HW_PARAM_CHANNELS);
+       struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_mask fmt;
+       u64 fmask;
+       snd_mask_any(&fmt);
+
+       fmask = fmt.bits[0] + ((u64)fmt.bits[1] << 32);
+
+       /* >2 channels must be S16_LE, S24_3LE or S32_LE */
+       if (c->min > 2) {
+               fmask &= SNDRV_PCM_FMTBIT_S16_LE |
+                        SNDRV_PCM_FMTBIT_S24_3LE |
+                        SNDRV_PCM_FMTBIT_S32_LE;
+       /* 1 channel must be S32_BE or S32_LE */
+       } else if (c->max == 1)
+               fmask &= SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE;
+#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+       /* 2 channels cannot be S32_BE */
+       else if (c->min == 2 && c->max == 2)
+               fmask &= ~SNDRV_PCM_FMTBIT_S32_BE;
+#endif
+       else
+               return 0;
+
+       fmt.bits[0] &= (u32)fmask;
+       fmt.bits[1] &= (u32)(fmask >> 32);
+       return snd_mask_refine(f, &fmt);
+}
+
+
+
+static int hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
+                                              struct snd_pcm_hw_rule *rule)
+{
+       struct snd_interval *c = hw_param_interval(params,
+                                                  SNDRV_PCM_HW_PARAM_CHANNELS);
+       struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_interval ch;
+       u64 fmask;
+
+       snd_interval_any(&ch);
+       ch.integer = 1;
+       fmask = f->bits[0] + ((u64)f->bits[1] << 32);
+
+       /* S32_BE is mono (and stereo) only */
+       if (fmask == SNDRV_PCM_FMTBIT_S32_BE) {
+               ch.min = 1;
+#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+               ch.max = 2;
+#else
+               ch.max = 1;
+#endif
+       /* U8 is stereo only */
+       } else if (fmask == SNDRV_PCM_FMTBIT_U8)
+               ch.min = ch.max = 2;
+       /* S16_LE and S24_3LE must be at least stereo */
+       else if (!(fmask & ~(SNDRV_PCM_FMTBIT_S16_LE |
+                              SNDRV_PCM_FMTBIT_S24_3LE)))
+               ch.min = 2;
+       else
+               return 0;
+
+       return snd_interval_refine(c, &ch);
+}
+
+
+
+/* Since the sample rate is a global setting, do allow the user to change the
+sample rate only if there is only one pcm device open. */
+static int hw_rule_sample_rate(struct snd_pcm_hw_params *params,
+                              struct snd_pcm_hw_rule *rule)
+{
+       struct snd_interval *rate = hw_param_interval(params,
+                                                     SNDRV_PCM_HW_PARAM_RATE);
+       struct echoaudio *chip = rule->private;
+       struct snd_interval fixed;
+
+       if (!chip->can_set_rate) {
+               snd_interval_any(&fixed);
+               fixed.min = fixed.max = chip->sample_rate;
+               return snd_interval_refine(rate, &fixed);
+       }
+       return 0;
+}
+
+
+static int pcm_open(struct snd_pcm_substream *substream,
+                   signed char max_channels)
+{
+       struct echoaudio *chip;
+       struct snd_pcm_runtime *runtime;
+       struct audiopipe *pipe;
+       int err, i;
+
+       if (max_channels <= 0)
+               return -EAGAIN;
+
+       chip = snd_pcm_substream_chip(substream);
+       runtime = substream->runtime;
+
+       pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL);
+       if (!pipe)
+               return -ENOMEM;
+       pipe->index = -1;               /* Not configured yet */
+
+       /* Set up hw capabilities and contraints */
+       memcpy(&pipe->hw, &pcm_hardware_skel, sizeof(struct snd_pcm_hardware));
+       DE_HWP(("max_channels=%d\n", max_channels));
+       pipe->constr.list = channels_list;
+       pipe->constr.mask = 0;
+       for (i = 0; channels_list[i] <= max_channels; i++);
+       pipe->constr.count = i;
+       if (pipe->hw.channels_max > max_channels)
+               pipe->hw.channels_max = max_channels;
+       if (chip->digital_mode == DIGITAL_MODE_ADAT) {
+               pipe->hw.rate_max = 48000;
+               pipe->hw.rates &= SNDRV_PCM_RATE_8000_48000;
+       }
+
+       runtime->hw = pipe->hw;
+       runtime->private_data = pipe;
+       runtime->private_free = audiopipe_free;
+       snd_pcm_set_sync(substream);
+
+       /* Only mono and any even number of channels are allowed */
+       if ((err = snd_pcm_hw_constraint_list(runtime, 0,
+                                             SNDRV_PCM_HW_PARAM_CHANNELS,
+                                             &pipe->constr)) < 0)
+               return err;
+
+       /* All periods should have the same size */
+       if ((err = snd_pcm_hw_constraint_integer(runtime,
+                                                SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+               return err;
+
+       /* The hw accesses memory in chunks 32 frames long and they should be
+       32-bytes-aligned. It's not a requirement, but it seems that IRQs are
+       generated with a resolution of 32 frames. Thus we need the following */
+       if ((err = snd_pcm_hw_constraint_step(runtime, 0,
+                                             SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+                                             32)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_constraint_step(runtime, 0,
+                                             SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+                                             32)) < 0)
+               return err;
+
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_RATE,
+                                       hw_rule_sample_rate, chip,
+                                      SNDRV_PCM_HW_PARAM_RATE, -1)) < 0)
+               return err;
+
+       /* Finally allocate a page for the scatter-gather list */
+       if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+                                      snd_dma_pci_data(chip->pci),
+                                      PAGE_SIZE, &pipe->sgpage)) < 0) {
+               DE_HWP(("s-g list allocation failed\n"));
+               return err;
+       }
+
+       return 0;
+}
+
+
+
+static int pcm_analog_in_open(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       int err;
+
+       DE_ACT(("pcm_analog_in_open\n"));
+       if ((err = pcm_open(substream, num_analog_busses_in(chip) -
+                           substream->number)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      hw_rule_capture_channels_by_format, NULL,
+                                      SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_FORMAT,
+                                      hw_rule_capture_format_by_channels, NULL,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0)
+               return err;
+       atomic_inc(&chip->opencount);
+       if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
+               chip->can_set_rate=0;
+       DE_HWP(("pcm_analog_in_open  cs=%d  oc=%d  r=%d\n",
+               chip->can_set_rate, atomic_read(&chip->opencount),
+               chip->sample_rate));
+       return 0;
+}
+
+
+
+static int pcm_analog_out_open(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       int max_channels, err;
+
+#ifdef ECHOCARD_HAS_VMIXER
+       max_channels = num_pipes_out(chip);
+#else
+       max_channels = num_analog_busses_out(chip);
+#endif
+       DE_ACT(("pcm_analog_out_open\n"));
+       if ((err = pcm_open(substream, max_channels - substream->number)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      hw_rule_playback_channels_by_format,
+                                      NULL,
+                                      SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0)
+               return err;
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_FORMAT,
+                                      hw_rule_playback_format_by_channels,
+                                      NULL,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0)
+               return err;
+       atomic_inc(&chip->opencount);
+       if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
+               chip->can_set_rate=0;
+       DE_HWP(("pcm_analog_out_open  cs=%d  oc=%d  r=%d\n",
+               chip->can_set_rate, atomic_read(&chip->opencount),
+               chip->sample_rate));
+       return 0;
+}
+
+
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+
+static int pcm_digital_in_open(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       int err, max_channels;
+
+       DE_ACT(("pcm_digital_in_open\n"));
+       max_channels = num_digital_busses_in(chip) - substream->number;
+       down(&chip->mode_mutex);
+       if (chip->digital_mode == DIGITAL_MODE_ADAT)
+               err = pcm_open(substream, max_channels);
+       else    /* If the card has ADAT, subtract the 6 channels
+                * that S/PDIF doesn't have
+                */
+               err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT);
+
+       if (err < 0)
+               goto din_exit;
+
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      hw_rule_capture_channels_by_format, NULL,
+                                      SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0)
+               goto din_exit;
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_FORMAT,
+                                      hw_rule_capture_format_by_channels, NULL,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0)
+               goto din_exit;
+
+       atomic_inc(&chip->opencount);
+       if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
+               chip->can_set_rate=0;
+
+din_exit:
+       up(&chip->mode_mutex);
+       return err;
+}
+
+
+
+#ifndef ECHOCARD_HAS_VMIXER    /* See the note in snd_echo_new_pcm() */
+
+static int pcm_digital_out_open(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       int err, max_channels;
+
+       DE_ACT(("pcm_digital_out_open\n"));
+       max_channels = num_digital_busses_out(chip) - substream->number;
+       down(&chip->mode_mutex);
+       if (chip->digital_mode == DIGITAL_MODE_ADAT)
+               err = pcm_open(substream, max_channels);
+       else    /* If the card has ADAT, subtract the 6 channels
+                * that S/PDIF doesn't have
+                */
+               err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT);
+
+       if (err < 0)
+               goto dout_exit;
+
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      hw_rule_playback_channels_by_format,
+                                      NULL, SNDRV_PCM_HW_PARAM_FORMAT,
+                                      -1)) < 0)
+               goto dout_exit;
+       if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                      SNDRV_PCM_HW_PARAM_FORMAT,
+                                      hw_rule_playback_format_by_channels,
+                                      NULL, SNDRV_PCM_HW_PARAM_CHANNELS,
+                                      -1)) < 0)
+               goto dout_exit;
+       atomic_inc(&chip->opencount);
+       if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
+               chip->can_set_rate=0;
+dout_exit:
+       up(&chip->mode_mutex);
+       return err;
+}
+
+#endif /* !ECHOCARD_HAS_VMIXER */
+
+#endif /* ECHOCARD_HAS_DIGITAL_IO */
+
+
+
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       int oc;
+
+       /* Nothing to do here. Audio is already off and pipe will be
+        * freed by its callback
+        */
+       DE_ACT(("pcm_close\n"));
+
+       atomic_dec(&chip->opencount);
+       oc = atomic_read(&chip->opencount);
+       DE_ACT(("pcm_close  oc=%d  cs=%d  rs=%d\n", oc,
+               chip->can_set_rate, chip->rate_set));
+       if (oc < 2)
+               chip->can_set_rate = 1;
+       if (oc == 0)
+               chip->rate_set = 0;
+       DE_ACT(("pcm_close2 oc=%d  cs=%d  rs=%d\n", oc,
+               chip->can_set_rate,chip->rate_set));
+
+       return 0;
+}
+
+
+
+/* Channel allocation and scatter-gather list setup */
+static int init_engine(struct snd_pcm_substream *substream,
+                      struct snd_pcm_hw_params *hw_params,
+                      int pipe_index, int interleave)
+{
+       struct echoaudio *chip;
+       int err, per, rest, page, edge, offs;
+       struct snd_sg_buf *sgbuf;
+       struct audiopipe *pipe;
+
+       chip = snd_pcm_substream_chip(substream);
+       pipe = (struct audiopipe *) substream->runtime->private_data;
+
+       /* Sets up che hardware. If it's already initialized, reset and
+        * redo with the new parameters
+        */
+       spin_lock_irq(&chip->lock);
+       if (pipe->index >= 0) {
+               DE_HWP(("hwp_ie free(%d)\n", pipe->index));
+               err = free_pipes(chip, pipe);
+               snd_assert(!err);
+               chip->substream[pipe->index] = NULL;
+       }
+
+       err = allocate_pipes(chip, pipe, pipe_index, interleave);
+       if (err < 0) {
+               spin_unlock_irq(&chip->lock);
+               DE_ACT((KERN_NOTICE "allocate_pipes(%d) err=%d\n",
+                       pipe_index, err));
+               return err;
+       }
+       spin_unlock_irq(&chip->lock);
+       DE_ACT((KERN_NOTICE "allocate_pipes()=%d\n", pipe_index));
+
+       DE_HWP(("pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n",
+               params_buffer_bytes(hw_params), params_periods(hw_params),
+               params_period_bytes(hw_params)));
+       err = snd_pcm_lib_malloc_pages(substream,
+                                      params_buffer_bytes(hw_params));
+       if (err < 0) {
+               snd_printk(KERN_ERR "malloc_pages err=%d\n", err);
+               spin_lock_irq(&chip->lock);
+               free_pipes(chip, pipe);
+               spin_unlock_irq(&chip->lock);
+               pipe->index = -1;
+               return err;
+       }
+
+       sgbuf = snd_pcm_substream_sgbuf(substream);
+
+       DE_HWP(("pcm_hw_params table size=%d pages=%d\n",
+               sgbuf->size, sgbuf->pages));
+       sglist_init(chip, pipe);
+       edge = PAGE_SIZE;
+       for (offs = page = per = 0; offs < params_buffer_bytes(hw_params);
+            per++) {
+               rest = params_period_bytes(hw_params);
+               if (offs + rest > params_buffer_bytes(hw_params))
+                       rest = params_buffer_bytes(hw_params) - offs;
+               while (rest) {
+                       if (rest <= edge - offs) {
+                               sglist_add_mapping(chip, pipe,
+                                                  snd_sgbuf_get_addr(sgbuf, offs),
+                                                  rest);
+                               sglist_add_irq(chip, pipe);
+                               offs += rest;
+                               rest = 0;
+                       } else {
+                               sglist_add_mapping(chip, pipe,
+                                                  snd_sgbuf_get_addr(sgbuf, offs),
+                                                  edge - offs);
+                               rest -= edge - offs;
+                               offs = edge;
+                       }
+                       if (offs == edge) {
+                               edge += PAGE_SIZE;
+                               page++;
+                       }
+               }
+       }
+
+       /* Close the ring buffer */
+       sglist_wrap(chip, pipe);
+
+       /* This stuff is used by the irq handler, so it must be
+        * initialized before chip->substream
+        */
+       chip->last_period[pipe_index] = 0;
+       pipe->last_counter = 0;
+       pipe->position = 0;
+       smp_wmb();
+       chip->substream[pipe_index] = substream;
+       chip->rate_set = 1;
+       spin_lock_irq(&chip->lock);
+       set_sample_rate(chip, hw_params->rate_num / hw_params->rate_den);
+       spin_unlock_irq(&chip->lock);
+       DE_HWP(("pcm_hw_params ok\n"));
+       return 0;
+}
+
+
+
+static int pcm_analog_in_hw_params(struct snd_pcm_substream *substream,
+                                  struct snd_pcm_hw_params *hw_params)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+
+       return init_engine(substream, hw_params, px_analog_in(chip) +
+                       substream->number, params_channels(hw_params));
+}
+
+
+
+static int pcm_analog_out_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *hw_params)
+{
+       return init_engine(substream, hw_params, substream->number,
+                          params_channels(hw_params));
+}
+
+
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+
+static int pcm_digital_in_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *hw_params)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+
+       return init_engine(substream, hw_params, px_digital_in(chip) +
+                       substream->number, params_channels(hw_params));
+}
+
+
+
+#ifndef ECHOCARD_HAS_VMIXER    /* See the note in snd_echo_new_pcm() */
+static int pcm_digital_out_hw_params(struct snd_pcm_substream *substream,
+                                    struct snd_pcm_hw_params *hw_params)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+
+       return init_engine(substream, hw_params, px_digital_out(chip) +
+                       substream->number, params_channels(hw_params));
+}
+#endif /* !ECHOCARD_HAS_VMIXER */
+
+#endif /* ECHOCARD_HAS_DIGITAL_IO */
+
+
+
+static int pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip;
+       struct audiopipe *pipe;
+
+       chip = snd_pcm_substream_chip(substream);
+       pipe = (struct audiopipe *) substream->runtime->private_data;
+
+       spin_lock_irq(&chip->lock);
+       if (pipe->index >= 0) {
+               DE_HWP(("pcm_hw_free(%d)\n", pipe->index));
+               free_pipes(chip, pipe);
+               chip->substream[pipe->index] = NULL;
+               pipe->index = -1;
+       }
+       spin_unlock_irq(&chip->lock);
+
+       DE_HWP(("pcm_hw_freed\n"));
+       snd_pcm_lib_free_pages(substream);
+       return 0;
+}
+
+
+
+static int pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct audioformat format;
+       int pipe_index = ((struct audiopipe *)runtime->private_data)->index;
+
+       DE_HWP(("Prepare rate=%d format=%d channels=%d\n",
+               runtime->rate, runtime->format, runtime->channels));
+       format.interleave = runtime->channels;
+       format.data_are_bigendian = 0;
+       format.mono_to_stereo = 0;
+       switch (runtime->format) {
+       case SNDRV_PCM_FORMAT_U8:
+               format.bits_per_sample = 8;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               format.bits_per_sample = 16;
+               break;
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               format.bits_per_sample = 24;
+               break;
+       case SNDRV_PCM_FORMAT_S32_BE:
+               format.data_are_bigendian = 1;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               format.bits_per_sample = 32;
+               break;
+       default:
+               DE_HWP(("Prepare error: unsupported format %d\n",
+                       runtime->format));
+               return -EINVAL;
+       }
+
+       snd_assert(pipe_index < px_num(chip), return -EINVAL);
+       snd_assert(is_pipe_allocated(chip, pipe_index), return -EINVAL);
+       set_audio_format(chip, pipe_index, &format);
+       return 0;
+}
+
+
+
+static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct echoaudio *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct audiopipe *pipe = runtime->private_data;
+       int i, err;
+       u32 channelmask = 0;
+       struct list_head *pos;
+       struct snd_pcm_substream *s;
+
+       snd_pcm_group_for_each(pos, substream) {
+               s = snd_pcm_group_substream_entry(pos);
+               for (i = 0; i < DSP_MAXPIPES; i++) {
+                       if (s == chip->substream[i]) {
+                               channelmask |= 1 << i;
+                               snd_pcm_trigger_done(s, substream);
+                       }
+               }
+       }
+
+       spin_lock(&chip->lock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               DE_ACT(("pcm_trigger start\n"));
+               for (i = 0; i < DSP_MAXPIPES; i++) {
+                       if (channelmask & (1 << i)) {
+                               pipe = chip->substream[i]->runtime->private_data;
+                               switch (pipe->state) {
+                               case PIPE_STATE_STOPPED:
+                                       chip->last_period[i] = 0;
+                                       pipe->last_counter = 0;
+                                       pipe->position = 0;
+                                       *pipe->dma_counter = 0;
+                               case PIPE_STATE_PAUSED:
+                                       pipe->state = PIPE_STATE_STARTED;
+                                       break;
+                               case PIPE_STATE_STARTED:
+                                       break;
+                               }
+                       }
+               }
+               err = start_transport(chip, channelmask,
+                                     chip->pipe_cyclic_mask);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               DE_ACT(("pcm_trigger stop\n"));
+               for (i = 0; i < DSP_MAXPIPES; i++) {
+                       if (channelmask & (1 << i)) {
+                               pipe = chip->substream[i]->runtime->private_data;
+                               pipe->state = PIPE_STATE_STOPPED;
+                       }
+               }
+               err = stop_transport(chip, channelmask);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               DE_ACT(("pcm_trigger pause\n"));
+               for (i = 0; i < DSP_MAXPIPES; i++) {
+                       if (channelmask & (1 << i)) {
+                               pipe = chip->substream[i]->runtime->private_data;
+                               pipe->state = PIPE_STATE_PAUSED;
+                       }
+               }
+               err = pause_transport(chip, channelmask);
+               break;
+       default:
+               err = -EINVAL;
+       }
+       spin_unlock(&chip->lock);
+       return err;
+}
+
+
+
+static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct audiopipe *pipe = runtime->private_data;
+       size_t cnt, bufsize, pos;
+
+       cnt = le32_to_cpu(*pipe->dma_counter);
+       pipe->position += cnt - pipe->last_counter;
+       pipe->last_counter = cnt;
+       bufsize = substream->runtime->buffer_size;
+       pos = bytes_to_frames(substream->runtime, pipe->position);
+
+       while (pos >= bufsize) {
+               pipe->position -= frames_to_bytes(substream->runtime, bufsize);
+               pos -= bufsize;
+       }
+       return pos;
+}
+
+
+
+/* pcm *_ops structures */
+static struct snd_pcm_ops analog_playback_ops = {
+       .open = pcm_analog_out_open,
+       .close = pcm_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = pcm_analog_out_hw_params,
+       .hw_free = pcm_hw_free,
+       .prepare = pcm_prepare,
+       .trigger = pcm_trigger,
+       .pointer = pcm_pointer,
+       .page = snd_pcm_sgbuf_ops_page,
+};
+static struct snd_pcm_ops analog_capture_ops = {
+       .open = pcm_analog_in_open,
+       .close = pcm_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = pcm_analog_in_hw_params,
+       .hw_free = pcm_hw_free,
+       .prepare = pcm_prepare,
+       .trigger = pcm_trigger,
+       .pointer = pcm_pointer,
+       .page = snd_pcm_sgbuf_ops_page,
+};
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+#ifndef ECHOCARD_HAS_VMIXER
+static struct snd_pcm_ops digital_playback_ops = {
+       .open = pcm_digital_out_open,
+       .close = pcm_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = pcm_digital_out_hw_params,
+       .hw_free = pcm_hw_free,
+       .prepare = pcm_prepare,
+       .trigger = pcm_trigger,
+       .pointer = pcm_pointer,
+       .page = snd_pcm_sgbuf_ops_page,
+};
+#endif /* !ECHOCARD_HAS_VMIXER */
+static struct snd_pcm_ops digital_capture_ops = {
+       .open = pcm_digital_in_open,
+       .close = pcm_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = pcm_digital_in_hw_params,
+       .hw_free = pcm_hw_free,
+       .prepare = pcm_prepare,
+       .trigger = pcm_trigger,
+       .pointer = pcm_pointer,
+       .page = snd_pcm_sgbuf_ops_page,
+};
+#endif /* ECHOCARD_HAS_DIGITAL_IO */
+
+
+
+/* Preallocate memory only for the first substream because it's the most
+ * used one
+ */
+static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
+{
+       struct snd_pcm_substream *ss;
+       int stream, err;
+
+       for (stream = 0; stream < 2; stream++)
+               for (ss = pcm->streams[stream].substream; ss; ss = ss->next) {
+                       err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG,
+                                                           dev,
+                                                           ss->number ? 0 : 128<<10,
+                                                           256<<10);
+                       if (err < 0)
+                               return err;
+               }
+       return 0;
+}
+
+
+
+/*<--snd_echo_probe() */
+static int __devinit snd_echo_new_pcm(struct echoaudio *chip)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+#ifdef ECHOCARD_HAS_VMIXER
+       /* This card has a Vmixer, that is there is no direct mapping from PCM
+       streams to physical outputs. The user can mix the streams as he wishes
+       via control interface and it's possible to send any stream to any
+       output, thus it makes no sense to keep analog and digital outputs
+       separated */
+
+       /* PCM#0 Virtual outputs and analog inputs */
+       if ((err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip),
+                               num_analog_busses_in(chip), &pcm)) < 0)
+               return err;
+       pcm->private_data = chip;
+       chip->analog_pcm = pcm;
+       strcpy(pcm->name, chip->card->shortname);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops);
+       if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
+               return err;
+       DE_INIT(("Analog PCM ok\n"));
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+       /* PCM#1 Digital inputs, no outputs */
+       if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, 0,
+                              num_digital_busses_in(chip), &pcm)) < 0)
+               return err;
+       pcm->private_data = chip;
+       chip->digital_pcm = pcm;
+       strcpy(pcm->name, chip->card->shortname);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops);
+       if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
+               return err;
+       DE_INIT(("Digital PCM ok\n"));
+#endif /* ECHOCARD_HAS_DIGITAL_IO */
+
+#else /* ECHOCARD_HAS_VMIXER */
+
+       /* The card can manage substreams formed by analog and digital channels
+       at the same time, but I prefer to keep analog and digital channels
+       separated, because that mixed thing is confusing and useless. So we
+       register two PCM devices: */
+
+       /* PCM#0 Analog i/o */
+       if ((err = snd_pcm_new(chip->card, "Analog PCM", 0,
+                              num_analog_busses_out(chip),
+                              num_analog_busses_in(chip), &pcm)) < 0)
+               return err;
+       pcm->private_data = chip;
+       chip->analog_pcm = pcm;
+       strcpy(pcm->name, chip->card->shortname);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops);
+       if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
+               return err;
+       DE_INIT(("Analog PCM ok\n"));
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+       /* PCM#1 Digital i/o */
+       if ((err = snd_pcm_new(chip->card, "Digital PCM", 1,
+                              num_digital_busses_out(chip),
+                              num_digital_busses_in(chip), &pcm)) < 0)
+               return err;
+       pcm->private_data = chip;
+       chip->digital_pcm = pcm;
+       strcpy(pcm->name, chip->card->shortname);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops);
+       if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
+               return err;
+       DE_INIT(("Digital PCM ok\n"));
+#endif /* ECHOCARD_HAS_DIGITAL_IO */
+
+#endif /* ECHOCARD_HAS_VMIXER */
+
+       return 0;
+}
+
+
+
+
+/******************************************************************************
+       Control interface
+******************************************************************************/
+
+/******************* PCM output volume *******************/
+static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = num_busses_out(chip);
+       uinfo->value.integer.min = ECHOGAIN_MINOUT;
+       uinfo->value.integer.max = ECHOGAIN_MAXOUT;
+       return 0;
+}
+
+static int snd_echo_output_gain_get(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       for (c = 0; c < num_busses_out(chip); c++)
+               ucontrol->value.integer.value[c] = chip->output_gain[c];
+       return 0;
+}
+
+static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c, changed, gain;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       spin_lock_irq(&chip->lock);
+       for (c = 0; c < num_busses_out(chip); c++) {
+               gain = ucontrol->value.integer.value[c];
+               /* Ignore out of range values */
+               if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT)
+                       continue;
+               if (chip->output_gain[c] != gain) {
+                       set_output_gain(chip, c, gain);
+                       changed = 1;
+               }
+       }
+       if (changed)
+               update_output_line_level(chip);
+       spin_unlock_irq(&chip->lock);
+       return changed;
+}
+
+#ifdef ECHOCARD_HAS_VMIXER
+/* On Vmixer cards this one controls the line-out volume */
+static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
+       .name = "Line Playback Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_output_gain_info,
+       .get = snd_echo_output_gain_get,
+       .put = snd_echo_output_gain_put,
+};
+#else
+static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
+       .name = "PCM Playback Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_output_gain_info,
+       .get = snd_echo_output_gain_get,
+       .put = snd_echo_output_gain_put,
+};
+#endif
+
+
+
+#ifdef ECHOCARD_HAS_INPUT_GAIN
+
+/******************* Analog input volume *******************/
+static int snd_echo_input_gain_info(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = num_analog_busses_in(chip);
+       uinfo->value.integer.min = ECHOGAIN_MININP;
+       uinfo->value.integer.max = ECHOGAIN_MAXINP;
+       return 0;
+}
+
+static int snd_echo_input_gain_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       for (c = 0; c < num_analog_busses_in(chip); c++)
+               ucontrol->value.integer.value[c] = chip->input_gain[c];
+       return 0;
+}
+
+static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c, gain, changed;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       spin_lock_irq(&chip->lock);
+       for (c = 0; c < num_analog_busses_in(chip); c++) {
+               gain = ucontrol->value.integer.value[c];
+               /* Ignore out of range values */
+               if (gain < ECHOGAIN_MININP || gain > ECHOGAIN_MAXINP)
+                       continue;
+               if (chip->input_gain[c] != gain) {
+                       set_input_gain(chip, c, gain);
+                       changed = 1;
+               }
+       }
+       if (changed)
+               update_input_line_level(chip);
+       spin_unlock_irq(&chip->lock);
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
+       .name = "Line Capture Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_input_gain_info,
+       .get = snd_echo_input_gain_get,
+       .put = snd_echo_input_gain_put,
+};
+
+#endif /* ECHOCARD_HAS_INPUT_GAIN */
+
+
+
+#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+
+/************ Analog output nominal level (+4dBu / -10dBV) ***************/
+static int snd_echo_output_nominal_info (struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = num_analog_busses_out(chip);
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_echo_output_nominal_get(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       for (c = 0; c < num_analog_busses_out(chip); c++)
+               ucontrol->value.integer.value[c] = chip->nominal_level[c];
+       return 0;
+}
+
+static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c, changed;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       spin_lock_irq(&chip->lock);
+       for (c = 0; c < num_analog_busses_out(chip); c++) {
+               if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) {
+                       set_nominal_level(chip, c,
+                                         ucontrol->value.integer.value[c]);
+                       changed = 1;
+               }
+       }
+       if (changed)
+               update_output_line_level(chip);
+       spin_unlock_irq(&chip->lock);
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = {
+       .name = "Line Playback Switch (-10dBV)",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_output_nominal_info,
+       .get = snd_echo_output_nominal_get,
+       .put = snd_echo_output_nominal_put,
+};
+
+#endif /* ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL */
+
+
+
+#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+
+/*************** Analog input nominal level (+4dBu / -10dBV) ***************/
+static int snd_echo_input_nominal_info(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = num_analog_busses_in(chip);
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_echo_input_nominal_get(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       for (c = 0; c < num_analog_busses_in(chip); c++)
+               ucontrol->value.integer.value[c] =
+                       chip->nominal_level[bx_analog_in(chip) + c];
+       return 0;
+}
+
+static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int c, changed;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       spin_lock_irq(&chip->lock);
+       for (c = 0; c < num_analog_busses_in(chip); c++) {
+               if (chip->nominal_level[bx_analog_in(chip) + c] !=
+                   ucontrol->value.integer.value[c]) {
+                       set_nominal_level(chip, bx_analog_in(chip) + c,
+                                         ucontrol->value.integer.value[c]);
+                       changed = 1;
+               }
+       }
+       if (changed)
+               update_output_line_level(chip); /* "Output" is not a mistake
+                                                * here.
+                                                */
+       spin_unlock_irq(&chip->lock);
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = {
+       .name = "Line Capture Switch (-10dBV)",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_input_nominal_info,
+       .get = snd_echo_input_nominal_get,
+       .put = snd_echo_input_nominal_put,
+};
+
+#endif /* ECHOCARD_HAS_INPUT_NOMINAL_LEVEL */
+
+
+
+#ifdef ECHOCARD_HAS_MONITOR
+
+/******************* Monitor mixer *******************/
+static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = ECHOGAIN_MINOUT;
+       uinfo->value.integer.max = ECHOGAIN_MAXOUT;
+       uinfo->dimen.d[0] = num_busses_out(chip);
+       uinfo->dimen.d[1] = num_busses_in(chip);
+       return 0;
+}
+
+static int snd_echo_mixer_get(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] =
+               chip->monitor_gain[ucontrol->id.index / num_busses_in(chip)]
+                       [ucontrol->id.index % num_busses_in(chip)];
+       return 0;
+}
+
+static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int changed,  gain;
+       short out, in;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       out = ucontrol->id.index / num_busses_in(chip);
+       in = ucontrol->id.index % num_busses_in(chip);
+       gain = ucontrol->value.integer.value[0];
+       if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT)
+               return -EINVAL;
+       if (chip->monitor_gain[out][in] != gain) {
+               spin_lock_irq(&chip->lock);
+               set_monitor_gain(chip, out, in, gain);
+               update_output_line_level(chip);
+               spin_unlock_irq(&chip->lock);
+               changed = 1;
+       }
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
+       .name = "Monitor Mixer Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_mixer_info,
+       .get = snd_echo_mixer_get,
+       .put = snd_echo_mixer_put,
+};
+
+#endif /* ECHOCARD_HAS_MONITOR */
+
+
+
+#ifdef ECHOCARD_HAS_VMIXER
+
+/******************* Vmixer *******************/
+static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = ECHOGAIN_MINOUT;
+       uinfo->value.integer.max = ECHOGAIN_MAXOUT;
+       uinfo->dimen.d[0] = num_busses_out(chip);
+       uinfo->dimen.d[1] = num_pipes_out(chip);
+       return 0;
+}
+
+static int snd_echo_vmixer_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] =
+               chip->vmixer_gain[ucontrol->id.index / num_pipes_out(chip)]
+                       [ucontrol->id.index % num_pipes_out(chip)];
+       return 0;
+}
+
+static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int gain, changed;
+       short vch, out;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       out = ucontrol->id.index / num_pipes_out(chip);
+       vch = ucontrol->id.index % num_pipes_out(chip);
+       gain = ucontrol->value.integer.value[0];
+       if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT)
+               return -EINVAL;
+       if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) {
+               spin_lock_irq(&chip->lock);
+               set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]);
+               update_vmixer_level(chip);
+               spin_unlock_irq(&chip->lock);
+               changed = 1;
+       }
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
+       .name = "VMixer Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .info = snd_echo_vmixer_info,
+       .get = snd_echo_vmixer_get,
+       .put = snd_echo_vmixer_put,
+};
+
+#endif /* ECHOCARD_HAS_VMIXER */
+
+
+
+#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+
+/******************* Digital mode switch *******************/
+static int snd_echo_digital_mode_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       static char *names[4] = {
+               "S/PDIF Coaxial", "S/PDIF Optical", "ADAT Optical",
+               "S/PDIF Cdrom"
+       };
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->value.enumerated.items = chip->num_digital_modes;
+       uinfo->count = 1;
+       if (uinfo->value.enumerated.item >= chip->num_digital_modes)
+               uinfo->value.enumerated.item = chip->num_digital_modes - 1;
+       strcpy(uinfo->value.enumerated.name, names[
+                       chip->digital_mode_list[uinfo->value.enumerated.item]]);
+       return 0;
+}
+
+static int snd_echo_digital_mode_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int i, mode;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       mode = chip->digital_mode;
+       for (i = chip->num_digital_modes - 1; i >= 0; i--)
+               if (mode == chip->digital_mode_list[i]) {
+                       ucontrol->value.enumerated.item[0] = i;
+                       break;
+               }
+       return 0;
+}
+
+static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int changed;
+       unsigned short emode, dmode;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+
+       emode = ucontrol->value.enumerated.item[0];
+       if (emode >= chip->num_digital_modes)
+               return -EINVAL;
+       dmode = chip->digital_mode_list[emode];
+
+       if (dmode != chip->digital_mode) {
+               /* mode_mutex is required to make this operation atomic wrt
+               pcm_digital_*_open() and set_input_clock() functions. */
+               down(&chip->mode_mutex);
+
+               /* Do not allow the user to change the digital mode when a pcm
+               device is open because it also changes the number of channels
+               and the allowed sample rates */
+               if (atomic_read(&chip->opencount)) {
+                       changed = -EAGAIN;
+               } else {
+                       changed = set_digital_mode(chip, dmode);
+                       /* If we had to change the clock source, report it */
+                       if (changed > 0 && chip->clock_src_ctl) {
+                               snd_ctl_notify(chip->card,
+                                              SNDRV_CTL_EVENT_MASK_VALUE,
+                                              &chip->clock_src_ctl->id);
+                               DE_ACT(("SDM() =%d\n", changed));
+                       }
+                       if (changed >= 0)
+                               changed = 1;    /* No errors */
+               }
+               up(&chip->mode_mutex);
+       }
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = {
+       .name = "Digital mode Switch",
+       .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+       .info = snd_echo_digital_mode_info,
+       .get = snd_echo_digital_mode_get,
+       .put = snd_echo_digital_mode_put,
+};
+
+#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
+
+
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+
+/******************* S/PDIF mode switch *******************/
+static int snd_echo_spdif_mode_info(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_info *uinfo)
+{
+       static char *names[2] = {"Consumer", "Professional"};
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->value.enumerated.items = 2;
+       uinfo->count = 1;
+       if (uinfo->value.enumerated.item)
+               uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name,
+              names[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int snd_echo_spdif_mode_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.enumerated.item[0] = !!chip->professional_spdif;
+       return 0;
+}
+
+static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int mode;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       mode = !!ucontrol->value.enumerated.item[0];
+       if (mode != chip->professional_spdif) {
+               spin_lock_irq(&chip->lock);
+               set_professional_spdif(chip, mode);
+               spin_unlock_irq(&chip->lock);
+               return 1;
+       }
+       return 0;
+}
+
+static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = {
+       .name = "S/PDIF mode Switch",
+       .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+       .info = snd_echo_spdif_mode_info,
+       .get = snd_echo_spdif_mode_get,
+       .put = snd_echo_spdif_mode_put,
+};
+
+#endif /* ECHOCARD_HAS_DIGITAL_IO */
+
+
+
+#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
+
+/******************* Select input clock source *******************/
+static int snd_echo_clock_source_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       static char *names[8] = {
+               "Internal", "Word", "Super", "S/PDIF", "ADAT", "ESync",
+               "ESync96", "MTC"
+       };
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->value.enumerated.items = chip->num_clock_sources;
+       uinfo->count = 1;
+       if (uinfo->value.enumerated.item >= chip->num_clock_sources)
+               uinfo->value.enumerated.item = chip->num_clock_sources - 1;
+       strcpy(uinfo->value.enumerated.name, names[
+                       chip->clock_source_list[uinfo->value.enumerated.item]]);
+       return 0;
+}
+
+static int snd_echo_clock_source_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int i, clock;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       clock = chip->input_clock;
+
+       for (i = 0; i < chip->num_clock_sources; i++)
+               if (clock == chip->clock_source_list[i])
+                       ucontrol->value.enumerated.item[0] = i;
+
+       return 0;
+}
+
+static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int changed;
+       unsigned int eclock, dclock;
+
+       changed = 0;
+       chip = snd_kcontrol_chip(kcontrol);
+       eclock = ucontrol->value.enumerated.item[0];
+       if (eclock >= chip->input_clock_types)
+               return -EINVAL;
+       dclock = chip->clock_source_list[eclock];
+       if (chip->input_clock != dclock) {
+               down(&chip->mode_mutex);
+               spin_lock_irq(&chip->lock);
+               if ((changed = set_input_clock(chip, dclock)) == 0)
+                       changed = 1;    /* no errors */
+               spin_unlock_irq(&chip->lock);
+               up(&chip->mode_mutex);
+       }
+
+       if (changed < 0)
+               DE_ACT(("seticlk val%d err 0x%x\n", dclock, changed));
+
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = {
+       .name = "Sample Clock Source",
+       .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+       .info = snd_echo_clock_source_info,
+       .get = snd_echo_clock_source_get,
+       .put = snd_echo_clock_source_put,
+};
+
+#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
+
+
+
+#ifdef ECHOCARD_HAS_PHANTOM_POWER
+
+/******************* Phantom power switch *******************/
+static int snd_echo_phantom_power_info(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = chip->phantom_power;
+       return 0;
+}
+
+static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
+       int power, changed = 0;
+
+       power = !!ucontrol->value.integer.value[0];
+       if (chip->phantom_power != power) {
+               spin_lock_irq(&chip->lock);
+               changed = set_phantom_power(chip, power);
+               spin_unlock_irq(&chip->lock);
+               if (changed == 0)
+                       changed = 1;    /* no errors */
+       }
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = {
+       .name = "Phantom power Switch",
+       .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+       .info = snd_echo_phantom_power_info,
+       .get = snd_echo_phantom_power_get,
+       .put = snd_echo_phantom_power_put,
+};
+
+#endif /* ECHOCARD_HAS_PHANTOM_POWER */
+
+
+
+#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
+
+/******************* Digital input automute switch *******************/
+static int snd_echo_automute_info(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_echo_automute_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = chip->digital_in_automute;
+       return 0;
+}
+
+static int snd_echo_automute_put(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
+       int automute, changed = 0;
+
+       automute = !!ucontrol->value.integer.value[0];
+       if (chip->digital_in_automute != automute) {
+               spin_lock_irq(&chip->lock);
+               changed = set_input_auto_mute(chip, automute);
+               spin_unlock_irq(&chip->lock);
+               if (changed == 0)
+                       changed = 1;    /* no errors */
+       }
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = {
+       .name = "Digital Capture Switch (automute)",
+       .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+       .info = snd_echo_automute_info,
+       .get = snd_echo_automute_get,
+       .put = snd_echo_automute_put,
+};
+
+#endif /* ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE */
+
+
+
+/******************* VU-meters switch *******************/
+static int snd_echo_vumeters_switch_info(struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       spin_lock_irq(&chip->lock);
+       set_meters_on(chip, ucontrol->value.integer.value[0]);
+       spin_unlock_irq(&chip->lock);
+       return 1;
+}
+
+static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = {
+       .name = "VU-meters Switch",
+       .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+       .access = SNDRV_CTL_ELEM_ACCESS_WRITE,
+       .info = snd_echo_vumeters_switch_info,
+       .put = snd_echo_vumeters_switch_put,
+};
+
+
+
+/***** Read VU-meters (input, output, analog and digital together) *****/
+static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 96;
+       uinfo->value.integer.min = ECHOGAIN_MINOUT;
+       uinfo->value.integer.max = 0;
+#ifdef ECHOCARD_HAS_VMIXER
+       uinfo->dimen.d[0] = 3;  /* Out, In, Virt */
+#else
+       uinfo->dimen.d[0] = 2;  /* Out, In */
+#endif
+       uinfo->dimen.d[1] = 16; /* 16 channels */
+       uinfo->dimen.d[2] = 2;  /* 0=level, 1=peak */
+       return 0;
+}
+
+static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       get_audio_meters(chip, ucontrol->value.integer.value);
+       return 0;
+}
+
+static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
+       .name = "VU-meters",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+       .info = snd_echo_vumeters_info,
+       .get = snd_echo_vumeters_get,
+};
+
+
+
+/*** Channels info - it exports informations about the number of channels ***/
+static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       struct echoaudio *chip;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 6;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1 << ECHO_CLOCK_NUMBER;
+       return 0;
+}
+
+static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct echoaudio *chip;
+       int detected, clocks, bit, src;
+
+       chip = snd_kcontrol_chip(kcontrol);
+       ucontrol->value.integer.value[0] = num_busses_in(chip);
+       ucontrol->value.integer.value[1] = num_analog_busses_in(chip);
+       ucontrol->value.integer.value[2] = num_busses_out(chip);
+       ucontrol->value.integer.value[3] = num_analog_busses_out(chip);
+       ucontrol->value.integer.value[4] = num_pipes_out(chip);
+
+       /* Compute the bitmask of the currently valid input clocks */
+       detected = detect_input_clocks(chip);
+       clocks = 0;
+       src = chip->num_clock_sources - 1;
+       for (bit = ECHO_CLOCK_NUMBER - 1; bit >= 0; bit--)
+               if (detected & (1 << bit))
+                       for (; src >= 0; src--)
+                               if (bit == chip->clock_source_list[src]) {
+                                       clocks |= 1 << src;
+                                       break;
+                               }
+       ucontrol->value.integer.value[5] = clocks;
+
+       return 0;
+}
+
+static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = {
+       .name = "Channels info",
+       .iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+       .info = snd_echo_channels_info_info,
+       .get = snd_echo_channels_info_get,
+};
+
+
+
+
+/******************************************************************************
+       IRQ Handler
+******************************************************************************/
+
+static irqreturn_t snd_echo_interrupt(int irq, void *dev_id,
+                                     struct pt_regs *regs)
+{
+       struct echoaudio *chip = dev_id;
+       struct snd_pcm_substream *substream;
+       int period, ss, st;
+
+       spin_lock(&chip->lock);
+       st = service_irq(chip);
+       if (st < 0) {
+               spin_unlock(&chip->lock);
+               return IRQ_NONE;
+       }
+       /* The hardware doesn't tell us which substream caused the irq,
+       thus we have to check all running substreams. */
+       for (ss = 0; ss < DSP_MAXPIPES; ss++) {
+               if ((substream = chip->substream[ss])) {
+                       period = pcm_pointer(substream) /
+                               substream->runtime->period_size;
+                       if (period != chip->last_period[ss]) {
+                               chip->last_period[ss] = period;
+                               spin_unlock(&chip->lock);
+                               snd_pcm_period_elapsed(substream);
+                               spin_lock(&chip->lock);
+                       }
+               }
+       }
+       spin_unlock(&chip->lock);
+
+#ifdef ECHOCARD_HAS_MIDI
+       if (st > 0 && chip->midi_in) {
+               snd_rawmidi_receive(chip->midi_in, chip->midi_buffer, st);
+               DE_MID(("rawmidi_iread=%d\n", st));
+       }
+#endif
+       return IRQ_HANDLED;
+}
+
+
+
+
+/******************************************************************************
+       Module construction / destruction
+******************************************************************************/
+
+static int snd_echo_free(struct echoaudio *chip)
+{
+       DE_INIT(("Stop DSP...\n"));
+       if (chip->comm_page) {
+               rest_in_peace(chip);
+               snd_dma_free_pages(&chip->commpage_dma_buf);
+       }
+       DE_INIT(("Stopped.\n"));
+
+       if (chip->irq >= 0)
+               free_irq(chip->irq, (void *)chip);
+
+       if (chip->dsp_registers)
+               iounmap(chip->dsp_registers);
+
+       if (chip->iores)
+               release_and_free_resource(chip->iores);
+
+       DE_INIT(("MMIO freed.\n"));
+
+       pci_disable_device(chip->pci);
+
+       /* release chip data */
+       kfree(chip);
+       DE_INIT(("Chip freed.\n"));
+       return 0;
+}
+
+
+
+static int snd_echo_dev_free(struct snd_device *device)
+{
+       struct echoaudio *chip = device->device_data;
+
+       DE_INIT(("snd_echo_dev_free()...\n"));
+       return snd_echo_free(chip);
+}
+
+
+
+/* <--snd_echo_probe() */
+static __devinit int snd_echo_create(struct snd_card *card,
+                                    struct pci_dev *pci,
+                                    struct echoaudio **rchip)
+{
+       struct echoaudio *chip;
+       int err;
+       size_t sz;
+       static struct snd_device_ops ops = {
+               .dev_free = snd_echo_dev_free,
+       };
+
+       *rchip = NULL;
+
+       pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0);
+
+       if ((err = pci_enable_device(pci)) < 0)
+               return err;
+       pci_set_master(pci);
+
+       /* allocate a chip-specific data */
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       if (!chip) {
+               pci_disable_device(pci);
+               return -ENOMEM;
+       }
+       DE_INIT(("chip=%p\n", chip));
+
+       spin_lock_init(&chip->lock);
+       chip->card = card;
+       chip->pci = pci;
+       chip->irq = -1;
+
+       /* PCI resource allocation */
+       chip->dsp_registers_phys = pci_resource_start(pci, 0);
+       sz = pci_resource_len(pci, 0);
+       if (sz > PAGE_SIZE)
+               sz = PAGE_SIZE;         /* We map only the required part */
+
+       if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz,
+                                             ECHOCARD_NAME)) == NULL) {
+               snd_echo_free(chip);
+               snd_printk(KERN_ERR "cannot get memory region\n");
+               return -EBUSY;
+       }
+       chip->dsp_registers = (volatile u32 __iomem *)
+               ioremap_nocache(chip->dsp_registers_phys, sz);
+
+       if (request_irq(pci->irq, snd_echo_interrupt, IRQF_DISABLED | IRQF_SHARED,
+                                               ECHOCARD_NAME, (void *)chip)) {
+               snd_echo_free(chip);
+               snd_printk(KERN_ERR "cannot grab irq\n");
+               return -EBUSY;
+       }
+       chip->irq = pci->irq;
+       DE_INIT(("pci=%p irq=%d subdev=%04x Init hardware...\n",
+                chip->pci, chip->irq, chip->pci->subsystem_device));
+
+       /* Create the DSP comm page - this is the area of memory used for most
+       of the communication with the DSP, which accesses it via bus mastering */
+       if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+                               sizeof(struct comm_page),
+                               &chip->commpage_dma_buf) < 0) {
+               snd_echo_free(chip);
+               snd_printk(KERN_ERR "cannot allocate the comm page\n");
+               return -ENOMEM;
+       }
+       chip->comm_page_phys = chip->commpage_dma_buf.addr;
+       chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
+
+       err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
+       if (err) {
+               DE_INIT(("init_hw err=%d\n", err));
+               snd_echo_free(chip);
+               return err;
+       }
+       DE_INIT(("Card init OK\n"));
+
+       if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+               snd_echo_free(chip);
+               return err;
+       }
+       atomic_set(&chip->opencount, 0);
+       init_MUTEX(&chip->mode_mutex);
+       chip->can_set_rate = 1;
+       *rchip = chip;
+       /* Init done ! */
+       return 0;
+}
+
+
+
+/* constructor */
+static int __devinit snd_echo_probe(struct pci_dev *pci,
+                                   const struct pci_device_id *pci_id)
+{
+       static int dev;
+       struct snd_card *card;
+       struct echoaudio *chip;
+       char *dsp;
+       int i, err;
+
+       if (dev >= SNDRV_CARDS)
+               return -ENODEV;
+       if (!enable[dev]) {
+               dev++;
+               return -ENOENT;
+       }
+
+       DE_INIT(("Echoaudio driver starting...\n"));
+       i = 0;
+       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+       if (card == NULL)
+               return -ENOMEM;
+
+       if ((err = snd_echo_create(card, pci, &chip)) < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       strcpy(card->driver, "Echo_" ECHOCARD_NAME);
+       strcpy(card->shortname, chip->card_name);
+
+       dsp = "56301";
+       if (pci_id->device == 0x3410)
+               dsp = "56361";
+
+       sprintf(card->longname, "%s rev.%d (DSP%s) at 0x%lx irq %i",
+               card->shortname, pci_id->subdevice & 0x000f, dsp,
+               chip->dsp_registers_phys, chip->irq);
+
+       if ((err = snd_echo_new_pcm(chip)) < 0) {
+               snd_printk(KERN_ERR "new pcm error %d\n", err);
+               snd_card_free(card);
+               return err;
+       }
+
+#ifdef ECHOCARD_HAS_MIDI
+       if (chip->has_midi) {   /* Some Mia's do not have midi */
+               if ((err = snd_echo_midi_create(card, chip)) < 0) {
+                       snd_printk(KERN_ERR "new midi error %d\n", err);
+                       snd_card_free(card);
+                       return err;
+               }
+       }
+#endif
+
+#ifdef ECHOCARD_HAS_VMIXER
+       snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_output_gain, chip))) < 0)
+               goto ctl_error;
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0)
+               goto ctl_error;
+#else
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_pcm_output_gain, chip))) < 0)
+               goto ctl_error;
+#endif
+
+#ifdef ECHOCARD_HAS_INPUT_GAIN
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0)
+               goto ctl_error;
+#endif
+
+#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+       if (!chip->hasnt_input_nominal_level)
+               if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip))) < 0)
+                       goto ctl_error;
+#endif
+
+#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip))) < 0)
+               goto ctl_error;
+#endif
+
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip))) < 0)
+               goto ctl_error;
+
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip))) < 0)
+               goto ctl_error;
+
+#ifdef ECHOCARD_HAS_MONITOR
+       snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip);
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip))) < 0)
+               goto ctl_error;
+#endif
+
+#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip))) < 0)
+               goto ctl_error;
+#endif
+
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip))) < 0)
+               goto ctl_error;
+
+#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+       /* Creates a list of available digital modes */
+       chip->num_digital_modes = 0;
+       for (i = 0; i < 6; i++)
+               if (chip->digital_modes & (1 << i))
+                       chip->digital_mode_list[chip->num_digital_modes++] = i;
+
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip))) < 0)
+               goto ctl_error;
+#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
+
+#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
+       /* Creates a list of available clock sources */
+       chip->num_clock_sources = 0;
+       for (i = 0; i < 10; i++)
+               if (chip->input_clock_types & (1 << i))
+                       chip->clock_source_list[chip->num_clock_sources++] = i;
+
+       if (chip->num_clock_sources > 1) {
+               chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip);
+               if ((err = snd_ctl_add(chip->card, chip->clock_src_ctl)) < 0)
+                       goto ctl_error;
+       }
+#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip))) < 0)
+               goto ctl_error;
+#endif
+
+#ifdef ECHOCARD_HAS_PHANTOM_POWER
+       if (chip->has_phantom_power)
+               if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip))) < 0)
+                       goto ctl_error;
+#endif
+
+       if ((err = snd_card_register(card)) < 0) {
+               snd_card_free(card);
+               goto ctl_error;
+       }
+       snd_printk(KERN_INFO "Card registered: %s\n", card->longname);
+
+       pci_set_drvdata(pci, chip);
+       dev++;
+       return 0;
+
+ctl_error:
+       snd_printk(KERN_ERR "new control error %d\n", err);
+       snd_card_free(card);
+       return err;
+}
+
+
+
+static void __devexit snd_echo_remove(struct pci_dev *pci)
+{
+       struct echoaudio *chip;
+
+       chip = pci_get_drvdata(pci);
+       if (chip)
+               snd_card_free(chip->card);
+       pci_set_drvdata(pci, NULL);
+}
+
+
+
+/******************************************************************************
+       Everything starts and ends here
+******************************************************************************/
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+       .name = "Echoaudio " ECHOCARD_NAME,
+       .id_table = snd_echo_ids,
+       .probe = snd_echo_probe,
+       .remove = __devexit_p(snd_echo_remove),
+};
+
+
+
+/* initialization of the module */
+static int __init alsa_card_echo_init(void)
+{
+       return pci_register_driver(&driver);
+}
+
+
+
+/* clean up the module */
+static void __exit alsa_card_echo_exit(void)
+{
+       pci_unregister_driver(&driver);
+}
+
+
+module_init(alsa_card_echo_init)
+module_exit(alsa_card_echo_exit)
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h
new file mode 100644 (file)
index 0000000..7e88c96
--- /dev/null
@@ -0,0 +1,590 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+ ****************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+ ****************************************************************************
+
+
+   Here's a block diagram of how most of the cards work:
+
+                  +-----------+
+           record |           |<-------------------- Inputs
+          <-------|           |        |
+     PCI          | Transport |        |
+     bus          |  engine   |       \|/
+          ------->|           |    +-------+
+            play  |           |--->|monitor|-------> Outputs
+                  +-----------+    | mixer |
+                                   +-------+
+
+   The lines going to and from the PCI bus represent "pipes".  A pipe performs
+   audio transport - moving audio data to and from buffers on the host via
+   bus mastering.
+
+   The inputs and outputs on the right represent input and output "busses."
+   A bus is a physical, real connection to the outside world.  An example
+   of a bus would be the 1/4" analog connectors on the back of Layla or
+   an RCA S/PDIF connector.
+
+   For most cards, there is a one-to-one correspondence between outputs
+   and busses; that is, each individual pipe is hard-wired to a single bus.
+
+   Cards that work this way are Darla20, Gina20, Layla20, Darla24, Gina24,
+   Layla24, Mona, and Indigo.
+
+
+   Mia has a feature called "virtual outputs."
+
+
+                  +-----------+
+           record |           |<----------------------------- Inputs
+          <-------|           |                  |
+     PCI          | Transport |                  |
+     bus          |  engine   |                 \|/
+          ------->|           |   +------+   +-------+
+            play  |           |-->|vmixer|-->|monitor|-------> Outputs
+                  +-----------+   +------+   | mixer |
+                                             +-------+
+
+
+   Obviously, the difference here is the box labeled "vmixer."  Vmixer is
+   short for "virtual output mixer."  For Mia, pipes are *not* hard-wired
+   to a single bus; the vmixer lets you mix any pipe to any bus in any
+   combination.
+
+   Note, however, that the left-hand side of the diagram is unchanged.
+   Transport works exactly the same way - the difference is in the mixer stage.
+
+
+   Pipes and busses are numbered starting at zero.
+
+
+
+   Pipe index
+   ==========
+
+   A number of calls in CEchoGals refer to a "pipe index".  A pipe index is
+   a unique number for a pipe that unambiguously refers to a playback or record
+   pipe.  Pipe indices are numbered starting with analog outputs, followed by
+   digital outputs, then analog inputs, then digital inputs.
+
+   Take Gina24 as an example:
+
+   Pipe index
+
+   0-7            Analog outputs (0 .. FirstDigitalBusOut-1)
+   8-15           Digital outputs (FirstDigitalBusOut .. NumBussesOut-1)
+   16-17          Analog inputs
+   18-25          Digital inputs
+
+
+   You get the pipe index by calling CEchoGals::OpenAudio; the other transport
+   functions take the pipe index as a parameter.  If you need a pipe index for
+   some other reason, use the handy Makepipe_index method.
+
+
+   Some calls take a CChannelMask parameter; CChannelMask is a handy way to
+   group pipe indices.
+
+
+
+   Digital mode switch
+   ===================
+
+   Some cards (right now, Gina24, Layla24, and Mona) have a Digital Mode Switch
+   or DMS.  Cards with a DMS can be set to one of three mutually exclusive
+   digital modes: S/PDIF RCA, S/PDIF optical, or ADAT optical.
+
+   This may create some confusion since ADAT optical is 8 channels wide and
+   S/PDIF is only two channels wide.  Gina24, Layla24, and Mona handle this
+   by acting as if they always have 8 digital outs and ins.  If you are in
+   either S/PDIF mode, the last 6 channels don't do anything - data sent
+   out these channels is thrown away and you will always record zeros.
+
+   Note that with Gina24, Layla24, and Mona, sample rates above 50 kHz are
+   only available if you have the card configured for S/PDIF optical or S/PDIF
+   RCA.
+
+
+
+   Double speed mode
+   =================
+
+   Some of the cards support 88.2 kHz and 96 kHz sampling (Darla24, Gina24,
+   Layla24, Mona, Mia, and Indigo).  For these cards, the driver sometimes has
+   to worry about "double speed mode"; double speed mode applies whenever the
+   sampling rate is above 50 kHz.
+
+   For instance, Mona and Layla24 support word clock sync.  However, they
+   actually support two different word clock modes - single speed (below
+   50 kHz) and double speed (above 50 kHz).  The hardware detects if a single
+   or double speed word clock signal is present; the generic code uses that
+   information to determine which mode to use.
+
+   The generic code takes care of all this for you.
+*/
+
+
+#ifndef _ECHOAUDIO_H_
+#define _ECHOAUDIO_H_
+
+
+#define TRUE 1
+#define FALSE 0
+
+#include "echoaudio_dsp.h"
+
+
+
+/***********************************************************************
+
+       PCI configuration space
+
+***********************************************************************/
+
+/*
+ * PCI vendor ID and device IDs for the hardware
+ */
+#define VENDOR_ID              0x1057
+#define DEVICE_ID_56301                0x1801
+#define DEVICE_ID_56361                0x3410
+#define SUBVENDOR_ID           0xECC0
+
+
+/*
+ * Valid Echo PCI subsystem card IDs
+ */
+#define DARLA20                        0x0010
+#define GINA20                 0x0020
+#define LAYLA20                        0x0030
+#define DARLA24                        0x0040
+#define GINA24                 0x0050
+#define LAYLA24                        0x0060
+#define MONA                   0x0070
+#define MIA                    0x0080
+#define INDIGO                 0x0090
+#define INDIGO_IO              0x00a0
+#define INDIGO_DJ              0x00b0
+#define ECHO3G                 0x0100
+
+
+/************************************************************************
+
+       Array sizes and so forth
+
+***********************************************************************/
+
+/*
+ * Sizes
+ */
+#define ECHO_MAXAUDIOINPUTS    32      /* Max audio input channels */
+#define ECHO_MAXAUDIOOUTPUTS   32      /* Max audio output channels */
+#define ECHO_MAXAUDIOPIPES     32      /* Max number of input and output
+                                        * pipes */
+#define E3G_MAX_OUTPUTS                16
+#define ECHO_MAXMIDIJACKS      1       /* Max MIDI ports */
+#define ECHO_MIDI_QUEUE_SZ     512     /* Max MIDI input queue entries */
+#define ECHO_MTC_QUEUE_SZ      32      /* Max MIDI time code input queue
+                                        * entries */
+
+/*
+ * MIDI activity indicator timeout
+ */
+#define MIDI_ACTIVITY_TIMEOUT_USEC     200000
+
+
+/****************************************************************************
+   Clocks
+
+*****************************************************************************/
+
+/*
+ * Clock numbers
+ */
+#define ECHO_CLOCK_INTERNAL            0
+#define ECHO_CLOCK_WORD                        1
+#define ECHO_CLOCK_SUPER               2
+#define ECHO_CLOCK_SPDIF               3
+#define ECHO_CLOCK_ADAT                        4
+#define ECHO_CLOCK_ESYNC               5
+#define ECHO_CLOCK_ESYNC96             6
+#define ECHO_CLOCK_MTC                 7
+#define ECHO_CLOCK_NUMBER              8
+#define ECHO_CLOCKS                    0xffff
+
+/*
+ * Clock bit numbers - used to report capabilities and whatever clocks
+ * are being detected dynamically.
+ */
+#define ECHO_CLOCK_BIT_INTERNAL                (1 << ECHO_CLOCK_INTERNAL)
+#define ECHO_CLOCK_BIT_WORD            (1 << ECHO_CLOCK_WORD)
+#define ECHO_CLOCK_BIT_SUPER           (1 << ECHO_CLOCK_SUPER)
+#define ECHO_CLOCK_BIT_SPDIF           (1 << ECHO_CLOCK_SPDIF)
+#define ECHO_CLOCK_BIT_ADAT            (1 << ECHO_CLOCK_ADAT)
+#define ECHO_CLOCK_BIT_ESYNC           (1 << ECHO_CLOCK_ESYNC)
+#define ECHO_CLOCK_BIT_ESYNC96         (1 << ECHO_CLOCK_ESYNC96)
+#define ECHO_CLOCK_BIT_MTC             (1<<ECHO_CLOCK_MTC)
+
+
+/***************************************************************************
+
+   Digital modes
+
+****************************************************************************/
+
+/*
+ * Digital modes for Mona, Layla24, and Gina24
+ */
+#define DIGITAL_MODE_NONE                      0xFF
+#define DIGITAL_MODE_SPDIF_RCA                 0
+#define DIGITAL_MODE_SPDIF_OPTICAL             1
+#define DIGITAL_MODE_ADAT                      2
+#define DIGITAL_MODE_SPDIF_CDROM               3
+#define DIGITAL_MODES                          4
+
+/*
+ * Digital mode capability masks
+ */
+#define ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA    (1 << DIGITAL_MODE_SPDIF_RCA)
+#define ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL        (1 << DIGITAL_MODE_SPDIF_OPTICAL)
+#define ECHOCAPS_HAS_DIGITAL_MODE_ADAT         (1 << DIGITAL_MODE_ADAT)
+#define ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM  (1 << DIGITAL_MODE_SPDIF_CDROM)
+
+
+#define EXT_3GBOX_NC                   0x01    /* 3G box not connected */
+#define EXT_3GBOX_NOT_SET              0x02    /* 3G box not detected yet */
+
+
+#define ECHOGAIN_MUTED         (-128)  /* Minimum possible gain */
+#define ECHOGAIN_MINOUT                (-128)  /* Min output gain (dB) */
+#define ECHOGAIN_MAXOUT                (6)     /* Max output gain (dB) */
+#define ECHOGAIN_MININP                (-50)   /* Min input gain (0.5 dB) */
+#define ECHOGAIN_MAXINP                (50)    /* Max input gain (0.5 dB) */
+
+#define PIPE_STATE_STOPPED     0       /* Pipe has been reset */
+#define PIPE_STATE_PAUSED      1       /* Pipe has been stopped */
+#define PIPE_STATE_STARTED     2       /* Pipe has been started */
+#define PIPE_STATE_PENDING     3       /* Pipe has pending start */
+
+
+/* Debug initialization */
+#ifdef CONFIG_SND_DEBUG
+#define DE_INIT(x) snd_printk x
+#else
+#define DE_INIT(x)
+#endif
+
+/* Debug hw_params callbacks */
+#ifdef CONFIG_SND_DEBUG
+#define DE_HWP(x) snd_printk x
+#else
+#define DE_HWP(x)
+#endif
+
+/* Debug normal activity (open, start, stop...) */
+#ifdef CONFIG_SND_DEBUG
+#define DE_ACT(x) snd_printk x
+#else
+#define DE_ACT(x)
+#endif
+
+/* Debug midi activity */
+#ifdef CONFIG_SND_DEBUG
+#define DE_MID(x) snd_printk x
+#else
+#define DE_MID(x)
+#endif
+
+
+struct audiopipe {
+       volatile u32 *dma_counter;      /* Commpage register that contains
+                                        * the current dma position
+                                        * (lower 32 bits only)
+                                        */
+       u32 last_counter;               /* The last position, which is used
+                                        * to compute...
+                                        */
+       u32 position;                   /* ...the number of bytes tranferred
+                                        * by the DMA engine, modulo the
+                                        * buffer size
+                                        */
+       short index;                    /* Index of the first channel or <0
+                                        * if hw is not configured yet
+                                        */
+       short interleave;
+       struct snd_dma_buffer sgpage;   /* Room for the scatter-gather list */
+       struct snd_pcm_hardware hw;
+       struct snd_pcm_hw_constraint_list constr;
+       short sglist_head;
+       char state;                     /* pipe state */
+};
+
+
+struct audioformat {
+       u8 interleave;                  /* How the data is arranged in memory:
+                                        * mono = 1, stereo = 2, ...
+                                        */
+       u8 bits_per_sample;             /* 8, 16, 24, 32 (24 bits left aligned) */
+       char mono_to_stereo;            /* Only used if interleave is 1 and
+                                        * if this is an output pipe.
+                                        */
+       char data_are_bigendian;        /* 1 = big endian, 0 = little endian */
+};
+
+
+struct echoaudio {
+       spinlock_t lock;
+       struct snd_pcm_substream *substream[DSP_MAXPIPES];
+       int last_period[DSP_MAXPIPES];
+       struct semaphore mode_mutex;
+       u16 num_digital_modes, digital_mode_list[6];
+       u16 num_clock_sources, clock_source_list[10];
+       atomic_t opencount;
+       struct snd_kcontrol *clock_src_ctl;
+       struct snd_pcm *analog_pcm, *digital_pcm;
+       struct snd_card *card;
+       const char *card_name;
+       struct pci_dev *pci;
+       unsigned long dsp_registers_phys;
+       struct resource *iores;
+       struct snd_dma_buffer commpage_dma_buf;
+       int irq;
+#ifdef ECHOCARD_HAS_MIDI
+       struct snd_rawmidi *rmidi;
+       struct snd_rawmidi_substream *midi_in, *midi_out;
+#endif
+       struct timer_list timer;
+       char tinuse;                            /* Timer in use */
+       char midi_full;                         /* MIDI output buffer is full */
+       char can_set_rate;
+       char rate_set;
+
+       /* This stuff is used mainly by the lowlevel code */
+       struct comm_page *comm_page;    /* Virtual address of the memory
+                                        * seen by DSP
+                                        */
+       u32 pipe_alloc_mask;            /* Bitmask of allocated pipes */
+       u32 pipe_cyclic_mask;           /* Bitmask of pipes with cyclic
+                                        * buffers
+                                        */
+       u32 sample_rate;                /* Card sample rate in Hz */
+       u8 digital_mode;                /* Current digital mode
+                                        * (see DIGITAL_MODE_*)
+                                        */
+       u8 spdif_status;                /* Gina20, Darla20, Darla24 - only */
+       u8 clock_state;                 /* Gina20, Darla20, Darla24 - only */
+       u8 input_clock;                 /* Currently selected sample clock
+                                        * source
+                                        */
+       u8 output_clock;                /* Layla20 only */
+       char meters_enabled;            /* VU-meters status */
+       char asic_loaded;               /* Set TRUE when ASIC loaded */
+       char bad_board;                 /* Set TRUE if DSP won't load */
+       char professional_spdif;        /* 0 = consumer; 1 = professional */
+       char non_audio_spdif;           /* 3G - only */
+       char digital_in_automute;       /* Gina24, Layla24, Mona - only */
+       char has_phantom_power;
+       char hasnt_input_nominal_level; /* Gina3G */
+       char phantom_power;             /* Gina3G - only */
+       char has_midi;
+       char midi_input_enabled;
+
+#ifdef ECHOCARD_ECHO3G
+       /* External module -dependent pipe and bus indexes */
+       char px_digital_out, px_analog_in, px_digital_in, px_num;
+       char bx_digital_out, bx_analog_in, bx_digital_in, bx_num;
+#endif
+
+       char nominal_level[ECHO_MAXAUDIOPIPES]; /* True == -10dBV
+                                                * False == +4dBu */
+       s8 input_gain[ECHO_MAXAUDIOINPUTS];     /* Input level -50..+50
+                                                * unit is 0.5dB */
+       s8 output_gain[ECHO_MAXAUDIOOUTPUTS];   /* Output level -128..+6 dB
+                                                * (-128=muted) */
+       s8 monitor_gain[ECHO_MAXAUDIOOUTPUTS][ECHO_MAXAUDIOINPUTS];
+               /* -128..+6 dB */
+       s8 vmixer_gain[ECHO_MAXAUDIOOUTPUTS][ECHO_MAXAUDIOOUTPUTS];
+               /* -128..+6 dB */
+
+       u16 digital_modes;              /* Bitmask of supported modes
+                                        * (see ECHOCAPS_HAS_DIGITAL_MODE_*) */
+       u16 input_clock_types;          /* Suppoted input clock types */
+       u16 output_clock_types;         /* Suppoted output clock types -
+                                        * Layla20 only */
+       u16 device_id, subdevice_id;
+       u16 *dsp_code;                  /* Current DSP code loaded,
+                                        * NULL if nothing loaded */
+       const struct firmware *dsp_code_to_load;/* DSP code to load */
+       const struct firmware *asic_code;       /* Current ASIC code */
+       u32 comm_page_phys;                     /* Physical address of the
+                                                * memory seen by DSP */
+       volatile u32 __iomem *dsp_registers;    /* DSP's register base */
+       u32 active_mask;                        /* Chs. active mask or
+                                                * punks out */
+
+#ifdef ECHOCARD_HAS_MIDI
+       u16 mtc_state;                          /* State for MIDI input parsing state machine */
+       u8 midi_buffer[MIDI_IN_BUFFER_SIZE];
+#endif
+};
+
+
+static int init_dsp_comm_page(struct echoaudio *chip);
+static int init_line_levels(struct echoaudio *chip);
+static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe);
+static int load_firmware(struct echoaudio *chip);
+static int wait_handshake(struct echoaudio *chip);
+static int send_vector(struct echoaudio *chip, u32 command);
+static int get_firmware(const struct firmware **fw_entry,
+                       const struct firmware *frm, struct echoaudio *chip);
+static void free_firmware(const struct firmware *fw_entry);
+
+#ifdef ECHOCARD_HAS_MIDI
+static int enable_midi_input(struct echoaudio *chip, char enable);
+static int midi_service_irq(struct echoaudio *chip);
+static int __devinit snd_echo_midi_create(struct snd_card *card,
+                                         struct echoaudio *chip);
+#endif
+
+
+static inline void clear_handshake(struct echoaudio *chip)
+{
+       chip->comm_page->handshake = 0;
+}
+
+static inline u32 get_dsp_register(struct echoaudio *chip, u32 index)
+{
+       return readl(&chip->dsp_registers[index]);
+}
+
+static inline void set_dsp_register(struct echoaudio *chip, u32 index,
+                                   u32 value)
+{
+       writel(value, &chip->dsp_registers[index]);
+}
+
+
+/* Pipe and bus indexes. PX_* and BX_* are defined as chip->px_* and chip->bx_*
+for 3G cards because they depend on the external box. They are integer
+constants for all other cards.
+Never use those defines directly, use the following functions instead. */
+
+static inline int px_digital_out(const struct echoaudio *chip)
+{
+       return PX_DIGITAL_OUT;
+}
+
+static inline int px_analog_in(const struct echoaudio *chip)
+{
+       return PX_ANALOG_IN;
+}
+
+static inline int px_digital_in(const struct echoaudio *chip)
+{
+       return PX_DIGITAL_IN;
+}
+
+static inline int px_num(const struct echoaudio *chip)
+{
+       return PX_NUM;
+}
+
+static inline int bx_digital_out(const struct echoaudio *chip)
+{
+       return BX_DIGITAL_OUT;
+}
+
+static inline int bx_analog_in(const struct echoaudio *chip)
+{
+       return BX_ANALOG_IN;
+}
+
+static inline int bx_digital_in(const struct echoaudio *chip)
+{
+       return BX_DIGITAL_IN;
+}
+
+static inline int bx_num(const struct echoaudio *chip)
+{
+       return BX_NUM;
+}
+
+static inline int num_pipes_out(const struct echoaudio *chip)
+{
+       return px_analog_in(chip);
+}
+
+static inline int num_pipes_in(const struct echoaudio *chip)
+{
+       return px_num(chip) - px_analog_in(chip);
+}
+
+static inline int num_busses_out(const struct echoaudio *chip)
+{
+       return bx_analog_in(chip);
+}
+
+static inline int num_busses_in(const struct echoaudio *chip)
+{
+       return bx_num(chip) - bx_analog_in(chip);
+}
+
+static inline int num_analog_busses_out(const struct echoaudio *chip)
+{
+       return bx_digital_out(chip);
+}
+
+static inline int num_analog_busses_in(const struct echoaudio *chip)
+{
+       return bx_digital_in(chip) - bx_analog_in(chip);
+}
+
+static inline int num_digital_busses_out(const struct echoaudio *chip)
+{
+       return num_busses_out(chip) - num_analog_busses_out(chip);
+}
+
+static inline int num_digital_busses_in(const struct echoaudio *chip)
+{
+       return num_busses_in(chip) - num_analog_busses_in(chip);
+}
+
+/* The monitor array is a one-dimensional array; compute the offset
+ * into the array */
+static inline int monitor_index(const struct echoaudio *chip, int out, int in)
+{
+       return out * num_busses_in(chip) + in;
+}
+
+
+#ifndef pci_device
+#define pci_device(chip) (&chip->pci->dev)
+#endif
+
+
+#endif /* _ECHOAUDIO_H_ */
diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c
new file mode 100644 (file)
index 0000000..9f439ea
--- /dev/null
@@ -0,0 +1,431 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+
+/* These functions are common for all "3G" cards */
+
+
+static int check_asic_status(struct echoaudio *chip)
+{
+       u32 box_status;
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->comm_page->ext_box_status =
+               __constant_cpu_to_le32(E3G_ASIC_NOT_LOADED);
+       chip->asic_loaded = FALSE;
+       clear_handshake(chip);
+       send_vector(chip, DSP_VC_TEST_ASIC);
+
+       if (wait_handshake(chip)) {
+               chip->dsp_code = NULL;
+               return -EIO;
+       }
+
+       box_status = le32_to_cpu(chip->comm_page->ext_box_status);
+       DE_INIT(("box_status=%x\n", box_status));
+       if (box_status == E3G_ASIC_NOT_LOADED)
+               return -ENODEV;
+
+       chip->asic_loaded = TRUE;
+       return box_status & E3G_BOX_TYPE_MASK;
+}
+
+
+
+static inline u32 get_frq_reg(struct echoaudio *chip)
+{
+       return le32_to_cpu(chip->comm_page->e3g_frq_register);
+}
+
+
+
+/* Most configuration of 3G cards is accomplished by writing the control
+register. write_control_reg sends the new control register value to the DSP. */
+static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
+                            char force)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+
+       DE_ACT(("WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq));
+
+       ctl = cpu_to_le32(ctl);
+       frq = cpu_to_le32(frq);
+
+       if (ctl != chip->comm_page->control_register ||
+           frq != chip->comm_page->e3g_frq_register || force) {
+               chip->comm_page->e3g_frq_register = frq;
+               chip->comm_page->control_register = ctl;
+               clear_handshake(chip);
+               return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
+       }
+
+       DE_ACT(("WriteControlReg: not written, no change\n"));
+       return 0;
+}
+
+
+
+/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */
+static int set_digital_mode(struct echoaudio *chip, u8 mode)
+{
+       u8 previous_mode;
+       int err, i, o;
+
+       /* All audio channels must be closed before changing the digital mode */
+       snd_assert(!chip->pipe_alloc_mask, return -EAGAIN);
+
+       snd_assert(chip->digital_modes & (1 << mode), return -EINVAL);
+
+       previous_mode = chip->digital_mode;
+       err = dsp_set_digital_mode(chip, mode);
+
+       /* If we successfully changed the digital mode from or to ADAT,
+        * then make sure all output, input and monitor levels are
+        * updated by the DSP comm object. */
+       if (err >= 0 && previous_mode != mode &&
+           (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
+               spin_lock_irq(&chip->lock);
+               for (o = 0; o < num_busses_out(chip); o++)
+                       for (i = 0; i < num_busses_in(chip); i++)
+                               set_monitor_gain(chip, o, i,
+                                                chip->monitor_gain[o][i]);
+
+#ifdef ECHOCARD_HAS_INPUT_GAIN
+               for (i = 0; i < num_busses_in(chip); i++)
+                       set_input_gain(chip, i, chip->input_gain[i]);
+               update_input_line_level(chip);
+#endif
+
+               for (o = 0; o < num_busses_out(chip); o++)
+                       set_output_gain(chip, o, chip->output_gain[o]);
+               update_output_line_level(chip);
+               spin_unlock_irq(&chip->lock);
+       }
+
+       return err;
+}
+
+
+
+static u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate)
+{
+       control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK;
+
+       switch (rate) {
+       case 32000 :
+               control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1;
+               break;
+       case 44100 :
+               if (chip->professional_spdif)
+                       control_reg |= E3G_SPDIF_SAMPLE_RATE0;
+               break;
+       case 48000 :
+               control_reg |= E3G_SPDIF_SAMPLE_RATE1;
+               break;
+       }
+
+       if (chip->professional_spdif)
+               control_reg |= E3G_SPDIF_PRO_MODE;
+
+       if (chip->non_audio_spdif)
+               control_reg |= E3G_SPDIF_NOT_AUDIO;
+
+       control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL |
+               E3G_SPDIF_COPY_PERMIT;
+
+       return control_reg;
+}
+
+
+
+/* Set the S/PDIF output format */
+static int set_professional_spdif(struct echoaudio *chip, char prof)
+{
+       u32 control_reg;
+
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       chip->professional_spdif = prof;
+       control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate);
+       return write_control_reg(chip, control_reg, get_frq_reg(chip), 0);
+}
+
+
+
+/* detect_input_clocks() returns a bitmask consisting of all the input clocks
+currently connected to the hardware; this changes as the user connects and
+disconnects clock inputs. You should use this information to determine which
+clocks the user is allowed to select. */
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock
+        * detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD)
+               clock_bits |= ECHO_CLOCK_BIT_WORD;
+
+       switch(chip->digital_mode) {
+       case DIGITAL_MODE_SPDIF_RCA:
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+               if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF)
+                       clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+               break;
+       case DIGITAL_MODE_ADAT:
+               if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT)
+                       clock_bits |= ECHO_CLOCK_BIT_ADAT;
+               break;
+       }
+
+       return clock_bits;
+}
+
+
+
+static int load_asic(struct echoaudio *chip)
+{
+       int box_type, err;
+
+       if (chip->asic_loaded)
+               return 0;
+
+       /* Give the DSP a few milliseconds to settle down */
+       mdelay(2);
+
+       err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC,
+                               &card_fw[FW_3G_ASIC]);
+       if (err < 0)
+               return err;
+
+       chip->asic_code = &card_fw[FW_3G_ASIC];
+
+       /* Now give the new ASIC a little time to set up */
+       mdelay(2);
+       /* See if it worked */
+       box_type = check_asic_status(chip);
+
+       /* Set up the control register if the load succeeded -
+        * 48 kHz, internal clock, S/PDIF RCA mode */
+       if (box_type >= 0) {
+               err = write_control_reg(chip, E3G_48KHZ,
+                                       E3G_FREQ_REG_DEFAULT, TRUE);
+               if (err < 0)
+                       return err;
+       }
+
+       return box_type;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg, clock, base_rate, frq_reg;
+
+       /* Only set the clock for internal mode. */
+       if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
+               DE_ACT(("set_sample_rate: Cannot set sample rate - "
+                       "clock not set to CLK_CLOCKININTERNAL\n"));
+               /* Save the rate anyhow */
+               chip->comm_page->sample_rate = cpu_to_le32(rate);
+               chip->sample_rate = rate;
+               set_input_clock(chip, chip->input_clock);
+               return 0;
+       }
+
+       snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT,
+                  return -EINVAL);
+
+       clock = 0;
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= E3G_CLOCK_CLEAR_MASK;
+
+       switch (rate) {
+       case 96000:
+               clock = E3G_96KHZ;
+               break;
+       case 88200:
+               clock = E3G_88KHZ;
+               break;
+       case 48000:
+               clock = E3G_48KHZ;
+               break;
+       case 44100:
+               clock = E3G_44KHZ;
+               break;
+       case 32000:
+               clock = E3G_32KHZ;
+               break;
+       default:
+               clock = E3G_CONTINUOUS_CLOCK;
+               if (rate > 50000)
+                       clock |= E3G_DOUBLE_SPEED_MODE;
+               break;
+       }
+
+       control_reg |= clock;
+       control_reg = set_spdif_bits(chip, control_reg, rate);
+
+       base_rate = rate;
+       if (base_rate > 50000)
+               base_rate /= 2;
+       if (base_rate < 32000)
+               base_rate = 32000;
+
+       frq_reg = E3G_MAGIC_NUMBER / base_rate - 2;
+       if (frq_reg > E3G_FREQ_REG_MAX)
+               frq_reg = E3G_FREQ_REG_MAX;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
+       chip->sample_rate = rate;
+       DE_ACT(("SetSampleRate: %d clock %x\n", rate, control_reg));
+
+       /* Tell the DSP about it - DSP reads both control reg & freq reg */
+       return write_control_reg(chip, control_reg, frq_reg, 0);
+}
+
+
+
+/* Set the sample clock source to internal, S/PDIF, ADAT */
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       u32 control_reg, clocks_from_dsp;
+
+       DE_ACT(("set_input_clock:\n"));
+
+       /* Mask off the clock select bits */
+       control_reg = le32_to_cpu(chip->comm_page->control_register) &
+               E3G_CLOCK_CLEAR_MASK;
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       switch (clock) {
+       case ECHO_CLOCK_INTERNAL:
+               DE_ACT(("Set Echo3G clock to INTERNAL\n"));
+               chip->input_clock = ECHO_CLOCK_INTERNAL;
+               return set_sample_rate(chip, chip->sample_rate);
+       case ECHO_CLOCK_SPDIF:
+               if (chip->digital_mode == DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               DE_ACT(("Set Echo3G clock to SPDIF\n"));
+               control_reg |= E3G_SPDIF_CLOCK;
+               if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96)
+                       control_reg |= E3G_DOUBLE_SPEED_MODE;
+               else
+                       control_reg &= ~E3G_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_ADAT:
+               if (chip->digital_mode != DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               DE_ACT(("Set Echo3G clock to ADAT\n"));
+               control_reg |= E3G_ADAT_CLOCK;
+               control_reg &= ~E3G_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_WORD:
+               DE_ACT(("Set Echo3G clock to WORD\n"));
+               control_reg |= E3G_WORD_CLOCK;
+               if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96)
+                       control_reg |= E3G_DOUBLE_SPEED_MODE;
+               else
+                       control_reg &= ~E3G_DOUBLE_SPEED_MODE;
+               break;
+       default:
+               DE_ACT(("Input clock 0x%x not supported for Echo3G\n", clock));
+               return -EINVAL;
+       }
+
+       chip->input_clock = clock;
+       return write_control_reg(chip, control_reg, get_frq_reg(chip), 1);
+}
+
+
+
+static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
+{
+       u32 control_reg;
+       int err, incompatible_clock;
+
+       /* Set clock to "internal" if it's not compatible with the new mode */
+       incompatible_clock = FALSE;
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+       case DIGITAL_MODE_SPDIF_RCA:
+               if (chip->input_clock == ECHO_CLOCK_ADAT)
+                       incompatible_clock = TRUE;
+               break;
+       case DIGITAL_MODE_ADAT:
+               if (chip->input_clock == ECHO_CLOCK_SPDIF)
+                       incompatible_clock = TRUE;
+               break;
+       default:
+               DE_ACT(("Digital mode not supported: %d\n", mode));
+               return -EINVAL;
+       }
+
+       spin_lock_irq(&chip->lock);
+
+       if (incompatible_clock) {
+               chip->sample_rate = 48000;
+               set_input_clock(chip, ECHO_CLOCK_INTERNAL);
+       }
+
+       /* Clear the current digital mode */
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK;
+
+       /* Tweak the control reg */
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+               control_reg |= E3G_SPDIF_OPTICAL_MODE;
+               break;
+       case DIGITAL_MODE_SPDIF_RCA:
+               /* E3G_SPDIF_OPTICAL_MODE bit cleared */
+               break;
+       case DIGITAL_MODE_ADAT:
+               control_reg |= E3G_ADAT_MODE;
+               control_reg &= ~E3G_DOUBLE_SPEED_MODE;  /* @@ useless */
+               break;
+       }
+
+       err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1);
+       spin_unlock_irq(&chip->lock);
+       if (err < 0)
+               return err;
+       chip->digital_mode = mode;
+
+       DE_ACT(("set_digital_mode(%d)\n", chip->digital_mode));
+       return incompatible_clock;
+}
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c
new file mode 100644 (file)
index 0000000..42afa83
--- /dev/null
@@ -0,0 +1,1125 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+#if PAGE_SIZE < 4096
+#error PAGE_SIZE is < 4k
+#endif
+
+static int restore_dsp_rettings(struct echoaudio *chip);
+
+
+/* Some vector commands involve the DSP reading or writing data to and from the
+comm page; if you send one of these commands to the DSP, it will complete the
+command and then write a non-zero value to the Handshake field in the
+comm page.  This function waits for the handshake to show up. */
+static int wait_handshake(struct echoaudio *chip)
+{
+       int i;
+
+       /* Wait up to 10ms for the handshake from the DSP */
+       for (i = 0; i < HANDSHAKE_TIMEOUT; i++) {
+               /* Look for the handshake value */
+               if (chip->comm_page->handshake) {
+                       /*if (i)  DE_ACT(("Handshake time: %d\n", i));*/
+                       return 0;
+               }
+               udelay(1);
+       }
+
+       snd_printk(KERN_ERR "wait_handshake(): Timeout waiting for DSP\n");
+       return -EBUSY;
+}
+
+
+
+/* Much of the interaction between the DSP and the driver is done via vector
+commands; send_vector writes a vector command to the DSP.  Typically, this
+causes the DSP to read or write fields in the comm page.
+PCI posting is not required thanks to the handshake logic. */
+static int send_vector(struct echoaudio *chip, u32 command)
+{
+       int i;
+
+       wmb();  /* Flush all pending writes before sending the command */
+
+       /* Wait up to 100ms for the "vector busy" bit to be off */
+       for (i = 0; i < VECTOR_BUSY_TIMEOUT; i++) {
+               if (!(get_dsp_register(chip, CHI32_VECTOR_REG) &
+                     CHI32_VECTOR_BUSY)) {
+                       set_dsp_register(chip, CHI32_VECTOR_REG, command);
+                       /*if (i)  DE_ACT(("send_vector time: %d\n", i));*/
+                       return 0;
+               }
+               udelay(1);
+       }
+
+       DE_ACT((KERN_ERR "timeout on send_vector\n"));
+       return -EBUSY;
+}
+
+
+
+/* write_dsp writes a 32-bit value to the DSP; this is used almost
+exclusively for loading the DSP. */
+static int write_dsp(struct echoaudio *chip, u32 data)
+{
+       u32 status, i;
+
+       for (i = 0; i < 10000000; i++) {        /* timeout = 10s */
+               status = get_dsp_register(chip, CHI32_STATUS_REG);
+               if ((status & CHI32_STATUS_HOST_WRITE_EMPTY) != 0) {
+                       set_dsp_register(chip, CHI32_DATA_REG, data);
+                       wmb();                  /* write it immediately */
+                       return 0;
+               }
+               udelay(1);
+               cond_resched();
+       }
+
+       chip->bad_board = TRUE;         /* Set TRUE until DSP re-loaded */
+       DE_ACT((KERN_ERR "write_dsp: Set bad_board to TRUE\n"));
+       return -EIO;
+}
+
+
+
+/* read_dsp reads a 32-bit value from the DSP; this is used almost
+exclusively for loading the DSP and checking the status of the ASIC. */
+static int read_dsp(struct echoaudio *chip, u32 *data)
+{
+       u32 status, i;
+
+       for (i = 0; i < READ_DSP_TIMEOUT; i++) {
+               status = get_dsp_register(chip, CHI32_STATUS_REG);
+               if ((status & CHI32_STATUS_HOST_READ_FULL) != 0) {
+                       *data = get_dsp_register(chip, CHI32_DATA_REG);
+                       return 0;
+               }
+               udelay(1);
+               cond_resched();
+       }
+
+       chip->bad_board = TRUE;         /* Set TRUE until DSP re-loaded */
+       DE_INIT((KERN_ERR "read_dsp: Set bad_board to TRUE\n"));
+       return -EIO;
+}
+
+
+
+/****************************************************************************
+       Firmware loading functions
+ ****************************************************************************/
+
+/* This function is used to read back the serial number from the DSP;
+this is triggered by the SET_COMMPAGE_ADDR command.
+Only some early Echogals products have serial numbers in the ROM;
+the serial number is not used, but you still need to do this as
+part of the DSP load process. */
+static int read_sn(struct echoaudio *chip)
+{
+       int i;
+       u32 sn[6];
+
+       for (i = 0; i < 5; i++) {
+               if (read_dsp(chip, &sn[i])) {
+                       snd_printk(KERN_ERR "Failed to read serial number\n");
+                       return -EIO;
+               }
+       }
+       DE_INIT(("Read serial number %08x %08x %08x %08x %08x\n",
+                sn[0], sn[1], sn[2], sn[3], sn[4]));
+       return 0;
+}
+
+
+
+#ifndef ECHOCARD_HAS_ASIC
+/* This card has no ASIC, just return ok */
+static inline int check_asic_status(struct echoaudio *chip)
+{
+       chip->asic_loaded = TRUE;
+       return 0;
+}
+
+#endif /* !ECHOCARD_HAS_ASIC */
+
+
+
+#ifdef ECHOCARD_HAS_ASIC
+
+/* Load ASIC code - done after the DSP is loaded */
+static int load_asic_generic(struct echoaudio *chip, u32 cmd,
+                            const struct firmware *asic)
+{
+       const struct firmware *fw;
+       int err;
+       u32 i, size;
+       u8 *code;
+
+       if ((err = get_firmware(&fw, asic, chip)) < 0) {
+               snd_printk(KERN_WARNING "Firmware not found !\n");
+               return err;
+       }
+
+       code = (u8 *)fw->data;
+       size = fw->size;
+
+       /* Send the "Here comes the ASIC" command */
+       if (write_dsp(chip, cmd) < 0)
+               goto la_error;
+
+       /* Write length of ASIC file in bytes */
+       if (write_dsp(chip, size) < 0)
+               goto la_error;
+
+       for (i = 0; i < size; i++) {
+               if (write_dsp(chip, code[i]) < 0)
+                       goto la_error;
+       }
+
+       DE_INIT(("ASIC loaded\n"));
+       free_firmware(fw);
+       return 0;
+
+la_error:
+       DE_INIT(("failed on write_dsp\n"));
+       free_firmware(fw);
+       return -EIO;
+}
+
+#endif /* ECHOCARD_HAS_ASIC */
+
+
+
+#ifdef DSP_56361
+
+/* Install the resident loader for 56361 DSPs;  The resident loader is on
+the EPROM on the board for 56301 DSP. The resident loader is a tiny little
+program that is used to load the real DSP code. */
+static int install_resident_loader(struct echoaudio *chip)
+{
+       u32 address;
+       int index, words, i;
+       u16 *code;
+       u32 status;
+       const struct firmware *fw;
+
+       /* 56361 cards only!  This check is required by the old 56301-based
+       Mona and Gina24 */
+       if (chip->device_id != DEVICE_ID_56361)
+               return 0;
+
+       /* Look to see if the resident loader is present.  If the resident
+       loader is already installed, host flag 5 will be on. */
+       status = get_dsp_register(chip, CHI32_STATUS_REG);
+       if (status & CHI32_STATUS_REG_HF5) {
+               DE_INIT(("Resident loader already installed; status is 0x%x\n",
+                        status));
+               return 0;
+       }
+
+       if ((i = get_firmware(&fw, &card_fw[FW_361_LOADER], chip)) < 0) {
+               snd_printk(KERN_WARNING "Firmware not found !\n");
+               return i;
+       }
+
+       /* The DSP code is an array of 16 bit words.  The array is divided up
+       into sections.  The first word of each section is the size in words,
+       followed by the section type.
+       Since DSP addresses and data are 24 bits wide, they each take up two
+       16 bit words in the array.
+       This is a lot like the other loader loop, but it's not a loop, you
+       don't write the memory type, and you don't write a zero at the end. */
+
+       /* Set DSP format bits for 24 bit mode */
+       set_dsp_register(chip, CHI32_CONTROL_REG,
+                        get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900);
+
+       code = (u16 *)fw->data;
+
+       /* Skip the header section; the first word in the array is the size
+       of the first section, so the first real section of code is pointed
+       to by Code[0]. */
+       index = code[0];
+
+       /* Skip the section size, LRS block type, and DSP memory type */
+       index += 3;
+
+       /* Get the number of DSP words to write */
+       words = code[index++];
+
+       /* Get the DSP address for this block; 24 bits, so build from two words */
+       address = ((u32)code[index] << 16) + code[index + 1];
+       index += 2;
+
+       /* Write the count to the DSP */
+       if (write_dsp(chip, words)) {
+               DE_INIT(("install_resident_loader: Failed to write word count!\n"));
+               goto irl_error;
+       }
+       /* Write the DSP address */
+       if (write_dsp(chip, address)) {
+               DE_INIT(("install_resident_loader: Failed to write DSP address!\n"));
+               goto irl_error;
+       }
+       /* Write out this block of code to the DSP */
+       for (i = 0; i < words; i++) {
+               u32 data;
+
+               data = ((u32)code[index] << 16) + code[index + 1];
+               if (write_dsp(chip, data)) {
+                       DE_INIT(("install_resident_loader: Failed to write DSP code\n"));
+                       goto irl_error;
+               }
+               index += 2;
+       }
+
+       /* Wait for flag 5 to come up */
+       for (i = 0; i < 200; i++) {     /* Timeout is 50us * 200 = 10ms */
+               udelay(50);
+               status = get_dsp_register(chip, CHI32_STATUS_REG);
+               if (status & CHI32_STATUS_REG_HF5)
+                       break;
+       }
+
+       if (i == 200) {
+               DE_INIT(("Resident loader failed to set HF5\n"));
+               goto irl_error;
+       }
+
+       DE_INIT(("Resident loader successfully installed\n"));
+       free_firmware(fw);
+       return 0;
+
+irl_error:
+       free_firmware(fw);
+       return -EIO;
+}
+
+#endif /* DSP_56361 */
+
+
+static int load_dsp(struct echoaudio *chip, u16 *code)
+{
+       u32 address, data;
+       int index, words, i;
+
+       if (chip->dsp_code == code) {
+               DE_INIT(("DSP is already loaded!\n"));
+               return 0;
+       }
+       chip->bad_board = TRUE;         /* Set TRUE until DSP loaded */
+       chip->dsp_code = NULL;          /* Current DSP code not loaded */
+       chip->asic_loaded = FALSE;      /* Loading the DSP code will reset the ASIC */
+
+       DE_INIT(("load_dsp: Set bad_board to TRUE\n"));
+
+       /* If this board requires a resident loader, install it. */
+#ifdef DSP_56361
+       if ((i = install_resident_loader(chip)) < 0)
+               return i;
+#endif
+
+       /* Send software reset command */
+       if (send_vector(chip, DSP_VC_RESET) < 0) {
+               DE_INIT(("LoadDsp: send_vector DSP_VC_RESET failed, Critical Failure\n"));
+               return -EIO;
+       }
+       /* Delay 10us */
+       udelay(10);
+
+       /* Wait 10ms for HF3 to indicate that software reset is complete */
+       for (i = 0; i < 1000; i++) {    /* Timeout is 10us * 1000 = 10ms */
+               if (get_dsp_register(chip, CHI32_STATUS_REG) &
+                   CHI32_STATUS_REG_HF3)
+                       break;
+               udelay(10);
+       }
+
+       if (i == 1000) {
+               DE_INIT(("load_dsp: Timeout waiting for CHI32_STATUS_REG_HF3\n"));
+               return -EIO;
+       }
+
+       /* Set DSP format bits for 24 bit mode now that soft reset is done */
+       set_dsp_register(chip, CHI32_CONTROL_REG,
+                        get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900);
+
+       /* Main loader loop */
+
+       index = code[0];
+       for (;;) {
+               int block_type, mem_type;
+
+               /* Total Block Size */
+               index++;
+
+               /* Block Type */
+               block_type = code[index];
+               if (block_type == 4)    /* We're finished */
+                       break;
+
+               index++;
+
+               /* Memory Type  P=0,X=1,Y=2 */
+               mem_type = code[index++];
+
+               /* Block Code Size */
+               words = code[index++];
+               if (words == 0)         /* We're finished */
+                       break;
+
+               /* Start Address */
+               address = ((u32)code[index] << 16) + code[index + 1];
+               index += 2;
+
+               if (write_dsp(chip, words) < 0) {
+                       DE_INIT(("load_dsp: failed to write number of DSP words\n"));
+                       return -EIO;
+               }
+               if (write_dsp(chip, address) < 0) {
+                       DE_INIT(("load_dsp: failed to write DSP address\n"));
+                       return -EIO;
+               }
+               if (write_dsp(chip, mem_type) < 0) {
+                       DE_INIT(("load_dsp: failed to write DSP memory type\n"));
+                       return -EIO;
+               }
+               /* Code */
+               for (i = 0; i < words; i++, index+=2) {
+                       data = ((u32)code[index] << 16) + code[index + 1];
+                       if (write_dsp(chip, data) < 0) {
+                               DE_INIT(("load_dsp: failed to write DSP data\n"));
+                               return -EIO;
+                       }
+               }
+       }
+
+       if (write_dsp(chip, 0) < 0) {   /* We're done!!! */
+               DE_INIT(("load_dsp: Failed to write final zero\n"));
+               return -EIO;
+       }
+       udelay(10);
+
+       for (i = 0; i < 5000; i++) {    /* Timeout is 100us * 5000 = 500ms */
+               /* Wait for flag 4 - indicates that the DSP loaded OK */
+               if (get_dsp_register(chip, CHI32_STATUS_REG) &
+                   CHI32_STATUS_REG_HF4) {
+                       set_dsp_register(chip, CHI32_CONTROL_REG,
+                                        get_dsp_register(chip, CHI32_CONTROL_REG) & ~0x1b00);
+
+                       if (write_dsp(chip, DSP_FNC_SET_COMMPAGE_ADDR) < 0) {
+                               DE_INIT(("load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n"));
+                               return -EIO;
+                       }
+
+                       if (write_dsp(chip, chip->comm_page_phys) < 0) {
+                               DE_INIT(("load_dsp: Failed to write comm page address\n"));
+                               return -EIO;
+                       }
+
+                       /* Get the serial number via slave mode.
+                       This is triggered by the SET_COMMPAGE_ADDR command.
+                       We don't actually use the serial number but we have to
+                       get it as part of the DSP init voodoo. */
+                       if (read_sn(chip) < 0) {
+                               DE_INIT(("load_dsp: Failed to read serial number\n"));
+                               return -EIO;
+                       }
+
+                       chip->dsp_code = code;          /* Show which DSP code loaded */
+                       chip->bad_board = FALSE;        /* DSP OK */
+                       DE_INIT(("load_dsp: OK!\n"));
+                       return 0;
+               }
+               udelay(100);
+       }
+
+       DE_INIT(("load_dsp: DSP load timed out waiting for HF4\n"));
+       return -EIO;
+}
+
+
+
+/* load_firmware takes care of loading the DSP and any ASIC code. */
+static int load_firmware(struct echoaudio *chip)
+{
+       const struct firmware *fw;
+       int box_type, err;
+
+       snd_assert(chip->dsp_code_to_load && chip->comm_page, return -EPERM);
+
+       /* See if the ASIC is present and working - only if the DSP is already loaded */
+       if (chip->dsp_code) {
+               if ((box_type = check_asic_status(chip)) >= 0)
+                       return box_type;
+               /* ASIC check failed; force the DSP to reload */
+               chip->dsp_code = NULL;
+       }
+
+       if ((err = get_firmware(&fw, chip->dsp_code_to_load, chip)) < 0)
+               return err;
+       err = load_dsp(chip, (u16 *)fw->data);
+       free_firmware(fw);
+       if (err < 0)
+               return err;
+
+       if ((box_type = load_asic(chip)) < 0)
+               return box_type;        /* error */
+
+       if ((err = restore_dsp_rettings(chip)) < 0)
+               return err;
+
+       return box_type;
+}
+
+
+
+/****************************************************************************
+       Mixer functions
+ ****************************************************************************/
+
+#if defined(ECHOCARD_HAS_INPUT_NOMINAL_LEVEL) || \
+       defined(ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL)
+
+/* Set the nominal level for an input or output bus (true = -10dBV, false = +4dBu) */
+static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer)
+{
+       snd_assert(index < num_busses_out(chip) + num_busses_in(chip),
+                  return -EINVAL);
+
+       /* Wait for the handshake (OK even if ASIC is not loaded) */
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->nominal_level[index] = consumer;
+
+       if (consumer)
+               chip->comm_page->nominal_level_mask |= cpu_to_le32(1 << index);
+       else
+               chip->comm_page->nominal_level_mask &= ~cpu_to_le32(1 << index);
+
+       return 0;
+}
+
+#endif /* ECHOCARD_HAS_*_NOMINAL_LEVEL */
+
+
+
+/* Set the gain for a single physical output channel (dB). */
+static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain)
+{
+       snd_assert(channel < num_busses_out(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       /* Save the new value */
+       chip->output_gain[channel] = gain;
+       chip->comm_page->line_out_level[channel] = gain;
+       return 0;
+}
+
+
+
+#ifdef ECHOCARD_HAS_MONITOR
+/* Set the monitor level from an input bus to an output bus. */
+static int set_monitor_gain(struct echoaudio *chip, u16 output, u16 input,
+                           s8 gain)
+{
+       snd_assert(output < num_busses_out(chip) &&
+                  input < num_busses_in(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->monitor_gain[output][input] = gain;
+       chip->comm_page->monitors[monitor_index(chip, output, input)] = gain;
+       return 0;
+}
+#endif /* ECHOCARD_HAS_MONITOR */
+
+
+/* Tell the DSP to read and update output, nominal & monitor levels in comm page. */
+static int update_output_line_level(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_OUTVOL);
+}
+
+
+
+/* Tell the DSP to read and update input levels in comm page */
+static int update_input_line_level(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_INGAIN);
+}
+
+
+
+/* set_meters_on turns the meters on or off.  If meters are turned on, the DSP
+will write the meter and clock detect values to the comm page at about 30Hz */
+static void set_meters_on(struct echoaudio *chip, char on)
+{
+       if (on && !chip->meters_enabled) {
+               send_vector(chip, DSP_VC_METERS_ON);
+               chip->meters_enabled = 1;
+       } else if (!on && chip->meters_enabled) {
+               send_vector(chip, DSP_VC_METERS_OFF);
+               chip->meters_enabled = 0;
+               memset((s8 *)chip->comm_page->vu_meter, ECHOGAIN_MUTED,
+                      DSP_MAXPIPES);
+               memset((s8 *)chip->comm_page->peak_meter, ECHOGAIN_MUTED,
+                      DSP_MAXPIPES);
+       }
+}
+
+
+
+/* Fill out an the given array using the current values in the comm page.
+Meters are written in the comm page by the DSP in this order:
+ Output busses
+ Input busses
+ Output pipes (vmixer cards only)
+
+This function assumes there are no more than 16 in/out busses or pipes
+Meters is an array [3][16][2] of long. */
+static void get_audio_meters(struct echoaudio *chip, long *meters)
+{
+       int i, m, n;
+
+       m = 0;
+       n = 0;
+       for (i = 0; i < num_busses_out(chip); i++, m++) {
+               meters[n++] = chip->comm_page->vu_meter[m];
+               meters[n++] = chip->comm_page->peak_meter[m];
+       }
+       for (; n < 32; n++)
+               meters[n] = 0;
+
+#ifdef ECHOCARD_ECHO3G
+       m = E3G_MAX_OUTPUTS;    /* Skip unused meters */
+#endif
+
+       for (i = 0; i < num_busses_in(chip); i++, m++) {
+               meters[n++] = chip->comm_page->vu_meter[m];
+               meters[n++] = chip->comm_page->peak_meter[m];
+       }
+       for (; n < 64; n++)
+               meters[n] = 0;
+
+#ifdef ECHOCARD_HAS_VMIXER
+       for (i = 0; i < num_pipes_out(chip); i++, m++) {
+               meters[n++] = chip->comm_page->vu_meter[m];
+               meters[n++] = chip->comm_page->peak_meter[m];
+       }
+#endif
+       for (; n < 96; n++)
+               meters[n] = 0;
+}
+
+
+
+static int restore_dsp_rettings(struct echoaudio *chip)
+{
+       int err;
+       DE_INIT(("restore_dsp_settings\n"));
+
+       if ((err = check_asic_status(chip)) < 0)
+               return err;
+
+       /* @ Gina20/Darla20 only. Should be harmless for other cards. */
+       chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF;
+       chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF;
+       chip->comm_page->handshake = 0xffffffff;
+
+       if ((err = set_sample_rate(chip, chip->sample_rate)) < 0)
+               return err;
+
+       if (chip->meters_enabled)
+               if (send_vector(chip, DSP_VC_METERS_ON) < 0)
+                       return -EIO;
+
+#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
+       if (set_input_clock(chip, chip->input_clock) < 0)
+               return -EIO;
+#endif
+
+#ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH
+       if (set_output_clock(chip, chip->output_clock) < 0)
+               return -EIO;
+#endif
+
+       if (update_output_line_level(chip) < 0)
+               return -EIO;
+
+       if (update_input_line_level(chip) < 0)
+               return -EIO;
+
+#ifdef ECHOCARD_HAS_VMIXER
+       if (update_vmixer_level(chip) < 0)
+               return -EIO;
+#endif
+
+       if (wait_handshake(chip) < 0)
+               return -EIO;
+       clear_handshake(chip);
+
+       DE_INIT(("restore_dsp_rettings done\n"));
+       return send_vector(chip, DSP_VC_UPDATE_FLAGS);
+}
+
+
+
+/****************************************************************************
+       Transport functions
+ ****************************************************************************/
+
+/* set_audio_format() sets the format of the audio data in host memory for
+this pipe.  Note that _MS_ (mono-to-stereo) playback modes are not used by ALSA
+but they are here because they are just mono while capturing */
+static void set_audio_format(struct echoaudio *chip, u16 pipe_index,
+                            const struct audioformat *format)
+{
+       u16 dsp_format;
+
+       dsp_format = DSP_AUDIOFORM_SS_16LE;
+
+       /* Look for super-interleave (no big-endian and 8 bits) */
+       if (format->interleave > 2) {
+               switch (format->bits_per_sample) {
+               case 16:
+                       dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE;
+                       break;
+               case 24:
+                       dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE;
+                       break;
+               case 32:
+                       dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE;
+                       break;
+               }
+               dsp_format |= format->interleave;
+       } else if (format->data_are_bigendian) {
+               /* For big-endian data, only 32 bit samples are supported */
+               switch (format->interleave) {
+               case 1:
+                       dsp_format = DSP_AUDIOFORM_MM_32BE;
+                       break;
+#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+               case 2:
+                       dsp_format = DSP_AUDIOFORM_SS_32BE;
+                       break;
+#endif
+               }
+       } else if (format->interleave == 1 &&
+                  format->bits_per_sample == 32 && !format->mono_to_stereo) {
+               /* 32 bit little-endian mono->mono case */
+               dsp_format = DSP_AUDIOFORM_MM_32LE;
+       } else {
+               /* Handle the other little-endian formats */
+               switch (format->bits_per_sample) {
+               case 8:
+                       if (format->interleave == 2)
+                               dsp_format = DSP_AUDIOFORM_SS_8;
+                       else
+                               dsp_format = DSP_AUDIOFORM_MS_8;
+                       break;
+               default:
+               case 16:
+                       if (format->interleave == 2)
+                               dsp_format = DSP_AUDIOFORM_SS_16LE;
+                       else
+                               dsp_format = DSP_AUDIOFORM_MS_16LE;
+                       break;
+               case 24:
+                       if (format->interleave == 2)
+                               dsp_format = DSP_AUDIOFORM_SS_24LE;
+                       else
+                               dsp_format = DSP_AUDIOFORM_MS_24LE;
+                       break;
+               case 32:
+                       if (format->interleave == 2)
+                               dsp_format = DSP_AUDIOFORM_SS_32LE;
+                       else
+                               dsp_format = DSP_AUDIOFORM_MS_32LE;
+                       break;
+               }
+       }
+       DE_ACT(("set_audio_format[%d] = %x\n", pipe_index, dsp_format));
+       chip->comm_page->audio_format[pipe_index] = cpu_to_le16(dsp_format);
+}
+
+
+
+/* start_transport starts transport for a set of pipes.
+The bits 1 in channel_mask specify what pipes to start. Only the bit of the
+first channel must be set, regardless its interleave.
+Same thing for pause_ and stop_ -trasport below. */
+static int start_transport(struct echoaudio *chip, u32 channel_mask,
+                          u32 cyclic_mask)
+{
+       DE_ACT(("start_transport %x\n", channel_mask));
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->comm_page->cmd_start |= cpu_to_le32(channel_mask);
+
+       if (chip->comm_page->cmd_start) {
+               clear_handshake(chip);
+               send_vector(chip, DSP_VC_START_TRANSFER);
+               if (wait_handshake(chip))
+                       return -EIO;
+               /* Keep track of which pipes are transporting */
+               chip->active_mask |= channel_mask;
+               chip->comm_page->cmd_start = 0;
+               return 0;
+       }
+
+       DE_ACT(("start_transport: No pipes to start!\n"));
+       return -EINVAL;
+}
+
+
+
+static int pause_transport(struct echoaudio *chip, u32 channel_mask)
+{
+       DE_ACT(("pause_transport %x\n", channel_mask));
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask);
+       chip->comm_page->cmd_reset = 0;
+       if (chip->comm_page->cmd_stop) {
+               clear_handshake(chip);
+               send_vector(chip, DSP_VC_STOP_TRANSFER);
+               if (wait_handshake(chip))
+                       return -EIO;
+               /* Keep track of which pipes are transporting */
+               chip->active_mask &= ~channel_mask;
+               chip->comm_page->cmd_stop = 0;
+               chip->comm_page->cmd_reset = 0;
+               return 0;
+       }
+
+       DE_ACT(("pause_transport: No pipes to stop!\n"));
+       return 0;
+}
+
+
+
+static int stop_transport(struct echoaudio *chip, u32 channel_mask)
+{
+       DE_ACT(("stop_transport %x\n", channel_mask));
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask);
+       chip->comm_page->cmd_reset |= cpu_to_le32(channel_mask);
+       if (chip->comm_page->cmd_reset) {
+               clear_handshake(chip);
+               send_vector(chip, DSP_VC_STOP_TRANSFER);
+               if (wait_handshake(chip))
+                       return -EIO;
+               /* Keep track of which pipes are transporting */
+               chip->active_mask &= ~channel_mask;
+               chip->comm_page->cmd_stop = 0;
+               chip->comm_page->cmd_reset = 0;
+               return 0;
+       }
+
+       DE_ACT(("stop_transport: No pipes to stop!\n"));
+       return 0;
+}
+
+
+
+static inline int is_pipe_allocated(struct echoaudio *chip, u16 pipe_index)
+{
+       return (chip->pipe_alloc_mask & (1 << pipe_index));
+}
+
+
+
+/* Stops everything and turns off the DSP. All pipes should be already
+stopped and unallocated. */
+static int rest_in_peace(struct echoaudio *chip)
+{
+       DE_ACT(("rest_in_peace() open=%x\n", chip->pipe_alloc_mask));
+
+       /* Stops all active pipes (just to be sure) */
+       stop_transport(chip, chip->active_mask);
+
+       set_meters_on(chip, FALSE);
+
+#ifdef ECHOCARD_HAS_MIDI
+       enable_midi_input(chip, FALSE);
+#endif
+
+       /* Go to sleep */
+       if (chip->dsp_code) {
+               /* Make load_firmware do a complete reload */
+               chip->dsp_code = NULL;
+               /* Put the DSP to sleep */
+               return send_vector(chip, DSP_VC_GO_COMATOSE);
+       }
+       return 0;
+}
+
+
+
+/* Fills the comm page with default values */
+static int init_dsp_comm_page(struct echoaudio *chip)
+{
+       /* Check if the compiler added extra padding inside the structure */
+       if (offsetof(struct comm_page, midi_output) != 0xbe0) {
+               DE_INIT(("init_dsp_comm_page() - Invalid struct comm_page structure\n"));
+               return -EPERM;
+       }
+
+       /* Init all the basic stuff */
+       chip->card_name = ECHOCARD_NAME;
+       chip->bad_board = TRUE; /* Set TRUE until DSP loaded */
+       chip->dsp_code = NULL;  /* Current DSP code not loaded */
+       chip->digital_mode = DIGITAL_MODE_NONE;
+       chip->input_clock = ECHO_CLOCK_INTERNAL;
+       chip->output_clock = ECHO_CLOCK_WORD;
+       chip->asic_loaded = FALSE;
+       memset(chip->comm_page, 0, sizeof(struct comm_page));
+
+       /* Init the comm page */
+       chip->comm_page->comm_size =
+               __constant_cpu_to_le32(sizeof(struct comm_page));
+       chip->comm_page->handshake = 0xffffffff;
+       chip->comm_page->midi_out_free_count =
+               __constant_cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE);
+       chip->comm_page->sample_rate = __constant_cpu_to_le32(44100);
+       chip->sample_rate = 44100;
+
+       /* Set line levels so we don't blast any inputs on startup */
+       memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE);
+       memset(chip->comm_page->vmixer, ECHOGAIN_MUTED, VMIXER_ARRAY_SIZE);
+
+       return 0;
+}
+
+
+
+/* This function initializes the several volume controls for busses and pipes.
+This MUST be called after the DSP is up and running ! */
+static int init_line_levels(struct echoaudio *chip)
+{
+       int st, i, o;
+
+       DE_INIT(("init_line_levels\n"));
+
+       /* Mute output busses */
+       for (i = 0; i < num_busses_out(chip); i++)
+               if ((st = set_output_gain(chip, i, ECHOGAIN_MUTED)))
+                       return st;
+       if ((st = update_output_line_level(chip)))
+               return st;
+
+#ifdef ECHOCARD_HAS_VMIXER
+       /* Mute the Vmixer */
+       for (i = 0; i < num_pipes_out(chip); i++)
+               for (o = 0; o < num_busses_out(chip); o++)
+                       if ((st = set_vmixer_gain(chip, o, i, ECHOGAIN_MUTED)))
+                               return st;
+       if ((st = update_vmixer_level(chip)))
+               return st;
+#endif /* ECHOCARD_HAS_VMIXER */
+
+#ifdef ECHOCARD_HAS_MONITOR
+       /* Mute the monitor mixer */
+       for (o = 0; o < num_busses_out(chip); o++)
+               for (i = 0; i < num_busses_in(chip); i++)
+                       if ((st = set_monitor_gain(chip, o, i, ECHOGAIN_MUTED)))
+                               return st;
+       if ((st = update_output_line_level(chip)))
+               return st;
+#endif /* ECHOCARD_HAS_MONITOR */
+
+#ifdef ECHOCARD_HAS_INPUT_GAIN
+       for (i = 0; i < num_busses_in(chip); i++)
+               if ((st = set_input_gain(chip, i, ECHOGAIN_MUTED)))
+                       return st;
+       if ((st = update_input_line_level(chip)))
+               return st;
+#endif /* ECHOCARD_HAS_INPUT_GAIN */
+
+       return 0;
+}
+
+
+
+/* This is low level part of the interrupt handler.
+It returns -1 if the IRQ is not ours, or N>=0 if it is, where N is the number
+of midi data in the input queue. */
+static int service_irq(struct echoaudio *chip)
+{
+       int st;
+
+       /* Read the DSP status register and see if this DSP generated this interrupt */
+       if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_IRQ) {
+               st = 0;
+#ifdef ECHOCARD_HAS_MIDI
+               /* Get and parse midi data if present */
+               if (chip->comm_page->midi_input[0])     /* The count is at index 0 */
+                       st = midi_service_irq(chip);    /* Returns how many midi bytes we received */
+#endif
+               /* Clear the hardware interrupt */
+               chip->comm_page->midi_input[0] = 0;
+               send_vector(chip, DSP_VC_ACK_INT);
+               return st;
+       }
+       return -1;
+}
+
+
+
+
+/******************************************************************************
+       Functions for opening and closing pipes
+ ******************************************************************************/
+
+/* allocate_pipes is used to reserve audio pipes for your exclusive use.
+The call will fail if some pipes are already allocated. */
+static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe,
+                         int pipe_index, int interleave)
+{
+       int i;
+       u32 channel_mask;
+       char is_cyclic;
+
+       DE_ACT(("allocate_pipes: ch=%d int=%d\n", pipe_index, interleave));
+
+       if (chip->bad_board)
+               return -EIO;
+
+       is_cyclic = 1;  /* This driver uses cyclic buffers only */
+
+       for (channel_mask = i = 0; i < interleave; i++)
+               channel_mask |= 1 << (pipe_index + i);
+       if (chip->pipe_alloc_mask & channel_mask) {
+               DE_ACT(("allocate_pipes: channel already open\n"));
+               return -EAGAIN;
+       }
+
+       chip->comm_page->position[pipe_index] = 0;
+       chip->pipe_alloc_mask |= channel_mask;
+       if (is_cyclic)
+               chip->pipe_cyclic_mask |= channel_mask;
+       pipe->index = pipe_index;
+       pipe->interleave = interleave;
+       pipe->state = PIPE_STATE_STOPPED;
+
+       /* The counter register is where the DSP writes the 32 bit DMA
+       position for a pipe.  The DSP is constantly updating this value as
+       it moves data. The DMA counter is in units of bytes, not samples. */
+       pipe->dma_counter = &chip->comm_page->position[pipe_index];
+       *pipe->dma_counter = 0;
+       DE_ACT(("allocate_pipes: ok\n"));
+       return pipe_index;
+}
+
+
+
+static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe)
+{
+       u32 channel_mask;
+       int i;
+
+       DE_ACT(("free_pipes: Pipe %d\n", pipe->index));
+       snd_assert(is_pipe_allocated(chip, pipe->index), return -EINVAL);
+       snd_assert(pipe->state == PIPE_STATE_STOPPED, return -EINVAL);
+
+       for (channel_mask = i = 0; i < pipe->interleave; i++)
+               channel_mask |= 1 << (pipe->index + i);
+
+       chip->pipe_alloc_mask &= ~channel_mask;
+       chip->pipe_cyclic_mask &= ~channel_mask;
+       return 0;
+}
+
+
+
+/******************************************************************************
+       Functions for managing the scatter-gather list
+******************************************************************************/
+
+static int sglist_init(struct echoaudio *chip, struct audiopipe *pipe)
+{
+       pipe->sglist_head = 0;
+       memset(pipe->sgpage.area, 0, PAGE_SIZE);
+       chip->comm_page->sglist_addr[pipe->index].addr =
+               cpu_to_le32(pipe->sgpage.addr);
+       return 0;
+}
+
+
+
+static int sglist_add_mapping(struct echoaudio *chip, struct audiopipe *pipe,
+                               dma_addr_t address, size_t length)
+{
+       int head = pipe->sglist_head;
+       struct sg_entry *list = (struct sg_entry *)pipe->sgpage.area;
+
+       if (head < MAX_SGLIST_ENTRIES - 1) {
+               list[head].addr = cpu_to_le32(address);
+               list[head].size = cpu_to_le32(length);
+               pipe->sglist_head++;
+       } else {
+               DE_ACT(("SGlist: too many fragments\n"));
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+
+
+static inline int sglist_add_irq(struct echoaudio *chip, struct audiopipe *pipe)
+{
+       return sglist_add_mapping(chip, pipe, 0, 0);
+}
+
+
+
+static inline int sglist_wrap(struct echoaudio *chip, struct audiopipe *pipe)
+{
+       return sglist_add_mapping(chip, pipe, pipe->sgpage.addr, 0);
+}
diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h
new file mode 100644 (file)
index 0000000..e55ee00
--- /dev/null
@@ -0,0 +1,694 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+#ifndef _ECHO_DSP_
+#define _ECHO_DSP_
+
+
+/**** Echogals: Darla20, Gina20, Layla20, and Darla24 ****/
+#if defined(ECHOGALS_FAMILY)
+
+#define NUM_ASIC_TESTS         5
+#define READ_DSP_TIMEOUT       1000000L        /* one second */
+
+/**** Echo24: Gina24, Layla24, Mona, Mia, Mia-midi ****/
+#elif defined(ECHO24_FAMILY)
+
+#define DSP_56361                      /* Some Echo24 cards use the 56361 DSP */
+#define READ_DSP_TIMEOUT       100000L         /* .1 second */
+
+/**** 3G: Gina3G, Layla3G ****/
+#elif defined(ECHO3G_FAMILY)
+
+#define DSP_56361
+#define READ_DSP_TIMEOUT       100000L         /* .1 second */
+#define MIN_MTC_1X_RATE                32000
+
+/**** Indigo: Indigo, Indigo IO, Indigo DJ ****/
+#elif defined(INDIGO_FAMILY)
+
+#define DSP_56361
+#define READ_DSP_TIMEOUT       100000L         /* .1 second */
+
+#else
+
+#error No family is defined
+
+#endif
+
+
+
+/*
+ *
+ *  Max inputs and outputs
+ *
+ */
+
+#define DSP_MAXAUDIOINPUTS             16      /* Max audio input channels */
+#define DSP_MAXAUDIOOUTPUTS            16      /* Max audio output channels */
+#define DSP_MAXPIPES                   32      /* Max total pipes (input + output) */
+
+
+/*
+ *
+ * These are the offsets for the memory-mapped DSP registers; the DSP base
+ * address is treated as the start of a u32 array.
+ */
+
+#define CHI32_CONTROL_REG              4
+#define CHI32_STATUS_REG               5
+#define CHI32_VECTOR_REG               6
+#define CHI32_DATA_REG                 7
+
+
+/*
+ *
+ * Interesting bits within the DSP registers
+ *
+ */
+
+#define CHI32_VECTOR_BUSY              0x00000001
+#define CHI32_STATUS_REG_HF3           0x00000008
+#define CHI32_STATUS_REG_HF4           0x00000010
+#define CHI32_STATUS_REG_HF5           0x00000020
+#define CHI32_STATUS_HOST_READ_FULL    0x00000004
+#define CHI32_STATUS_HOST_WRITE_EMPTY  0x00000002
+#define CHI32_STATUS_IRQ               0x00000040
+
+
+/* 
+ *
+ * DSP commands sent via slave mode; these are sent to the DSP by write_dsp()
+ *
+ */
+
+#define DSP_FNC_SET_COMMPAGE_ADDR              0x02
+#define DSP_FNC_LOAD_LAYLA_ASIC                        0xa0
+#define DSP_FNC_LOAD_GINA24_ASIC               0xa0
+#define DSP_FNC_LOAD_MONA_PCI_CARD_ASIC                0xa0
+#define DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC     0xa0
+#define DSP_FNC_LOAD_MONA_EXTERNAL_ASIC                0xa1
+#define DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC     0xa1
+#define DSP_FNC_LOAD_3G_ASIC                   0xa0
+
+
+/*
+ *
+ * Defines to handle the MIDI input state engine; these are used to properly
+ * extract MIDI time code bytes and their timestamps from the MIDI input stream.
+ *
+ */
+
+#define MIDI_IN_STATE_NORMAL   0
+#define MIDI_IN_STATE_TS_HIGH  1
+#define MIDI_IN_STATE_TS_LOW   2
+#define MIDI_IN_STATE_F1_DATA  3
+#define MIDI_IN_SKIP_DATA      (-1)
+
+
+/*----------------------------------------------------------------------------
+
+Setting the sample rates on Layla24 is somewhat schizophrenic.
+
+For standard rates, it works exactly like Mona and Gina24.  That is, for
+8, 11.025, 16, 22.05, 32, 44.1, 48, 88.2, and 96 kHz, you just set the
+appropriate bits in the control register and write the control register.
+
+In order to support MIDI time code sync (and possibly SMPTE LTC sync in
+the future), Layla24 also has "continuous sample rate mode".  In this mode,
+Layla24 can generate any sample rate between 25 and 50 kHz inclusive, or
+50 to 100 kHz inclusive for double speed mode.
+
+To use continuous mode:
+
+-Set the clock select bits in the control register to 0xe (see the #define
+ below)
+
+-Set double-speed mode if you want to use sample rates above 50 kHz
+
+-Write the control register as you would normally
+
+-Now, you need to set the frequency register. First, you need to determine the
+ value for the frequency register.  This is given by the following formula:
+
+frequency_reg = (LAYLA24_MAGIC_NUMBER / sample_rate) - 2
+
+Note the #define below for the magic number
+
+-Wait for the DSP handshake
+-Write the frequency_reg value to the .SampleRate field of the comm page
+-Send the vector command SET_LAYLA24_FREQUENCY_REG (see vmonkey.h)
+
+Once you have set the control register up for continuous mode, you can just
+write the frequency register to change the sample rate.  This could be
+used for MIDI time code sync. For MTC sync, the control register is set for
+continuous mode.  The driver then just keeps writing the
+SET_LAYLA24_FREQUENCY_REG command.
+
+-----------------------------------------------------------------------------*/
+
+#define LAYLA24_MAGIC_NUMBER                   677376000
+#define LAYLA24_CONTINUOUS_CLOCK               0x000e
+
+
+/*
+ *
+ * DSP vector commands
+ *
+ */
+
+#define DSP_VC_RESET                           0x80ff
+
+#ifndef DSP_56361
+
+#define DSP_VC_ACK_INT                         0x8073
+#define DSP_VC_SET_VMIXER_GAIN                 0x0000  /* Not used, only for compile */
+#define DSP_VC_START_TRANSFER                  0x0075  /* Handshke rqd. */
+#define DSP_VC_METERS_ON                       0x0079
+#define DSP_VC_METERS_OFF                      0x007b
+#define DSP_VC_UPDATE_OUTVOL                   0x007d  /* Handshke rqd. */
+#define DSP_VC_UPDATE_INGAIN                   0x007f  /* Handshke rqd. */
+#define DSP_VC_ADD_AUDIO_BUFFER                        0x0081  /* Handshke rqd. */
+#define DSP_VC_TEST_ASIC                       0x00eb
+#define DSP_VC_UPDATE_CLOCKS                   0x00ef  /* Handshke rqd. */
+#define DSP_VC_SET_LAYLA_SAMPLE_RATE           0x00f1  /* Handshke rqd. */
+#define DSP_VC_SET_GD_AUDIO_STATE              0x00f1  /* Handshke rqd. */
+#define DSP_VC_WRITE_CONTROL_REG               0x00f1  /* Handshke rqd. */
+#define DSP_VC_MIDI_WRITE                      0x00f5  /* Handshke rqd. */
+#define DSP_VC_STOP_TRANSFER                   0x00f7  /* Handshke rqd. */
+#define DSP_VC_UPDATE_FLAGS                    0x00fd  /* Handshke rqd. */
+#define DSP_VC_GO_COMATOSE                     0x00f9
+
+#else /* !DSP_56361 */
+
+/* Vector commands for families that use either the 56301 or 56361 */
+#define DSP_VC_ACK_INT                         0x80F5
+#define DSP_VC_SET_VMIXER_GAIN                 0x00DB  /* Handshke rqd. */
+#define DSP_VC_START_TRANSFER                  0x00DD  /* Handshke rqd. */
+#define DSP_VC_METERS_ON                       0x00EF
+#define DSP_VC_METERS_OFF                      0x00F1
+#define DSP_VC_UPDATE_OUTVOL                   0x00E3  /* Handshke rqd. */
+#define DSP_VC_UPDATE_INGAIN                   0x00E5  /* Handshke rqd. */
+#define DSP_VC_ADD_AUDIO_BUFFER                        0x00E1  /* Handshke rqd. */
+#define DSP_VC_TEST_ASIC                       0x00ED
+#define DSP_VC_UPDATE_CLOCKS                   0x00E9  /* Handshke rqd. */
+#define DSP_VC_SET_LAYLA24_FREQUENCY_REG       0x00E9  /* Handshke rqd. */
+#define DSP_VC_SET_LAYLA_SAMPLE_RATE           0x00EB  /* Handshke rqd. */
+#define DSP_VC_SET_GD_AUDIO_STATE              0x00EB  /* Handshke rqd. */
+#define DSP_VC_WRITE_CONTROL_REG               0x00EB  /* Handshke rqd. */
+#define DSP_VC_MIDI_WRITE                      0x00E7  /* Handshke rqd. */
+#define DSP_VC_STOP_TRANSFER                   0x00DF  /* Handshke rqd. */
+#define DSP_VC_UPDATE_FLAGS                    0x00FB  /* Handshke rqd. */
+#define DSP_VC_GO_COMATOSE                     0x00d9
+
+#endif /* !DSP_56361 */
+
+
+/*
+ *
+ * Timeouts
+ *
+ */
+
+#define HANDSHAKE_TIMEOUT              20000   /* send_vector command timeout (20ms) */
+#define VECTOR_BUSY_TIMEOUT            100000  /* 100ms */
+#define MIDI_OUT_DELAY_USEC            2000    /* How long to wait after MIDI fills up */
+
+
+/*
+ *
+ * Flags for .Flags field in the comm page
+ *
+ */
+
+#define DSP_FLAG_MIDI_INPUT            0x0001  /* Enable MIDI input */
+#define DSP_FLAG_SPDIF_NONAUDIO                0x0002  /* Sets the "non-audio" bit
+                                                * in the S/PDIF out status
+                                                * bits.  Clear this flag for
+                                                * audio data;
+                                                * set it for AC3 or WMA or
+                                                * some such */
+#define DSP_FLAG_PROFESSIONAL_SPDIF    0x0008  /* 1 Professional, 0 Consumer */
+
+
+/*
+ *
+ * Clock detect bits reported by the DSP for Gina20, Layla20, Darla24, and Mia
+ *
+ */
+
+#define GLDM_CLOCK_DETECT_BIT_WORD     0x0002
+#define GLDM_CLOCK_DETECT_BIT_SUPER    0x0004
+#define GLDM_CLOCK_DETECT_BIT_SPDIF    0x0008
+#define GLDM_CLOCK_DETECT_BIT_ESYNC    0x0010
+
+
+/*
+ *
+ * Clock detect bits reported by the DSP for Gina24, Mona, and Layla24
+ *
+ */
+
+#define GML_CLOCK_DETECT_BIT_WORD96    0x0002
+#define GML_CLOCK_DETECT_BIT_WORD48    0x0004
+#define GML_CLOCK_DETECT_BIT_SPDIF48   0x0008
+#define GML_CLOCK_DETECT_BIT_SPDIF96   0x0010
+#define GML_CLOCK_DETECT_BIT_WORD      (GML_CLOCK_DETECT_BIT_WORD96 | GML_CLOCK_DETECT_BIT_WORD48)
+#define GML_CLOCK_DETECT_BIT_SPDIF     (GML_CLOCK_DETECT_BIT_SPDIF48 | GML_CLOCK_DETECT_BIT_SPDIF96)
+#define GML_CLOCK_DETECT_BIT_ESYNC     0x0020
+#define GML_CLOCK_DETECT_BIT_ADAT      0x0040
+
+
+/*
+ *
+ * Layla clock numbers to send to DSP
+ *
+ */
+
+#define LAYLA20_CLOCK_INTERNAL         0
+#define LAYLA20_CLOCK_SPDIF            1
+#define LAYLA20_CLOCK_WORD             2
+#define LAYLA20_CLOCK_SUPER            3
+
+
+/*
+ *
+ * Gina/Darla clock states
+ *
+ */
+
+#define GD_CLOCK_NOCHANGE              0
+#define GD_CLOCK_44                    1
+#define GD_CLOCK_48                    2
+#define GD_CLOCK_SPDIFIN               3
+#define GD_CLOCK_UNDEF                 0xff
+
+
+/*
+ *
+ * Gina/Darla S/PDIF status bits
+ *
+ */
+
+#define GD_SPDIF_STATUS_NOCHANGE       0
+#define GD_SPDIF_STATUS_44             1
+#define GD_SPDIF_STATUS_48             2
+#define GD_SPDIF_STATUS_UNDEF          0xff
+
+
+/*
+ *
+ * Layla20 output clocks
+ *
+ */
+
+#define LAYLA20_OUTPUT_CLOCK_SUPER     0
+#define LAYLA20_OUTPUT_CLOCK_WORD      1
+
+
+/****************************************************************************
+
+   Magic constants for the Darla24 hardware
+
+ ****************************************************************************/
+
+#define GD24_96000     0x0
+#define GD24_48000     0x1
+#define GD24_44100     0x2
+#define GD24_32000     0x3
+#define GD24_22050     0x4
+#define GD24_16000     0x5
+#define GD24_11025     0x6
+#define GD24_8000      0x7
+#define GD24_88200     0x8
+#define GD24_EXT_SYNC  0x9
+
+
+/*
+ *
+ * Return values from the DSP when ASIC is loaded
+ *
+ */
+
+#define ASIC_ALREADY_LOADED    0x1
+#define ASIC_NOT_LOADED                0x0
+
+
+/*
+ *
+ * DSP Audio formats
+ *
+ * These are the audio formats that the DSP can transfer
+ * via input and output pipes.  LE means little-endian,
+ * BE means big-endian.
+ *
+ * DSP_AUDIOFORM_MS_8   
+ *
+ *    8-bit mono unsigned samples.  For playback,
+ *    mono data is duplicated out the left and right channels
+ *    of the output bus.  The "MS" part of the name
+ *    means mono->stereo.
+ *
+ * DSP_AUDIOFORM_MS_16LE
+ *
+ *    16-bit signed little-endian mono samples.  Playback works
+ *    like the previous code.
+ *
+ * DSP_AUDIOFORM_MS_24LE
+ *
+ *    24-bit signed little-endian mono samples.  Data is packed
+ *    three bytes per sample; if you had two samples 0x112233 and 0x445566
+ *    they would be stored in memory like this: 33 22 11 66 55 44.
+ *
+ * DSP_AUDIOFORM_MS_32LE
+ * 
+ *    24-bit signed little-endian mono samples in a 32-bit 
+ *    container.  In other words, each sample is a 32-bit signed 
+ *    integer, where the actual audio data is left-justified 
+ *    in the 32 bits and only the 24 most significant bits are valid.
+ *
+ * DSP_AUDIOFORM_SS_8
+ * DSP_AUDIOFORM_SS_16LE
+ * DSP_AUDIOFORM_SS_24LE
+ * DSP_AUDIOFORM_SS_32LE
+ *
+ *    Like the previous ones, except now with stereo interleaved
+ *    data.  "SS" means stereo->stereo.
+ *
+ * DSP_AUDIOFORM_MM_32LE
+ *
+ *    Similar to DSP_AUDIOFORM_MS_32LE, except that the mono
+ *    data is not duplicated out both the left and right outputs.
+ *    This mode is used by the ASIO driver.  Here, "MM" means
+ *    mono->mono.
+ *
+ * DSP_AUDIOFORM_MM_32BE
+ *
+ *    Just like DSP_AUDIOFORM_MM_32LE, but now the data is
+ *    in big-endian format.
+ *
+ */
+
+#define DSP_AUDIOFORM_MS_8     0       /* 8 bit mono */
+#define DSP_AUDIOFORM_MS_16LE  1       /* 16 bit mono */
+#define DSP_AUDIOFORM_MS_24LE  2       /* 24 bit mono */
+#define DSP_AUDIOFORM_MS_32LE  3       /* 32 bit mono */
+#define DSP_AUDIOFORM_SS_8     4       /* 8 bit stereo */
+#define DSP_AUDIOFORM_SS_16LE  5       /* 16 bit stereo */
+#define DSP_AUDIOFORM_SS_24LE  6       /* 24 bit stereo */
+#define DSP_AUDIOFORM_SS_32LE  7       /* 32 bit stereo */
+#define DSP_AUDIOFORM_MM_32LE  8       /* 32 bit mono->mono little-endian */
+#define DSP_AUDIOFORM_MM_32BE  9       /* 32 bit mono->mono big-endian */
+#define DSP_AUDIOFORM_SS_32BE  10      /* 32 bit stereo big endian */
+#define DSP_AUDIOFORM_INVALID  0xFF    /* Invalid audio format */
+
+
+/*
+ *
+ * Super-interleave is defined as interleaving by 4 or more.  Darla20 and Gina20
+ * do not support super interleave.
+ *
+ * 16 bit, 24 bit, and 32 bit little endian samples are supported for super 
+ * interleave.  The interleave factor must be even.  16 - way interleave is the 
+ * current maximum, so you can interleave by 4, 6, 8, 10, 12, 14, and 16.
+ *
+ * The actual format code is derived by taking the define below and or-ing with
+ * the interleave factor.  So, 32 bit interleave by 6 is 0x86 and
+ * 16 bit interleave by 16 is (0x40 | 0x10) = 0x50.
+ *
+ */
+
+#define DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE    0x40
+#define DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE    0xc0
+#define DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE    0x80
+
+
+/*
+ *
+ * Gina24, Mona, and Layla24 control register defines
+ *
+ */
+
+#define GML_CONVERTER_ENABLE   0x0010
+#define GML_SPDIF_PRO_MODE     0x0020  /* Professional S/PDIF == 1,
+                                          consumer == 0 */
+#define GML_SPDIF_SAMPLE_RATE0 0x0040
+#define GML_SPDIF_SAMPLE_RATE1 0x0080
+#define GML_SPDIF_TWO_CHANNEL  0x0100  /* 1 == two channels,
+                                          0 == one channel */
+#define GML_SPDIF_NOT_AUDIO    0x0200
+#define GML_SPDIF_COPY_PERMIT  0x0400
+#define GML_SPDIF_24_BIT       0x0800  /* 1 == 24 bit, 0 == 20 bit */
+#define GML_ADAT_MODE          0x1000  /* 1 == ADAT mode, 0 == S/PDIF mode */
+#define GML_SPDIF_OPTICAL_MODE 0x2000  /* 1 == optical mode, 0 == RCA mode */
+#define GML_SPDIF_CDROM_MODE   0x3000  /* 1 == CDROM mode,
+                                        * 0 == RCA or optical mode */
+#define GML_DOUBLE_SPEED_MODE  0x4000  /* 1 == double speed,
+                                          0 == single speed */
+
+#define GML_DIGITAL_IN_AUTO_MUTE 0x800000
+
+#define GML_96KHZ              (0x0 | GML_DOUBLE_SPEED_MODE)
+#define GML_88KHZ              (0x1 | GML_DOUBLE_SPEED_MODE)
+#define GML_48KHZ              0x2
+#define GML_44KHZ              0x3
+#define GML_32KHZ              0x4
+#define GML_22KHZ              0x5
+#define GML_16KHZ              0x6
+#define GML_11KHZ              0x7
+#define GML_8KHZ               0x8
+#define GML_SPDIF_CLOCK                0x9
+#define GML_ADAT_CLOCK         0xA
+#define GML_WORD_CLOCK         0xB
+#define GML_ESYNC_CLOCK                0xC
+#define GML_ESYNCx2_CLOCK      0xD
+
+#define GML_CLOCK_CLEAR_MASK           0xffffbff0
+#define GML_SPDIF_RATE_CLEAR_MASK      (~(GML_SPDIF_SAMPLE_RATE0|GML_SPDIF_SAMPLE_RATE1))
+#define GML_DIGITAL_MODE_CLEAR_MASK    0xffffcfff
+#define GML_SPDIF_FORMAT_CLEAR_MASK    0xfffff01f
+
+
+/*
+ *
+ * Mia sample rate and clock setting constants
+ *
+ */
+
+#define MIA_32000      0x0040
+#define MIA_44100      0x0042
+#define MIA_48000      0x0041
+#define MIA_88200      0x0142
+#define MIA_96000      0x0141
+
+#define MIA_SPDIF      0x00000044
+#define MIA_SPDIF96    0x00000144
+
+#define MIA_MIDI_REV   1       /* Must be Mia rev 1 for MIDI support */
+
+
+/*
+ *
+ * 3G register bits
+ *
+ */
+
+#define E3G_CONVERTER_ENABLE   0x0010
+#define E3G_SPDIF_PRO_MODE     0x0020  /* Professional S/PDIF == 1,
+                                          consumer == 0 */
+#define E3G_SPDIF_SAMPLE_RATE0 0x0040
+#define E3G_SPDIF_SAMPLE_RATE1 0x0080
+#define E3G_SPDIF_TWO_CHANNEL  0x0100  /* 1 == two channels,
+                                          0 == one channel */
+#define E3G_SPDIF_NOT_AUDIO    0x0200
+#define E3G_SPDIF_COPY_PERMIT  0x0400
+#define E3G_SPDIF_24_BIT       0x0800  /* 1 == 24 bit, 0 == 20 bit */
+#define E3G_DOUBLE_SPEED_MODE  0x4000  /* 1 == double speed,
+                                          0 == single speed */
+#define E3G_PHANTOM_POWER      0x8000  /* 1 == phantom power on,
+                                          0 == phantom power off */
+
+#define E3G_96KHZ              (0x0 | E3G_DOUBLE_SPEED_MODE)
+#define E3G_88KHZ              (0x1 | E3G_DOUBLE_SPEED_MODE)
+#define E3G_48KHZ              0x2
+#define E3G_44KHZ              0x3
+#define E3G_32KHZ              0x4
+#define E3G_22KHZ              0x5
+#define E3G_16KHZ              0x6
+#define E3G_11KHZ              0x7
+#define E3G_8KHZ               0x8
+#define E3G_SPDIF_CLOCK                0x9
+#define E3G_ADAT_CLOCK         0xA
+#define E3G_WORD_CLOCK         0xB
+#define E3G_CONTINUOUS_CLOCK   0xE
+
+#define E3G_ADAT_MODE          0x1000
+#define E3G_SPDIF_OPTICAL_MODE 0x2000
+
+#define E3G_CLOCK_CLEAR_MASK           0xbfffbff0
+#define E3G_DIGITAL_MODE_CLEAR_MASK    0xffffcfff
+#define E3G_SPDIF_FORMAT_CLEAR_MASK    0xfffff01f
+
+/* Clock detect bits reported by the DSP */
+#define E3G_CLOCK_DETECT_BIT_WORD96    0x0001
+#define E3G_CLOCK_DETECT_BIT_WORD48    0x0002
+#define E3G_CLOCK_DETECT_BIT_SPDIF48   0x0004
+#define E3G_CLOCK_DETECT_BIT_ADAT      0x0004
+#define E3G_CLOCK_DETECT_BIT_SPDIF96   0x0008
+#define E3G_CLOCK_DETECT_BIT_WORD      (E3G_CLOCK_DETECT_BIT_WORD96|E3G_CLOCK_DETECT_BIT_WORD48)
+#define E3G_CLOCK_DETECT_BIT_SPDIF     (E3G_CLOCK_DETECT_BIT_SPDIF48|E3G_CLOCK_DETECT_BIT_SPDIF96)
+
+/* Frequency control register */
+#define E3G_MAGIC_NUMBER               677376000
+#define E3G_FREQ_REG_DEFAULT           (E3G_MAGIC_NUMBER / 48000 - 2)
+#define E3G_FREQ_REG_MAX               0xffff
+
+/* 3G external box types */
+#define E3G_GINA3G_BOX_TYPE            0x00
+#define E3G_LAYLA3G_BOX_TYPE           0x10
+#define E3G_ASIC_NOT_LOADED            0xffff
+#define E3G_BOX_TYPE_MASK              0xf0
+
+#define EXT_3GBOX_NC                   0x01
+#define EXT_3GBOX_NOT_SET              0x02
+
+
+/*
+ *
+ * Gina20 & Layla20 have input gain controls for the analog inputs;
+ * this is the magic number for the hardware that gives you 0 dB at -10.
+ *
+ */
+
+#define GL20_INPUT_GAIN_MAGIC_NUMBER   0xC8
+
+
+/*
+ *
+ * Defines how much time must pass between DSP load attempts
+ *
+ */
+
+#define DSP_LOAD_ATTEMPT_PERIOD                1000000L        /* One second */
+
+
+/*
+ *
+ * Size of arrays for the comm page.  MAX_PLAY_TAPS and MAX_REC_TAPS are
+ * no longer used, but the sizes must still be right for the DSP to see
+ * the comm page correctly.
+ *
+ */
+
+#define MONITOR_ARRAY_SIZE     0x180
+#define VMIXER_ARRAY_SIZE      0x40
+#define MIDI_OUT_BUFFER_SIZE   32
+#define MIDI_IN_BUFFER_SIZE    256
+#define MAX_PLAY_TAPS          168
+#define MAX_REC_TAPS           192
+#define DSP_MIDI_OUT_FIFO_SIZE 64
+
+
+/* sg_entry is a single entry for the scatter-gather list.  The array of struct
+sg_entry struct is read by the DSP, so all values must be little-endian. */
+
+#define MAX_SGLIST_ENTRIES 512
+
+struct sg_entry {
+       u32 addr;
+       u32 size;
+};
+
+
+/****************************************************************************
+
+  The comm page.  This structure is read and written by the DSP; the
+  DSP code is a firm believer in the byte offsets written in the comments
+  at the end of each line.  This structure should not be changed.
+
+  Any reads from or writes to this structure should be in little-endian format.
+
+ ****************************************************************************/
+
+struct comm_page {             /*                              Base    Length*/
+       u32 comm_size;          /* size of this object          0x000   4 */
+       u32 flags;              /* See Appendix A below         0x004   4 */
+       u32 unused;             /* Unused entry                 0x008   4 */
+       u32 sample_rate;        /* Card sample rate in Hz       0x00c   4 */
+       volatile u32 handshake; /* DSP command handshake        0x010   4 */
+       u32 cmd_start;          /* Chs. to start mask           0x014   4 */
+       u32 cmd_stop;           /* Chs. to stop mask            0x018   4 */
+       u32 cmd_reset;          /* Chs. to reset mask           0x01c   4 */
+       u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format    0x020   32*2 */
+       struct sg_entry sglist_addr[DSP_MAXPIPES];
+                               /* Chs. Physical sglist addrs   0x060   32*8 */
+       volatile u32 position[DSP_MAXPIPES];
+                               /* Positions for ea. ch.        0x160   32*4 */
+       volatile s8 vu_meter[DSP_MAXPIPES];
+                               /* VU meters                    0x1e0   32*1 */
+       volatile s8 peak_meter[DSP_MAXPIPES];
+                               /* Peak meters                  0x200   32*1 */
+       s8 line_out_level[DSP_MAXAUDIOOUTPUTS];
+                               /* Output gain                  0x220   16*1 */
+       s8 line_in_level[DSP_MAXAUDIOINPUTS];
+                               /* Input gain                   0x230   16*1 */
+       s8 monitors[MONITOR_ARRAY_SIZE];
+                               /* Monitor map                  0x240   0x180 */
+       u32 play_coeff[MAX_PLAY_TAPS];
+                       /* Gina/Darla play filters - obsolete   0x3c0   168*4 */
+       u32 rec_coeff[MAX_REC_TAPS];
+                       /* Gina/Darla record filters - obsolete 0x660   192*4 */
+       volatile u16 midi_input[MIDI_IN_BUFFER_SIZE];
+                       /* MIDI input data transfer buffer      0x960   256*2 */
+       u8 gd_clock_state;      /* Chg Gina/Darla clock state   0xb60   1 */
+       u8 gd_spdif_status;     /* Chg. Gina/Darla S/PDIF state 0xb61   1 */
+       u8 gd_resampler_state;  /* Should always be 3           0xb62   1 */
+       u8 filler2;             /*                              0xb63   1 */
+       u32 nominal_level_mask; /* -10 level enable mask        0xb64   4 */
+       u16 input_clock;        /* Chg. Input clock state       0xb68   2 */
+       u16 output_clock;       /* Chg. Output clock state      0xb6a   2 */
+       volatile u32 status_clocks;
+                               /* Current Input clock state    0xb6c   4 */
+       u32 ext_box_status;     /* External box status          0xb70   4 */
+       u32 cmd_add_buffer;     /* Pipes to add (obsolete)      0xb74   4 */
+       volatile u32 midi_out_free_count;
+                       /* # of bytes free in MIDI output FIFO  0xb78   4 */
+       u32 unused2;            /* Cyclic pipes                 0xb7c   4 */
+       u32 control_register;
+                       /* Mona, Gina24, Layla24, 3G ctrl reg   0xb80   4 */
+       u32 e3g_frq_register;   /* 3G frequency register        0xb84   4 */
+       u8 filler[24];          /* filler                       0xb88   24*1 */
+       s8 vmixer[VMIXER_ARRAY_SIZE];
+                               /* Vmixer levels                0xba0   64*1 */
+       u8 midi_output[MIDI_OUT_BUFFER_SIZE];
+                               /* MIDI output data             0xbe0   32*1 */
+};
+
+#endif /* _ECHO_DSP_ */
diff --git a/sound/pci/echoaudio/echoaudio_gml.c b/sound/pci/echoaudio/echoaudio_gml.c
new file mode 100644 (file)
index 0000000..3aa37e7
--- /dev/null
@@ -0,0 +1,198 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+/* These functions are common for Gina24, Layla24 and Mona cards */
+
+
+/* ASIC status check - some cards have one or two ASICs that need to be
+loaded.  Once that load is complete, this function is called to see if
+the load was successful.
+If this load fails, it does not necessarily mean that the hardware is
+defective - the external box may be disconnected or turned off. */
+static int check_asic_status(struct echoaudio *chip)
+{
+       u32 asic_status;
+
+       send_vector(chip, DSP_VC_TEST_ASIC);
+
+       /* The DSP will return a value to indicate whether or not the
+          ASIC is currently loaded */
+       if (read_dsp(chip, &asic_status) < 0) {
+               DE_INIT(("check_asic_status: failed on read_dsp\n"));
+               chip->asic_loaded = FALSE;
+               return -EIO;
+       }
+
+       chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED);
+       return chip->asic_loaded ? 0 : -EIO;
+}
+
+
+
+/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing
+the control register.  write_control_reg sends the new control register
+value to the DSP. */
+static int write_control_reg(struct echoaudio *chip, u32 value, char force)
+{
+       /* Handle the digital input auto-mute */
+       if (chip->digital_in_automute)
+               value |= GML_DIGITAL_IN_AUTO_MUTE;
+       else
+               value &= ~GML_DIGITAL_IN_AUTO_MUTE;
+
+       DE_ACT(("write_control_reg: 0x%x\n", value));
+
+       /* Write the control register */
+       value = cpu_to_le32(value);
+       if (value != chip->comm_page->control_register || force) {
+               if (wait_handshake(chip))
+                       return -EIO;
+               chip->comm_page->control_register = value;
+               clear_handshake(chip);
+               return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
+       }
+       return 0;
+}
+
+
+
+/* Gina24, Layla24, and Mona support digital input auto-mute.  If the digital
+input auto-mute is enabled, the DSP will only enable the digital inputs if
+the card is syncing to a valid clock on the ADAT or S/PDIF inputs.
+If the auto-mute is disabled, the digital inputs are enabled regardless of
+what the input clock is set or what is connected. */
+static int set_input_auto_mute(struct echoaudio *chip, int automute)
+{
+       DE_ACT(("set_input_auto_mute %d\n", automute));
+
+       chip->digital_in_automute = automute;
+
+       /* Re-set the input clock to the current value - indirectly causes
+       the auto-mute flag to be sent to the DSP */
+       return set_input_clock(chip, chip->input_clock);
+}
+
+
+
+/* S/PDIF coax / S/PDIF optical / ADAT - switch */
+static int set_digital_mode(struct echoaudio *chip, u8 mode)
+{
+       u8 previous_mode;
+       int err, i, o;
+
+       if (chip->bad_board)
+               return -EIO;
+
+       /* All audio channels must be closed before changing the digital mode */
+       snd_assert(!chip->pipe_alloc_mask, return -EAGAIN);
+
+       snd_assert(chip->digital_modes & (1 << mode), return -EINVAL);
+
+       previous_mode = chip->digital_mode;
+       err = dsp_set_digital_mode(chip, mode);
+
+       /* If we successfully changed the digital mode from or to ADAT,
+          then make sure all output, input and monitor levels are
+          updated by the DSP comm object. */
+       if (err >= 0 && previous_mode != mode &&
+           (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
+               spin_lock_irq(&chip->lock);
+               for (o = 0; o < num_busses_out(chip); o++)
+                       for (i = 0; i < num_busses_in(chip); i++)
+                               set_monitor_gain(chip, o, i,
+                                                chip->monitor_gain[o][i]);
+
+#ifdef ECHOCARD_HAS_INPUT_GAIN
+               for (i = 0; i < num_busses_in(chip); i++)
+                       set_input_gain(chip, i, chip->input_gain[i]);
+               update_input_line_level(chip);
+#endif
+
+               for (o = 0; o < num_busses_out(chip); o++)
+                       set_output_gain(chip, o, chip->output_gain[o]);
+               update_output_line_level(chip);
+               spin_unlock_irq(&chip->lock);
+       }
+
+       return err;
+}
+
+
+
+/* Set the S/PDIF output format */
+static int set_professional_spdif(struct echoaudio *chip, char prof)
+{
+       u32 control_reg;
+       int err;
+
+       /* Clear the current S/PDIF flags */
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK;
+
+       /* Set the new S/PDIF flags depending on the mode */
+       control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT |
+               GML_SPDIF_COPY_PERMIT;
+       if (prof) {
+               /* Professional mode */
+               control_reg |= GML_SPDIF_PRO_MODE;
+
+               switch (chip->sample_rate) {
+               case 32000:
+                       control_reg |= GML_SPDIF_SAMPLE_RATE0 |
+                               GML_SPDIF_SAMPLE_RATE1;
+                       break;
+               case 44100:
+                       control_reg |= GML_SPDIF_SAMPLE_RATE0;
+                       break;
+               case 48000:
+                       control_reg |= GML_SPDIF_SAMPLE_RATE1;
+                       break;
+               }
+       } else {
+               /* Consumer mode */
+               switch (chip->sample_rate) {
+               case 32000:
+                       control_reg |= GML_SPDIF_SAMPLE_RATE0 |
+                               GML_SPDIF_SAMPLE_RATE1;
+                       break;
+               case 48000:
+                       control_reg |= GML_SPDIF_SAMPLE_RATE1;
+                       break;
+               }
+       }
+
+       if ((err = write_control_reg(chip, control_reg, FALSE)))
+               return err;
+       chip->professional_spdif = prof;
+       DE_ACT(("set_professional_spdif to %s\n",
+               prof ? "Professional" : "Consumer"));
+       return 0;
+}
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
new file mode 100644 (file)
index 0000000..29d6d12
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHOGALS_FAMILY
+#define ECHOCARD_GINA20
+#define ECHOCARD_NAME "Gina20"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_INPUT_GAIN
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_ADAT      FALSE
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 2 */
+#define PX_ANALOG_IN   10      /* 2 */
+#define PX_DIGITAL_IN  12      /* 2 */
+#define PX_NUM         14
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 8 */
+#define BX_DIGITAL_OUT 8       /* 2 */
+#define BX_ANALOG_IN   10      /* 2 */
+#define BX_DIGITAL_IN  12      /* 2 */
+#define BX_NUM         14
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_GINA20_DSP  0
+
+static const struct firmware card_fw[] = {
+       {0, "gina20_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0},      /* DSP 56301 Gina20 rev.0 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+       .rate_min = 44100,
+       .rate_max = 48000,
+       .channels_min = 1,
+       .channels_max = 2,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+
+#include "gina20_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c
new file mode 100644 (file)
index 0000000..2757c89
--- /dev/null
@@ -0,0 +1,215 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int update_flags(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Gina20\n"));
+       snd_assert((subdevice_id & 0xfff0) == GINA20, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_GINA20_DSP];
+       chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
+       chip->clock_state = GD_CLOCK_UNDEF;
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
+               ECHO_CLOCK_BIT_SPDIF;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       err = set_professional_spdif(chip, TRUE);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock
+          detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
+               clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+
+       return clock_bits;
+}
+
+
+
+/* The Gina20 has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u8 clock_state, spdif_status;
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       switch (rate) {
+       case 44100:
+               clock_state = GD_CLOCK_44;
+               spdif_status = GD_SPDIF_STATUS_44;
+               break;
+       case 48000:
+               clock_state = GD_CLOCK_48;
+               spdif_status = GD_SPDIF_STATUS_48;
+               break;
+       default:
+               clock_state = GD_CLOCK_NOCHANGE;
+               spdif_status = GD_SPDIF_STATUS_NOCHANGE;
+               break;
+       }
+
+       if (chip->clock_state == clock_state)
+               clock_state = GD_CLOCK_NOCHANGE;
+       if (spdif_status == chip->spdif_status)
+               spdif_status = GD_SPDIF_STATUS_NOCHANGE;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);
+       chip->comm_page->gd_clock_state = clock_state;
+       chip->comm_page->gd_spdif_status = spdif_status;
+       chip->comm_page->gd_resampler_state = 3;        /* magic number - should always be 3 */
+
+       /* Save the new audio state if it changed */
+       if (clock_state != GD_CLOCK_NOCHANGE)
+               chip->clock_state = clock_state;
+       if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
+               chip->spdif_status = spdif_status;
+       chip->sample_rate = rate;
+
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       DE_ACT(("set_input_clock:\n"));
+
+       switch (clock) {
+       case ECHO_CLOCK_INTERNAL:
+               /* Reset the audio state to unknown (just in case) */
+               chip->clock_state = GD_CLOCK_UNDEF;
+               chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
+               set_sample_rate(chip, chip->sample_rate);
+               chip->input_clock = clock;
+               DE_ACT(("Set Gina clock to INTERNAL\n"));
+               break;
+       case ECHO_CLOCK_SPDIF:
+               chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN;
+               chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE;
+               clear_handshake(chip);
+               send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
+               chip->clock_state = GD_CLOCK_SPDIFIN;
+               DE_ACT(("Set Gina20 clock to SPDIF\n"));
+               chip->input_clock = clock;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+
+/* Set input bus gain (one unit is 0.5dB !) */
+static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
+{
+       snd_assert(input < num_busses_in(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->input_gain[input] = gain;
+       gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
+       chip->comm_page->line_in_level[input] = gain;
+       return 0;
+}
+
+
+
+/* Tell the DSP to reread the flags from the comm page */
+static int update_flags(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_FLAGS);
+}
+
+
+
+static int set_professional_spdif(struct echoaudio *chip, char prof)
+{
+       DE_ACT(("set_professional_spdif %d\n", prof));
+       if (prof)
+               chip->comm_page->flags |=
+                       __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+       else
+               chip->comm_page->flags &=
+                       ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+       chip->professional_spdif = prof;
+       return update_flags(chip);
+}
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
new file mode 100644 (file)
index 0000000..e464d72
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHO24_FAMILY
+#define ECHOCARD_GINA24
+#define ECHOCARD_NAME "Gina24"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_ASIC
+#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
+#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_ADAT      6
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 8 */
+#define PX_ANALOG_IN   16      /* 2 */
+#define PX_DIGITAL_IN  18      /* 8 */
+#define PX_NUM         26
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 8 */
+#define BX_DIGITAL_OUT 8       /* 8 */
+#define BX_ANALOG_IN   16      /* 2 */
+#define BX_DIGITAL_IN  18      /* 8 */
+#define BX_NUM         26
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER          0
+#define FW_GINA24_301_DSP      1
+#define FW_GINA24_361_DSP      2
+#define FW_GINA24_301_ASIC     3
+#define FW_GINA24_361_ASIC     4
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "gina24_301_dsp.fw"},
+       {0, "gina24_361_dsp.fw"},
+       {0, "gina24_301_asic.fw"},
+       {0, "gina24_361_asic.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0},      /* DSP 56301 Gina24 rev.0 */
+       {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0},      /* DSP 56301 Gina24 rev.1 */
+       {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0},      /* DSP 56361 Gina24 rev.0 */
+       {0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0},      /* DSP 56361 Gina24 rev.1 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_8000_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions.
+       220 ~= (512 - 1 - (BUFFER_BYTES_MAX / PAGE_SIZE)) / 2 */
+};
+
+#include "gina24_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio_gml.c"
+#include "echoaudio.c"
diff --git a/sound/pci/echoaudio/gina24_dsp.c b/sound/pci/echoaudio/gina24_dsp.c
new file mode 100644 (file)
index 0000000..144fc56
--- /dev/null
@@ -0,0 +1,346 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int write_control_reg(struct echoaudio *chip, u32 value, char force);
+static int set_input_clock(struct echoaudio *chip, u16 clock);
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int set_digital_mode(struct echoaudio *chip, u8 mode);
+static int load_asic_generic(struct echoaudio *chip, u32 cmd,
+                            const struct firmware *asic);
+static int check_asic_status(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Gina24\n"));
+       snd_assert((subdevice_id & 0xfff0) == GINA24, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->input_clock_types =
+               ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
+               ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 |
+               ECHO_CLOCK_BIT_ADAT;
+       chip->professional_spdif = FALSE;
+       chip->digital_in_automute = TRUE;
+       chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
+
+       /* Gina24 comes in both '301 and '361 flavors */
+       if (chip->device_id == DEVICE_ID_56361) {
+               chip->dsp_code_to_load = &card_fw[FW_GINA24_361_DSP];
+               chip->digital_modes =
+                       ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
+                       ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
+                       ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
+       } else {
+               chip->dsp_code_to_load = &card_fw[FW_GINA24_301_DSP];
+               chip->digital_modes =
+                       ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
+                       ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
+                       ECHOCAPS_HAS_DIGITAL_MODE_ADAT |
+                       ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM;
+       }
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+       err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA);
+       snd_assert(err >= 0, return err);
+       err = set_professional_spdif(chip, TRUE);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock
+          detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
+               clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
+               clock_bits |= ECHO_CLOCK_BIT_ADAT;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC)
+               clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;
+
+       return clock_bits;
+}
+
+
+
+/* Gina24 has an ASIC on the PCI card which must be loaded for anything
+interesting to happen. */
+static int load_asic(struct echoaudio *chip)
+{
+       u32 control_reg;
+       int err;
+       const struct firmware *fw;
+
+       if (chip->asic_loaded)
+               return 1;
+
+       /* Give the DSP a few milliseconds to settle down */
+       mdelay(10);
+
+       /* Pick the correct ASIC for '301 or '361 Gina24 */
+       if (chip->device_id == DEVICE_ID_56361)
+               fw = &card_fw[FW_GINA24_361_ASIC];
+       else
+               fw = &card_fw[FW_GINA24_301_ASIC];
+
+       if ((err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, fw)) < 0)
+               return err;
+
+       chip->asic_code = fw;
+
+       /* Now give the new ASIC a little time to set up */
+       mdelay(10);
+       /* See if it worked */
+       err = check_asic_status(chip);
+
+       /* Set up the control register if the load succeeded -
+          48 kHz, internal clock, S/PDIF RCA mode */
+       if (!err) {
+               control_reg = GML_CONVERTER_ENABLE | GML_48KHZ;
+               err = write_control_reg(chip, control_reg, TRUE);
+       }
+       DE_INIT(("load_asic() done\n"));
+       return err;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg, clock;
+
+       snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT,
+                  return -EINVAL);
+
+       /* Only set the clock for internal mode. */
+       if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
+               DE_ACT(("set_sample_rate: Cannot set sample rate - "
+                       "clock not set to CLK_CLOCKININTERNAL\n"));
+               /* Save the rate anyhow */
+               chip->comm_page->sample_rate = cpu_to_le32(rate);
+               chip->sample_rate = rate;
+               return 0;
+       }
+
+       clock = 0;
+
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
+
+       switch (rate) {
+       case 96000:
+               clock = GML_96KHZ;
+               break;
+       case 88200:
+               clock = GML_88KHZ;
+               break;
+       case 48000:
+               clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
+               break;
+       case 44100:
+               clock = GML_44KHZ;
+               /* Professional mode ? */
+               if (control_reg & GML_SPDIF_PRO_MODE)
+                       clock |= GML_SPDIF_SAMPLE_RATE0;
+               break;
+       case 32000:
+               clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
+                       GML_SPDIF_SAMPLE_RATE1;
+               break;
+       case 22050:
+               clock = GML_22KHZ;
+               break;
+       case 16000:
+               clock = GML_16KHZ;
+               break;
+       case 11025:
+               clock = GML_11KHZ;
+               break;
+       case 8000:
+               clock = GML_8KHZ;
+               break;
+       default:
+               DE_ACT(("set_sample_rate: %d invalid!\n", rate));
+               return -EINVAL;
+       }
+
+       control_reg |= clock;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
+       chip->sample_rate = rate;
+       DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock));
+
+       return write_control_reg(chip, control_reg, FALSE);
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       u32 control_reg, clocks_from_dsp;
+
+       DE_ACT(("set_input_clock:\n"));
+
+       /* Mask off the clock select bits */
+       control_reg = le32_to_cpu(chip->comm_page->control_register) &
+               GML_CLOCK_CLEAR_MASK;
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       switch (clock) {
+       case ECHO_CLOCK_INTERNAL:
+               DE_ACT(("Set Gina24 clock to INTERNAL\n"));
+               chip->input_clock = ECHO_CLOCK_INTERNAL;
+               return set_sample_rate(chip, chip->sample_rate);
+       case ECHO_CLOCK_SPDIF:
+               if (chip->digital_mode == DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               DE_ACT(("Set Gina24 clock to SPDIF\n"));
+               control_reg |= GML_SPDIF_CLOCK;
+               if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96)
+                       control_reg |= GML_DOUBLE_SPEED_MODE;
+               else
+                       control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_ADAT:
+               if (chip->digital_mode != DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               DE_ACT(("Set Gina24 clock to ADAT\n"));
+               control_reg |= GML_ADAT_CLOCK;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_ESYNC:
+               DE_ACT(("Set Gina24 clock to ESYNC\n"));
+               control_reg |= GML_ESYNC_CLOCK;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_ESYNC96:
+               DE_ACT(("Set Gina24 clock to ESYNC96\n"));
+               control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE;
+               break;
+       default:
+               DE_ACT(("Input clock 0x%x not supported for Gina24\n", clock));
+               return -EINVAL;
+       }
+
+       chip->input_clock = clock;
+       return write_control_reg(chip, control_reg, TRUE);
+}
+
+
+
+static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
+{
+       u32 control_reg;
+       int err, incompatible_clock;
+
+       /* Set clock to "internal" if it's not compatible with the new mode */
+       incompatible_clock = FALSE;
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+       case DIGITAL_MODE_SPDIF_CDROM:
+       case DIGITAL_MODE_SPDIF_RCA:
+               if (chip->input_clock == ECHO_CLOCK_ADAT)
+                       incompatible_clock = TRUE;
+               break;
+       case DIGITAL_MODE_ADAT:
+               if (chip->input_clock == ECHO_CLOCK_SPDIF)
+                       incompatible_clock = TRUE;
+               break;
+       default:
+               DE_ACT(("Digital mode not supported: %d\n", mode));
+               return -EINVAL;
+       }
+
+       spin_lock_irq(&chip->lock);
+
+       if (incompatible_clock) {       /* Switch to 48KHz, internal */
+               chip->sample_rate = 48000;
+               set_input_clock(chip, ECHO_CLOCK_INTERNAL);
+       }
+
+       /* Clear the current digital mode */
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
+
+       /* Tweak the control reg */
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+               control_reg |= GML_SPDIF_OPTICAL_MODE;
+               break;
+       case DIGITAL_MODE_SPDIF_CDROM:
+               /* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */
+               if (chip->device_id == DEVICE_ID_56301)
+                       control_reg |= GML_SPDIF_CDROM_MODE;
+               break;
+       case DIGITAL_MODE_SPDIF_RCA:
+               /* GML_SPDIF_OPTICAL_MODE bit cleared */
+               break;
+       case DIGITAL_MODE_ADAT:
+               control_reg |= GML_ADAT_MODE;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       }
+
+       err = write_control_reg(chip, control_reg, TRUE);
+       spin_unlock_irq(&chip->lock);
+       if (err < 0)
+               return err;
+       chip->digital_mode = mode;
+
+       DE_ACT(("set_digital_mode to %d\n", chip->digital_mode));
+       return incompatible_clock;
+}
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
new file mode 100644 (file)
index 0000000..bfd2467
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define INDIGO_FAMILY
+#define ECHOCARD_INDIGO
+#define ECHOCARD_NAME "Indigo"
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_VMIXER
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 0 */
+#define PX_ANALOG_IN   8       /* 0 */
+#define PX_DIGITAL_IN  8       /* 0 */
+#define PX_NUM         8
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 2 */
+#define BX_DIGITAL_OUT 2       /* 0 */
+#define BX_ANALOG_IN   2       /* 0 */
+#define BX_DIGITAL_IN  2       /* 0 */
+#define BX_NUM         2
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER  0
+#define FW_INDIGO_DSP  1
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "indigo_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0},      /* Indigo */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_32000 |
+                       SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 32000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+};
+
+#include "indigo_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
+
diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c
new file mode 100644 (file)
index 0000000..d6ac773
--- /dev/null
@@ -0,0 +1,170 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain);
+static int update_vmixer_level(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Indigo\n"));
+       snd_assert((subdevice_id & 0xfff0) == INDIGO, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_INDIGO_DSP];
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       /* Default routing of the virtual channels: all vchannels are routed
+       to the stereo output */
+       set_vmixer_gain(chip, 0, 0, 0);
+       set_vmixer_gain(chip, 1, 1, 0);
+       set_vmixer_gain(chip, 0, 2, 0);
+       set_vmixer_gain(chip, 1, 3, 0);
+       set_vmixer_gain(chip, 0, 4, 0);
+       set_vmixer_gain(chip, 1, 5, 0);
+       set_vmixer_gain(chip, 0, 6, 0);
+       set_vmixer_gain(chip, 1, 7, 0);
+       err = update_vmixer_level(chip);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       return ECHO_CLOCK_BIT_INTERNAL;
+}
+
+
+
+/* The Indigo has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg;
+
+       switch (rate) {
+       case 96000:
+               control_reg = MIA_96000;
+               break;
+       case 88200:
+               control_reg = MIA_88200;
+               break;
+       case 48000:
+               control_reg = MIA_48000;
+               break;
+       case 44100:
+               control_reg = MIA_44100;
+               break;
+       case 32000:
+               control_reg = MIA_32000;
+               break;
+       default:
+               DE_ACT(("set_sample_rate: %d invalid!\n", rate));
+               return -EINVAL;
+       }
+
+       /* Set the control register if it has changed */
+       if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
+               if (wait_handshake(chip))
+                       return -EIO;
+
+               chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
+               chip->comm_page->control_register = cpu_to_le32(control_reg);
+               chip->sample_rate = rate;
+
+               clear_handshake(chip);
+               return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+       }
+       return 0;
+}
+
+
+
+/* This function routes the sound from a virtual channel to a real output */
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain)
+{
+       int index;
+
+       snd_assert(pipe < num_pipes_out(chip) &&
+                  output < num_busses_out(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->vmixer_gain[output][pipe] = gain;
+       index = output * num_pipes_out(chip) + pipe;
+       chip->comm_page->vmixer[index] = gain;
+
+       DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
+       return 0;
+}
+
+
+
+/* Tell the DSP to read and update virtual mixer levels in comm page. */
+static int update_vmixer_level(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
+}
+
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
new file mode 100644 (file)
index 0000000..8ed7ff1
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define INDIGO_FAMILY
+#define ECHOCARD_INDIGO_DJ
+#define ECHOCARD_NAME "Indigo DJ"
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_VMIXER
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 0 */
+#define PX_ANALOG_IN   8       /* 0 */
+#define PX_DIGITAL_IN  8       /* 0 */
+#define PX_NUM         8
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 4 */
+#define BX_DIGITAL_OUT 4       /* 0 */
+#define BX_ANALOG_IN   4       /* 0 */
+#define BX_DIGITAL_IN  4       /* 0 */
+#define BX_NUM         4
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER          0
+#define FW_INDIGO_DJ_DSP       1
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "indigo_dj_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0},      /* Indigo DJ*/
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_32000 |
+                       SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 32000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 4,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+};
+
+#include "indigodj_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
+
diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c
new file mode 100644 (file)
index 0000000..500e150
--- /dev/null
@@ -0,0 +1,170 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain);
+static int update_vmixer_level(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Indigo DJ\n"));
+       snd_assert((subdevice_id & 0xfff0) == INDIGO_DJ, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_INDIGO_DJ_DSP];
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       /* Default routing of the virtual channels: vchannels 0-3 and
+       vchannels 4-7 are routed to real channels 0-4 */
+       set_vmixer_gain(chip, 0, 0, 0);
+       set_vmixer_gain(chip, 1, 1, 0);
+       set_vmixer_gain(chip, 2, 2, 0);
+       set_vmixer_gain(chip, 3, 3, 0);
+       set_vmixer_gain(chip, 0, 4, 0);
+       set_vmixer_gain(chip, 1, 5, 0);
+       set_vmixer_gain(chip, 2, 6, 0);
+       set_vmixer_gain(chip, 3, 7, 0);
+       err = update_vmixer_level(chip);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       return ECHO_CLOCK_BIT_INTERNAL;
+}
+
+
+
+/* The IndigoDJ has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg;
+
+       switch (rate) {
+       case 96000:
+               control_reg = MIA_96000;
+               break;
+       case 88200:
+               control_reg = MIA_88200;
+               break;
+       case 48000:
+               control_reg = MIA_48000;
+               break;
+       case 44100:
+               control_reg = MIA_44100;
+               break;
+       case 32000:
+               control_reg = MIA_32000;
+               break;
+       default:
+               DE_ACT(("set_sample_rate: %d invalid!\n", rate));
+               return -EINVAL;
+       }
+
+       /* Set the control register if it has changed */
+       if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
+               if (wait_handshake(chip))
+                       return -EIO;
+
+               chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
+               chip->comm_page->control_register = cpu_to_le32(control_reg);
+               chip->sample_rate = rate;
+
+               clear_handshake(chip);
+               return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+       }
+       return 0;
+}
+
+
+
+/* This function routes the sound from a virtual channel to a real output */
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain)
+{
+       int index;
+
+       snd_assert(pipe < num_pipes_out(chip) &&
+                  output < num_busses_out(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->vmixer_gain[output][pipe] = gain;
+       index = output * num_pipes_out(chip) + pipe;
+       chip->comm_page->vmixer[index] = gain;
+
+       DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
+       return 0;
+}
+
+
+
+/* Tell the DSP to read and update virtual mixer levels in comm page. */
+static int update_vmixer_level(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
+}
+
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
new file mode 100644 (file)
index 0000000..a8788e9
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define INDIGO_FAMILY
+#define ECHOCARD_INDIGO_IO
+#define ECHOCARD_NAME "Indigo IO"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_VMIXER
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 0 */
+#define PX_ANALOG_IN   8       /* 2 */
+#define PX_DIGITAL_IN  10      /* 0 */
+#define PX_NUM         10
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 2 */
+#define BX_DIGITAL_OUT 2       /* 0 */
+#define BX_ANALOG_IN   2       /* 2 */
+#define BX_DIGITAL_IN  4       /* 0 */
+#define BX_NUM         4
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER          0
+#define FW_INDIGO_IO_DSP       1
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "indigo_io_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0},      /* Indigo IO*/
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_32000 |
+                       SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 32000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+};
+
+#include "indigoio_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
+
diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c
new file mode 100644 (file)
index 0000000..f3ad13d
--- /dev/null
@@ -0,0 +1,141 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain);
+static int update_vmixer_level(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Indigo IO\n"));
+       snd_assert((subdevice_id & 0xfff0) == INDIGO_IO, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_INDIGO_IO_DSP];
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       /* Default routing of the virtual channels: all vchannels are routed
+       to the stereo output */
+       set_vmixer_gain(chip, 0, 0, 0);
+       set_vmixer_gain(chip, 1, 1, 0);
+       set_vmixer_gain(chip, 0, 2, 0);
+       set_vmixer_gain(chip, 1, 3, 0);
+       set_vmixer_gain(chip, 0, 4, 0);
+       set_vmixer_gain(chip, 1, 5, 0);
+       set_vmixer_gain(chip, 0, 6, 0);
+       set_vmixer_gain(chip, 1, 7, 0);
+       err = update_vmixer_level(chip);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       return ECHO_CLOCK_BIT_INTERNAL;
+}
+
+
+
+/* The IndigoIO has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->sample_rate = rate;
+       chip->comm_page->sample_rate = cpu_to_le32(rate);
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+}
+
+
+
+/* This function routes the sound from a virtual channel to a real output */
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain)
+{
+       int index;
+
+       snd_assert(pipe < num_pipes_out(chip) &&
+                  output < num_busses_out(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->vmixer_gain[output][pipe] = gain;
+       index = output * num_pipes_out(chip) + pipe;
+       chip->comm_page->vmixer[index] = gain;
+
+       DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
+       return 0;
+}
+
+
+
+/* Tell the DSP to read and update virtual mixer levels in comm page. */
+static int update_vmixer_level(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
+}
+
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
new file mode 100644 (file)
index 0000000..e503d74
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHOGALS_FAMILY
+#define ECHOCARD_LAYLA20
+#define ECHOCARD_NAME "Layla20"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_ASIC
+#define ECHOCARD_HAS_INPUT_GAIN
+#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_ADAT      FALSE
+#define ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH
+#define ECHOCARD_HAS_MIDI
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 10 */
+#define PX_DIGITAL_OUT 10      /*  2 */
+#define PX_ANALOG_IN   12      /*  8 */
+#define PX_DIGITAL_IN  20      /*  2 */
+#define PX_NUM         22
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 10 */
+#define BX_DIGITAL_OUT 10      /*  2 */
+#define BX_ANALOG_IN   12      /*  8 */
+#define BX_DIGITAL_IN  20      /*  2 */
+#define BX_NUM         22
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_LAYLA20_DSP 0
+#define FW_LAYLA20_ASIC        1
+
+static const struct firmware card_fw[] = {
+       {0, "layla20_dsp.fw"},
+       {0, "layla20_asic.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0},      /* DSP 56301 Layla20 rev.0 */
+       {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0},      /* DSP 56301 Layla20 rev.1 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS,
+       .rate_min = 8000,
+       .rate_max = 50000,
+       .channels_min = 1,
+       .channels_max = 10,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+#include "layla20_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
+#include "midi.c"
diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c
new file mode 100644 (file)
index 0000000..990c9a6
--- /dev/null
@@ -0,0 +1,290 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int read_dsp(struct echoaudio *chip, u32 *data);
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int load_asic_generic(struct echoaudio *chip, u32 cmd,
+                            const struct firmware *asic);
+static int check_asic_status(struct echoaudio *chip);
+static int update_flags(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Layla20\n"));
+       snd_assert((subdevice_id & 0xfff0) == LAYLA20, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->has_midi = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_LAYLA20_DSP];
+       chip->input_clock_types =
+               ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
+               ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER;
+       chip->output_clock_types =
+               ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       err = set_professional_spdif(chip, TRUE);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
+               clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+
+       if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) {
+               if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER)
+                       clock_bits |= ECHO_CLOCK_BIT_SUPER;
+               else
+                       clock_bits |= ECHO_CLOCK_BIT_WORD;
+       }
+
+       return clock_bits;
+}
+
+
+
+/* ASIC status check - some cards have one or two ASICs that need to be
+loaded.  Once that load is complete, this function is called to see if
+the load was successful.
+If this load fails, it does not necessarily mean that the hardware is
+defective - the external box may be disconnected or turned off.
+This routine sometimes fails for Layla20; for Layla20, the loop runs
+5 times and succeeds if it wins on three of the loops. */
+static int check_asic_status(struct echoaudio *chip)
+{
+       u32 asic_status;
+       int goodcnt, i;
+
+       chip->asic_loaded = FALSE;
+       for (i = goodcnt = 0; i < 5; i++) {
+               send_vector(chip, DSP_VC_TEST_ASIC);
+
+               /* The DSP will return a value to indicate whether or not
+                  the ASIC is currently loaded */
+               if (read_dsp(chip, &asic_status) < 0) {
+                       DE_ACT(("check_asic_status: failed on read_dsp\n"));
+                       return -EIO;
+               }
+
+               if (asic_status == ASIC_ALREADY_LOADED) {
+                       if (++goodcnt == 3) {
+                               chip->asic_loaded = TRUE;
+                               return 0;
+                       }
+               }
+       }
+       return -EIO;
+}
+
+
+
+/* Layla20 has an ASIC in the external box */
+static int load_asic(struct echoaudio *chip)
+{
+       int err;
+
+       if (chip->asic_loaded)
+               return 0;
+
+       err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC,
+                               &card_fw[FW_LAYLA20_ASIC]);
+       if (err < 0)
+               return err;
+
+       /* Check if ASIC is alive and well. */
+       return check_asic_status(chip);
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       snd_assert(rate >= 8000 && rate <= 50000, return -EINVAL);
+
+       /* Only set the clock for internal mode. Do not return failure,
+          simply treat it as a non-event. */
+       if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
+               DE_ACT(("set_sample_rate: Cannot set sample rate - "
+                       "clock not set to CLK_CLOCKININTERNAL\n"));
+               chip->comm_page->sample_rate = cpu_to_le32(rate);
+               chip->sample_rate = rate;
+               return 0;
+       }
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       DE_ACT(("set_sample_rate(%d)\n", rate));
+       chip->sample_rate = rate;
+       chip->comm_page->sample_rate = cpu_to_le32(rate);
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE);
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock_source)
+{
+       u16 clock;
+       u32 rate;
+
+       DE_ACT(("set_input_clock:\n"));
+       rate = 0;
+       switch (clock_source) {
+       case ECHO_CLOCK_INTERNAL:
+               DE_ACT(("Set Layla20 clock to INTERNAL\n"));
+               rate = chip->sample_rate;
+               clock = LAYLA20_CLOCK_INTERNAL;
+               break;
+       case ECHO_CLOCK_SPDIF:
+               DE_ACT(("Set Layla20 clock to SPDIF\n"));
+               clock = LAYLA20_CLOCK_SPDIF;
+               break;
+       case ECHO_CLOCK_WORD:
+               DE_ACT(("Set Layla20 clock to WORD\n"));
+               clock = LAYLA20_CLOCK_WORD;
+               break;
+       case ECHO_CLOCK_SUPER:
+               DE_ACT(("Set Layla20 clock to SUPER\n"));
+               clock = LAYLA20_CLOCK_SUPER;
+               break;
+       default:
+               DE_ACT(("Input clock 0x%x not supported for Layla24\n",
+                       clock_source));
+               return -EINVAL;
+       }
+       chip->input_clock = clock_source;
+
+       chip->comm_page->input_clock = cpu_to_le16(clock);
+       clear_handshake(chip);
+       send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+
+       if (rate)
+               set_sample_rate(chip, rate);
+
+       return 0;
+}
+
+
+
+static int set_output_clock(struct echoaudio *chip, u16 clock)
+{
+       DE_ACT(("set_output_clock: %d\n", clock));
+       switch (clock) {
+       case ECHO_CLOCK_SUPER:
+               clock = LAYLA20_OUTPUT_CLOCK_SUPER;
+               break;
+       case ECHO_CLOCK_WORD:
+               clock = LAYLA20_OUTPUT_CLOCK_WORD;
+               break;
+       default:
+               DE_ACT(("set_output_clock wrong clock\n"));
+               return -EINVAL;
+       }
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->comm_page->output_clock = cpu_to_le16(clock);
+       chip->output_clock = clock;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+}
+
+
+
+/* Set input bus gain (one unit is 0.5dB !) */
+static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
+{
+       snd_assert(input < num_busses_in(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->input_gain[input] = gain;
+       gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
+       chip->comm_page->line_in_level[input] = gain;
+       return 0;
+}
+
+
+
+/* Tell the DSP to reread the flags from the comm page */
+static int update_flags(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_FLAGS);
+}
+
+
+
+static int set_professional_spdif(struct echoaudio *chip, char prof)
+{
+       DE_ACT(("set_professional_spdif %d\n", prof));
+       if (prof)
+               chip->comm_page->flags |=
+                       __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+       else
+               chip->comm_page->flags &=
+                       ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+       chip->professional_spdif = prof;
+       return update_flags(chip);
+}
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
new file mode 100644 (file)
index 0000000..d4581fd
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHO24_FAMILY
+#define ECHOCARD_LAYLA24
+#define ECHOCARD_NAME "Layla24"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_ASIC
+#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
+#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_ADAT      6
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+#define ECHOCARD_HAS_MIDI
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 8 */
+#define PX_ANALOG_IN   16      /* 8 */
+#define PX_DIGITAL_IN  24      /* 8 */
+#define PX_NUM         32
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 8 */
+#define BX_DIGITAL_OUT 8       /* 8 */
+#define BX_ANALOG_IN   16      /* 8 */
+#define BX_DIGITAL_IN  24      /* 8 */
+#define BX_NUM         32
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER          0
+#define FW_LAYLA24_DSP         1
+#define FW_LAYLA24_1_ASIC      2
+#define FW_LAYLA24_2A_ASIC     3
+#define FW_LAYLA24_2S_ASIC     4
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "layla24_dsp.fw"},
+       {0, "layla24_1_asic.fw"},
+       {0, "layla24_2A_asic.fw"},
+       {0, "layla24_2S_asic.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0},      /* DSP 56361 Layla24 rev.0 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_8000_96000,
+       .rate_min = 8000,
+       .rate_max = 100000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+
+#include "layla24_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio_gml.c"
+#include "echoaudio.c"
+#include "midi.c"
diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c
new file mode 100644 (file)
index 0000000..7ec5b63
--- /dev/null
@@ -0,0 +1,394 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int write_control_reg(struct echoaudio *chip, u32 value, char force);
+static int set_input_clock(struct echoaudio *chip, u16 clock);
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int set_digital_mode(struct echoaudio *chip, u8 mode);
+static int load_asic_generic(struct echoaudio *chip, u32 cmd,
+                            const struct firmware *asic);
+static int check_asic_status(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Layla24\n"));
+       snd_assert((subdevice_id & 0xfff0) == LAYLA24, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->has_midi = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_LAYLA24_DSP];
+       chip->input_clock_types =
+               ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
+               ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT;
+       chip->digital_modes =
+               ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
+               ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
+               ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
+       chip->digital_mode =            DIGITAL_MODE_SPDIF_RCA;
+       chip->professional_spdif = FALSE;
+       chip->digital_in_automute = TRUE;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA);
+       snd_assert(err >= 0, return err);
+       err = set_professional_spdif(chip, TRUE);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
+               clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
+               clock_bits |= ECHO_CLOCK_BIT_ADAT;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD)
+               clock_bits |= ECHO_CLOCK_BIT_WORD;
+
+       return clock_bits;
+}
+
+
+
+/* Layla24 has an ASIC on the PCI card and another ASIC in the external box;
+both need to be loaded. */
+static int load_asic(struct echoaudio *chip)
+{
+       int err;
+
+       if (chip->asic_loaded)
+               return 1;
+
+       DE_INIT(("load_asic\n"));
+
+       /* Give the DSP a few milliseconds to settle down */
+       mdelay(10);
+
+       /* Load the ASIC for the PCI card */
+       err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC,
+                               &card_fw[FW_LAYLA24_1_ASIC]);
+       if (err < 0)
+               return err;
+
+       chip->asic_code = &card_fw[FW_LAYLA24_2S_ASIC];
+
+       /* Now give the new ASIC a little time to set up */
+       mdelay(10);
+
+       /* Do the external one */
+       err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
+                               &card_fw[FW_LAYLA24_2S_ASIC]);
+       if (err < 0)
+               return FALSE;
+
+       /* Now give the external ASIC a little time to set up */
+       mdelay(10);
+
+       /* See if it worked */
+       err = check_asic_status(chip);
+
+       /* Set up the control register if the load succeeded -
+          48 kHz, internal clock, S/PDIF RCA mode */
+       if (!err)
+               err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ,
+                                       TRUE);
+       
+       DE_INIT(("load_asic() done\n"));
+       return err;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg, clock, base_rate;
+
+       snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT,
+                  return -EINVAL);
+
+       /* Only set the clock for internal mode. */
+       if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
+               DE_ACT(("set_sample_rate: Cannot set sample rate - "
+                       "clock not set to CLK_CLOCKININTERNAL\n"));
+               /* Save the rate anyhow */
+               chip->comm_page->sample_rate = cpu_to_le32(rate);
+               chip->sample_rate = rate;
+               return 0;
+       }
+
+       /* Get the control register & clear the appropriate bits */
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
+
+       clock = 0;
+
+       switch (rate) {
+       case 96000:
+               clock = GML_96KHZ;
+               break;
+       case 88200:
+               clock = GML_88KHZ;
+               break;
+       case 48000:
+               clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
+               break;
+       case 44100:
+               clock = GML_44KHZ;
+               /* Professional mode */
+               if (control_reg & GML_SPDIF_PRO_MODE)
+                       clock |= GML_SPDIF_SAMPLE_RATE0;
+               break;
+       case 32000:
+               clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
+                       GML_SPDIF_SAMPLE_RATE1;
+               break;
+       case 22050:
+               clock = GML_22KHZ;
+               break;
+       case 16000:
+               clock = GML_16KHZ;
+               break;
+       case 11025:
+               clock = GML_11KHZ;
+               break;
+       case 8000:
+               clock = GML_8KHZ;
+               break;
+       default:
+               /* If this is a non-standard rate, then the driver needs to
+               use Layla24's special "continuous frequency" mode */
+               clock = LAYLA24_CONTINUOUS_CLOCK;
+               if (rate > 50000) {
+                       base_rate = rate >> 1;
+                       control_reg |= GML_DOUBLE_SPEED_MODE;
+               } else {
+                       base_rate = rate;
+               }
+
+               if (base_rate < 25000)
+                       base_rate = 25000;
+
+               if (wait_handshake(chip))
+                       return -EIO;
+
+               chip->comm_page->sample_rate =
+                       cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2);
+
+               clear_handshake(chip);
+               send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG);
+       }
+
+       control_reg |= clock;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP ? */
+       chip->sample_rate = rate;
+       DE_ACT(("set_sample_rate: %d clock %d\n", rate, control_reg));
+
+       return write_control_reg(chip, control_reg, FALSE);
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       u32 control_reg, clocks_from_dsp;
+
+       /* Mask off the clock select bits */
+       control_reg = le32_to_cpu(chip->comm_page->control_register) &
+               GML_CLOCK_CLEAR_MASK;
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       /* Pick the new clock */
+       switch (clock) {
+       case ECHO_CLOCK_INTERNAL:
+               DE_ACT(("Set Layla24 clock to INTERNAL\n"));
+               chip->input_clock = ECHO_CLOCK_INTERNAL;
+               return set_sample_rate(chip, chip->sample_rate);
+       case ECHO_CLOCK_SPDIF:
+               if (chip->digital_mode == DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               control_reg |= GML_SPDIF_CLOCK;
+               /* Layla24 doesn't support 96KHz S/PDIF */
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               DE_ACT(("Set Layla24 clock to SPDIF\n"));
+               break;
+       case ECHO_CLOCK_WORD:
+               control_reg |= GML_WORD_CLOCK;
+               if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96)
+                       control_reg |= GML_DOUBLE_SPEED_MODE;
+               else
+                       control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               DE_ACT(("Set Layla24 clock to WORD\n"));
+               break;
+       case ECHO_CLOCK_ADAT:
+               if (chip->digital_mode != DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               control_reg |= GML_ADAT_CLOCK;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               DE_ACT(("Set Layla24 clock to ADAT\n"));
+               break;
+       default:
+               DE_ACT(("Input clock 0x%x not supported for Layla24\n", clock));
+               return -EINVAL;
+       }
+
+       chip->input_clock = clock;
+       return write_control_reg(chip, control_reg, TRUE);
+}
+
+
+
+/* Depending on what digital mode you want, Layla24 needs different ASICs
+loaded.  This function checks the ASIC needed for the new mode and sees
+if it matches the one already loaded. */
+static int switch_asic(struct echoaudio *chip, const struct firmware *asic)
+{
+       s8 *monitors;
+
+       /*  Check to see if this is already loaded */
+       if (asic != chip->asic_code) {
+               monitors = kmalloc(MONITOR_ARRAY_SIZE, GFP_KERNEL);
+               if (! monitors)
+                       return -ENOMEM;
+
+               memcpy(monitors, chip->comm_page->monitors, MONITOR_ARRAY_SIZE);
+               memset(chip->comm_page->monitors, ECHOGAIN_MUTED,
+                      MONITOR_ARRAY_SIZE);
+
+               /* Load the desired ASIC */
+               if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
+                                     asic) < 0) {
+                       memcpy(chip->comm_page->monitors, monitors,
+                              MONITOR_ARRAY_SIZE);
+                       kfree(monitors);
+                       return -EIO;
+               }
+               chip->asic_code = asic;
+               memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE);
+               kfree(monitors);
+       }
+
+       return 0;
+}
+
+
+
+static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
+{
+       u32 control_reg;
+       int err, incompatible_clock;
+       const struct firmware *asic;
+
+       /* Set clock to "internal" if it's not compatible with the new mode */
+       incompatible_clock = FALSE;
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+       case DIGITAL_MODE_SPDIF_RCA:
+               if (chip->input_clock == ECHO_CLOCK_ADAT)
+                       incompatible_clock = TRUE;
+               asic = &card_fw[FW_LAYLA24_2S_ASIC];
+               break;
+       case DIGITAL_MODE_ADAT:
+               if (chip->input_clock == ECHO_CLOCK_SPDIF)
+                       incompatible_clock = TRUE;
+               asic = &card_fw[FW_LAYLA24_2A_ASIC];
+               break;
+       default:
+               DE_ACT(("Digital mode not supported: %d\n", mode));
+               return -EINVAL;
+       }
+
+       if (incompatible_clock) {       /* Switch to 48KHz, internal */
+               chip->sample_rate = 48000;
+               spin_lock_irq(&chip->lock);
+               set_input_clock(chip, ECHO_CLOCK_INTERNAL);
+               spin_unlock_irq(&chip->lock);
+       }
+
+       /* switch_asic() can sleep */
+       if (switch_asic(chip, asic) < 0)
+               return -EIO;
+
+       spin_lock_irq(&chip->lock);
+
+       /* Tweak the control register */
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
+
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+               control_reg |= GML_SPDIF_OPTICAL_MODE;
+               break;
+       case DIGITAL_MODE_SPDIF_RCA:
+               /* GML_SPDIF_OPTICAL_MODE bit cleared */
+               break;
+       case DIGITAL_MODE_ADAT:
+               control_reg |= GML_ADAT_MODE;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       }
+
+       err = write_control_reg(chip, control_reg, TRUE);
+       spin_unlock_irq(&chip->lock);
+       if (err < 0)
+               return err;
+       chip->digital_mode = mode;
+
+       DE_ACT(("set_digital_mode to %d\n", mode));
+       return incompatible_clock;
+}
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
new file mode 100644 (file)
index 0000000..be40c64
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHO24_FAMILY
+#define ECHOCARD_MIA
+#define ECHOCARD_NAME "Mia"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_VMIXER
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_ADAT      FALSE
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+#define ECHOCARD_HAS_MIDI
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 8 */
+#define PX_DIGITAL_OUT 8       /* 0 */
+#define PX_ANALOG_IN   8       /* 2 */
+#define PX_DIGITAL_IN  10      /* 2 */
+#define PX_NUM         12
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 2 */
+#define BX_DIGITAL_OUT 2       /* 2 */
+#define BX_ANALOG_IN   4       /* 2 */
+#define BX_DIGITAL_IN  6       /* 2 */
+#define BX_NUM         8
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER  0
+#define FW_MIA_DSP     1
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "mia_dsp.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0},      /* DSP 56361 Mia rev.0 */
+       {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0},      /* DSP 56361 Mia rev.1 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_32000 |
+                       SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+
+#include "mia_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio.c"
+#include "midi.c"
diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c
new file mode 100644 (file)
index 0000000..891c705
--- /dev/null
@@ -0,0 +1,229 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock);
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int update_flags(struct echoaudio *chip);
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain);
+static int update_vmixer_level(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Mia\n"));
+       snd_assert((subdevice_id & 0xfff0) == MIA, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->dsp_code_to_load = &card_fw[FW_MIA_DSP];
+       /* Since this card has no ASIC, mark it as loaded so everything
+          works OK */
+       chip->asic_loaded = TRUE;
+       if ((subdevice_id & 0x0000f) == MIA_MIDI_REV)
+               chip->has_midi = TRUE;
+       chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
+               ECHO_CLOCK_BIT_SPDIF;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)))
+               return err;
+
+       /* Default routing of the virtual channels: vchannels 0-3 go to analog
+       outputs and vchannels 4-7 go to S/PDIF outputs */
+       set_vmixer_gain(chip, 0, 0, 0);
+       set_vmixer_gain(chip, 1, 1, 0);
+       set_vmixer_gain(chip, 0, 2, 0);
+       set_vmixer_gain(chip, 1, 3, 0);
+       set_vmixer_gain(chip, 2, 4, 0);
+       set_vmixer_gain(chip, 3, 5, 0);
+       set_vmixer_gain(chip, 2, 6, 0);
+       set_vmixer_gain(chip, 3, 7, 0);
+       err = update_vmixer_level(chip);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock
+          detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
+               clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+
+       return clock_bits;
+}
+
+
+
+/* The Mia has no ASIC. Just do nothing */
+static int load_asic(struct echoaudio *chip)
+{
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg;
+
+       switch (rate) {
+       case 96000:
+               control_reg = MIA_96000;
+               break;
+       case 88200:
+               control_reg = MIA_88200;
+               break;
+       case 48000:
+               control_reg = MIA_48000;
+               break;
+       case 44100:
+               control_reg = MIA_44100;
+               break;
+       case 32000:
+               control_reg = MIA_32000;
+               break;
+       default:
+               DE_ACT(("set_sample_rate: %d invalid!\n", rate));
+               return -EINVAL;
+       }
+
+       /* Override the clock setting if this Mia is set to S/PDIF clock */
+       if (chip->input_clock == ECHO_CLOCK_SPDIF)
+               control_reg |= MIA_SPDIF;
+
+       /* Set the control register if it has changed */
+       if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
+               if (wait_handshake(chip))
+                       return -EIO;
+
+               chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
+               chip->comm_page->control_register = cpu_to_le32(control_reg);
+               chip->sample_rate = rate;
+
+               clear_handshake(chip);
+               return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
+       }
+       return 0;
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       DE_ACT(("set_input_clock(%d)\n", clock));
+       snd_assert(clock == ECHO_CLOCK_INTERNAL || clock == ECHO_CLOCK_SPDIF,
+                  return -EINVAL);
+
+       chip->input_clock = clock;
+       return set_sample_rate(chip, chip->sample_rate);
+}
+
+
+
+/* This function routes the sound from a virtual channel to a real output */
+static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
+                          int gain)
+{
+       int index;
+
+       snd_assert(pipe < num_pipes_out(chip) &&
+                  output < num_busses_out(chip), return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       chip->vmixer_gain[output][pipe] = gain;
+       index = output * num_pipes_out(chip) + pipe;
+       chip->comm_page->vmixer[index] = gain;
+
+       DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
+       return 0;
+}
+
+
+
+/* Tell the DSP to read and update virtual mixer levels in comm page. */
+static int update_vmixer_level(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
+}
+
+
+
+/* Tell the DSP to reread the flags from the comm page */
+static int update_flags(struct echoaudio *chip)
+{
+       if (wait_handshake(chip))
+               return -EIO;
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_FLAGS);
+}
+
+
+
+static int set_professional_spdif(struct echoaudio *chip, char prof)
+{
+       DE_ACT(("set_professional_spdif %d\n", prof));
+       if (prof)
+               chip->comm_page->flags |=
+                       __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+       else
+               chip->comm_page->flags &=
+                       ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
+       chip->professional_spdif = prof;
+       return update_flags(chip);
+}
+
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
new file mode 100644 (file)
index 0000000..e31f0f1
--- /dev/null
@@ -0,0 +1,327 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+/******************************************************************************
+       MIDI lowlevel code
+******************************************************************************/
+
+/* Start and stop Midi input */
+static int enable_midi_input(struct echoaudio *chip, char enable)
+{
+       DE_MID(("enable_midi_input(%d)\n", enable));
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       if (enable) {
+               chip->mtc_state = MIDI_IN_STATE_NORMAL;
+               chip->comm_page->flags |=
+                       __constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT);
+       } else
+               chip->comm_page->flags &=
+                       ~__constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT);
+
+       clear_handshake(chip);
+       return send_vector(chip, DSP_VC_UPDATE_FLAGS);
+}
+
+
+
+/* Send a buffer full of MIDI data to the DSP
+Returns how many actually written or < 0 on error */
+static int write_midi(struct echoaudio *chip, u8 *data, int bytes)
+{
+       snd_assert(bytes > 0 && bytes < MIDI_OUT_BUFFER_SIZE, return -EINVAL);
+
+       if (wait_handshake(chip))
+               return -EIO;
+
+       /* HF4 indicates that it is safe to write MIDI output data */
+       if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4))
+               return 0;
+
+       chip->comm_page->midi_output[0] = bytes;
+       memcpy(&chip->comm_page->midi_output[1], data, bytes);
+       chip->comm_page->midi_out_free_count = 0;
+       clear_handshake(chip);
+       send_vector(chip, DSP_VC_MIDI_WRITE);
+       DE_MID(("write_midi: %d\n", bytes));
+       return bytes;
+}
+
+
+
+/* Run the state machine for MIDI input data
+MIDI time code sync isn't supported by this code right now, but you still need
+this state machine to parse the incoming MIDI data stream.  Every time the DSP
+sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data
+stream. The DSP sample position is represented as a 32 bit unsigned value,
+with the high 16 bits first, followed by the low 16 bits. Since these aren't
+real MIDI bytes, the following logic is needed to skip them. */
+static inline int mtc_process_data(struct echoaudio *chip, short midi_byte)
+{
+       switch (chip->mtc_state) {
+       case MIDI_IN_STATE_NORMAL:
+               if (midi_byte == 0xF1)
+                       chip->mtc_state = MIDI_IN_STATE_TS_HIGH;
+               break;
+       case MIDI_IN_STATE_TS_HIGH:
+               chip->mtc_state = MIDI_IN_STATE_TS_LOW;
+               return MIDI_IN_SKIP_DATA;
+               break;
+       case MIDI_IN_STATE_TS_LOW:
+               chip->mtc_state = MIDI_IN_STATE_F1_DATA;
+               return MIDI_IN_SKIP_DATA;
+               break;
+       case MIDI_IN_STATE_F1_DATA:
+               chip->mtc_state = MIDI_IN_STATE_NORMAL;
+               break;
+       }
+       return 0;
+}
+
+
+
+/* This function is called from the IRQ handler and it reads the midi data
+from the DSP's buffer.  It returns the number of bytes received. */
+static int midi_service_irq(struct echoaudio *chip)
+{
+       short int count, midi_byte, i, received;
+
+       /* The count is at index 0, followed by actual data */
+       count = le16_to_cpu(chip->comm_page->midi_input[0]);
+
+       snd_assert(count < MIDI_IN_BUFFER_SIZE, return 0);
+
+       /* Get the MIDI data from the comm page */
+       i = 1;
+       received = 0;
+       for (i = 1; i <= count; i++) {
+               /* Get the MIDI byte */
+               midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]);
+
+               /* Parse the incoming MIDI stream. The incoming MIDI data
+               consists of MIDI bytes and timestamps for the MIDI time code
+               0xF1 bytes. mtc_process_data() is a little state machine that
+               parses the stream. If you get MIDI_IN_SKIP_DATA back, then
+               this is a timestamp byte, not a MIDI byte, so don't store it
+               in the MIDI input buffer. */
+               if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA)
+                       continue;
+
+               chip->midi_buffer[received++] = (u8)midi_byte;
+       }
+
+       return received;
+}
+
+
+
+
+/******************************************************************************
+       MIDI interface
+******************************************************************************/
+
+static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream)
+{
+       struct echoaudio *chip = substream->rmidi->private_data;
+
+       chip->midi_in = substream;
+       DE_MID(("rawmidi_iopen\n"));
+       return 0;
+}
+
+
+
+static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream,
+                                       int up)
+{
+       struct echoaudio *chip = substream->rmidi->private_data;
+
+       if (up != chip->midi_input_enabled) {
+               spin_lock_irq(&chip->lock);
+               enable_midi_input(chip, up);
+               spin_unlock_irq(&chip->lock);
+               chip->midi_input_enabled = up;
+       }
+}
+
+
+
+static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream)
+{
+       struct echoaudio *chip = substream->rmidi->private_data;
+
+       chip->midi_in = NULL;
+       DE_MID(("rawmidi_iclose\n"));
+       return 0;
+}
+
+
+
+static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream)
+{
+       struct echoaudio *chip = substream->rmidi->private_data;
+
+       chip->tinuse = 0;
+       chip->midi_full = 0;
+       chip->midi_out = substream;
+       DE_MID(("rawmidi_oopen\n"));
+       return 0;
+}
+
+
+
+static void snd_echo_midi_output_write(unsigned long data)
+{
+       struct echoaudio *chip = (struct echoaudio *)data;
+       unsigned long flags;
+       int bytes, sent, time;
+       unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1];
+
+       DE_MID(("snd_echo_midi_output_write\n"));
+       /* No interrupts are involved: we have to check at regular intervals
+       if the card's output buffer has room for new data. */
+       sent = bytes = 0;
+       spin_lock_irqsave(&chip->lock, flags);
+       chip->midi_full = 0;
+       if (chip->midi_out && !snd_rawmidi_transmit_empty(chip->midi_out)) {
+               bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
+                                                 MIDI_OUT_BUFFER_SIZE - 1);
+               DE_MID(("Try to send %d bytes...\n", bytes));
+               sent = write_midi(chip, buf, bytes);
+               if (sent < 0) {
+                       snd_printk(KERN_ERR "write_midi() error %d\n", sent);
+                       /* retry later */
+                       sent = 9000;
+                       chip->midi_full = 1;
+               } else if (sent > 0) {
+                       DE_MID(("%d bytes sent\n", sent));
+                       snd_rawmidi_transmit_ack(chip->midi_out, sent);
+               } else {
+                       /* Buffer is full. DSP's internal buffer is 64 (128 ?)
+                       bytes long. Let's wait until half of them are sent */
+                       DE_MID(("Full\n"));
+                       sent = 32;
+                       chip->midi_full = 1;
+               }
+       }
+
+       /* We restart the timer only if there is some data left to send */
+       if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) {
+               /* The timer will expire slightly after the data has been
+                  sent */
+               time = (sent << 3) / 25 + 1;    /* 8/25=0.32ms to send a byte */
+               mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000);
+               DE_MID(("Timer armed(%d)\n", ((time * HZ + 999) / 1000)));
+       }
+       spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+
+
+static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream,
+                                        int up)
+{
+       struct echoaudio *chip = substream->rmidi->private_data;
+
+       DE_MID(("snd_echo_midi_output_trigger(%d)\n", up));
+       spin_lock_irq(&chip->lock);
+       if (up) {
+               if (!chip->tinuse) {
+                       init_timer(&chip->timer);
+                       chip->timer.function = snd_echo_midi_output_write;
+                       chip->timer.data = (unsigned long)chip;
+                       chip->tinuse = 1;
+               }
+       } else {
+               if (chip->tinuse) {
+                       del_timer(&chip->timer);
+                       chip->tinuse = 0;
+                       DE_MID(("Timer removed\n"));
+               }
+       }
+       spin_unlock_irq(&chip->lock);
+
+       if (up && !chip->midi_full)
+               snd_echo_midi_output_write((unsigned long)chip);
+}
+
+
+
+static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream)
+{
+       struct echoaudio *chip = substream->rmidi->private_data;
+
+       chip->midi_out = NULL;
+       DE_MID(("rawmidi_oclose\n"));
+       return 0;
+}
+
+
+
+static struct snd_rawmidi_ops snd_echo_midi_input = {
+       .open = snd_echo_midi_input_open,
+       .close = snd_echo_midi_input_close,
+       .trigger = snd_echo_midi_input_trigger,
+};
+
+static struct snd_rawmidi_ops snd_echo_midi_output = {
+       .open = snd_echo_midi_output_open,
+       .close = snd_echo_midi_output_close,
+       .trigger = snd_echo_midi_output_trigger,
+};
+
+
+
+/* <--snd_echo_probe() */
+static int __devinit snd_echo_midi_create(struct snd_card *card,
+                                         struct echoaudio *chip)
+{
+       int err;
+
+       if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1,
+                                  &chip->rmidi)) < 0)
+               return err;
+
+       strcpy(chip->rmidi->name, card->shortname);
+       chip->rmidi->private_data = chip;
+
+       snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+                           &snd_echo_midi_input);
+       snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+                           &snd_echo_midi_output);
+
+       chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
+               SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
+       DE_INIT(("MIDI ok\n"));
+       return 0;
+}
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
new file mode 100644 (file)
index 0000000..5dc512a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  ALSA driver for Echoaudio soundcards.
+ *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
+ *
+ *  This program is free software; 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; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ECHO24_FAMILY
+#define ECHOCARD_MONA
+#define ECHOCARD_NAME "Mona"
+#define ECHOCARD_HAS_MONITOR
+#define ECHOCARD_HAS_ASIC
+#define ECHOCARD_HAS_SUPER_INTERLEAVE
+#define ECHOCARD_HAS_DIGITAL_IO
+#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
+#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+#define ECHOCARD_HAS_EXTERNAL_CLOCK
+#define ECHOCARD_HAS_ADAT      6
+#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
+
+/* Pipe indexes */
+#define PX_ANALOG_OUT  0       /* 6 */
+#define PX_DIGITAL_OUT 6       /* 8 */
+#define PX_ANALOG_IN   14      /* 4 */
+#define PX_DIGITAL_IN  18      /* 8 */
+#define PX_NUM         26
+
+/* Bus indexes */
+#define BX_ANALOG_OUT  0       /* 6 */
+#define BX_DIGITAL_OUT 6       /* 8 */
+#define BX_ANALOG_IN   14      /* 4 */
+#define BX_DIGITAL_IN  18      /* 8 */
+#define BX_NUM         26
+
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "echoaudio.h"
+
+#define FW_361_LOADER          0
+#define FW_MONA_301_DSP                1
+#define FW_MONA_361_DSP                2
+#define FW_MONA_301_1_ASIC48   3
+#define FW_MONA_301_1_ASIC96   4
+#define FW_MONA_361_1_ASIC48   5
+#define FW_MONA_361_1_ASIC96   6
+#define FW_MONA_2_ASIC         7
+
+static const struct firmware card_fw[] = {
+       {0, "loader_dsp.fw"},
+       {0, "mona_301_dsp.fw"},
+       {0, "mona_361_dsp.fw"},
+       {0, "mona_301_1_asic_48.fw"},
+       {0, "mona_301_1_asic_96.fw"},
+       {0, "mona_361_1_asic_48.fw"},
+       {0, "mona_361_1_asic_96.fw"},
+       {0, "mona_2_asic.fw"}
+};
+
+static struct pci_device_id snd_echo_ids[] = {
+       {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0},      /* DSP 56301 Mona rev.0 */
+       {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0},      /* DSP 56301 Mona rev.1 */
+       {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0},      /* DSP 56301 Mona rev.2 */
+       {0x1057, 0x3410, 0xECC0, 0x0070, 0, 0, 0},      /* DSP 56361 Mona rev.0 */
+       {0x1057, 0x3410, 0xECC0, 0x0071, 0, 0, 0},      /* DSP 56361 Mona rev.1 */
+       {0x1057, 0x3410, 0xECC0, 0x0072, 0, 0, 0},      /* DSP 56361 Mona rev.2 */
+       {0,}
+};
+
+static struct snd_pcm_hardware pcm_hardware_skel = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID |
+               SNDRV_PCM_INFO_PAUSE |
+               SNDRV_PCM_INFO_SYNC_START,
+       .formats =      SNDRV_PCM_FMTBIT_U8 |
+                       SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S24_3LE |
+                       SNDRV_PCM_FMTBIT_S32_LE |
+                       SNDRV_PCM_FMTBIT_S32_BE,
+       .rates =        SNDRV_PCM_RATE_8000_48000 |
+                       SNDRV_PCM_RATE_88200 |
+                       SNDRV_PCM_RATE_96000,
+       .rate_min = 8000,
+       .rate_max = 96000,
+       .channels_min = 1,
+       .channels_max = 8,
+       .buffer_bytes_max = 262144,
+       .period_bytes_min = 32,
+       .period_bytes_max = 131072,
+       .periods_min = 2,
+       .periods_max = 220,
+       /* One page (4k) contains 512 instructions. I don't know if the hw
+       supports lists longer than this. In this case periods_max=220 is a
+       safe limit to make sure the list never exceeds 512 instructions. */
+};
+
+
+#include "mona_dsp.c"
+#include "echoaudio_dsp.c"
+#include "echoaudio_gml.c"
+#include "echoaudio.c"
diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c
new file mode 100644 (file)
index 0000000..c0b4bf0
--- /dev/null
@@ -0,0 +1,428 @@
+/****************************************************************************
+
+   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
+   All rights reserved
+   www.echoaudio.com
+
+   This file is part of Echo Digital Audio's generic driver library.
+
+   Echo Digital Audio's generic driver library is free software;
+   you can redistribute it and/or modify it under the terms of
+   the GNU General Public License 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.
+
+   *************************************************************************
+
+ Translation from C++ and adaptation for use in ALSA-Driver
+ were made by Giuliano Pochini <pochini@shiny.it>
+
+****************************************************************************/
+
+
+static int write_control_reg(struct echoaudio *chip, u32 value, char force);
+static int set_input_clock(struct echoaudio *chip, u16 clock);
+static int set_professional_spdif(struct echoaudio *chip, char prof);
+static int set_digital_mode(struct echoaudio *chip, u8 mode);
+static int load_asic_generic(struct echoaudio *chip, u32 cmd,
+                            const struct firmware *asic);
+static int check_asic_status(struct echoaudio *chip);
+
+
+static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
+{
+       int err;
+
+       DE_INIT(("init_hw() - Mona\n"));
+       snd_assert((subdevice_id & 0xfff0) == MONA, return -ENODEV);
+
+       if ((err = init_dsp_comm_page(chip))) {
+               DE_INIT(("init_hw - could not initialize DSP comm page\n"));
+               return err;
+       }
+
+       chip->device_id = device_id;
+       chip->subdevice_id = subdevice_id;
+       chip->bad_board = TRUE;
+       chip->input_clock_types =
+               ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
+               ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT;
+       chip->digital_modes =
+               ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
+               ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
+               ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
+
+       /* Mona comes in both '301 and '361 flavors */
+       if (chip->device_id == DEVICE_ID_56361)
+               chip->dsp_code_to_load = &card_fw[FW_MONA_361_DSP];
+       else
+               chip->dsp_code_to_load = &card_fw[FW_MONA_301_DSP];
+
+       chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
+       chip->professional_spdif = FALSE;
+       chip->digital_in_automute = TRUE;
+
+       if ((err = load_firmware(chip)) < 0)
+               return err;
+       chip->bad_board = FALSE;
+
+       if ((err = init_line_levels(chip)) < 0)
+               return err;
+
+       err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA);
+       snd_assert(err >= 0, return err);
+       err = set_professional_spdif(chip, TRUE);
+
+       DE_INIT(("init_hw done\n"));
+       return err;
+}
+
+
+
+static u32 detect_input_clocks(const struct echoaudio *chip)
+{
+       u32 clocks_from_dsp, clock_bits;
+
+       /* Map the DSP clock detect bits to the generic driver clock
+          detect bits */
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       clock_bits = ECHO_CLOCK_BIT_INTERNAL;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
+               clock_bits |= ECHO_CLOCK_BIT_SPDIF;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
+               clock_bits |= ECHO_CLOCK_BIT_ADAT;
+
+       if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD)
+               clock_bits |= ECHO_CLOCK_BIT_WORD;
+
+       return clock_bits;
+}
+
+
+
+/* Mona has an ASIC on the PCI card and another ASIC in the external box; 
+both need to be loaded. */
+static int load_asic(struct echoaudio *chip)
+{
+       u32 control_reg;
+       int err;
+       const struct firmware *asic;
+
+       if (chip->asic_loaded)
+               return 0;
+
+       mdelay(10);
+
+       if (chip->device_id == DEVICE_ID_56361)
+               asic = &card_fw[FW_MONA_361_1_ASIC48];
+       else
+               asic = &card_fw[FW_MONA_301_1_ASIC48];
+
+       err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, asic);
+       if (err < 0)
+               return err;
+
+       chip->asic_code = asic;
+       mdelay(10);
+
+       /* Do the external one */
+       err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_EXTERNAL_ASIC,
+                               &card_fw[FW_MONA_2_ASIC]);
+       if (err < 0)
+               return err;
+
+       mdelay(10);
+       err = check_asic_status(chip);
+
+       /* Set up the control register if the load succeeded -
+          48 kHz, internal clock, S/PDIF RCA mode */
+       if (!err) {
+               control_reg = GML_CONVERTER_ENABLE | GML_48KHZ;
+               err = write_control_reg(chip, control_reg, TRUE);
+       }
+
+       return err;
+}
+
+
+
+/* Depending on what digital mode you want, Mona needs different ASICs
+loaded.  This function checks the ASIC needed for the new mode and sees
+if it matches the one already loaded. */
+static int switch_asic(struct echoaudio *chip, char double_speed)
+{
+       const struct firmware *asic;
+       int err;
+
+       /* Check the clock detect bits to see if this is
+       a single-speed clock or a double-speed clock; load
+       a new ASIC if necessary. */
+       if (chip->device_id == DEVICE_ID_56361) {
+               if (double_speed)
+                       asic = &card_fw[FW_MONA_361_1_ASIC96];
+               else
+                       asic = &card_fw[FW_MONA_361_1_ASIC48];
+       } else {
+               if (double_speed)
+                       asic = &card_fw[FW_MONA_301_1_ASIC96];
+               else
+                       asic = &card_fw[FW_MONA_301_1_ASIC48];
+       }
+
+       if (asic != chip->asic_code) {
+               /* Load the desired ASIC */
+               err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC,
+                                       asic);
+               if (err < 0)
+                       return err;
+               chip->asic_code = asic;
+       }
+
+       return 0;
+}
+
+
+
+static int set_sample_rate(struct echoaudio *chip, u32 rate)
+{
+       u32 control_reg, clock;
+       const struct firmware *asic;
+       char force_write;
+
+       /* Only set the clock for internal mode. */
+       if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
+               DE_ACT(("set_sample_rate: Cannot set sample rate - "
+                       "clock not set to CLK_CLOCKININTERNAL\n"));
+               /* Save the rate anyhow */
+               chip->comm_page->sample_rate = cpu_to_le32(rate);
+               chip->sample_rate = rate;
+               return 0;
+       }
+
+       /* Now, check to see if the required ASIC is loaded */
+       if (rate >= 88200) {
+               if (chip->digital_mode == DIGITAL_MODE_ADAT)
+                       return -EINVAL;
+               if (chip->device_id == DEVICE_ID_56361)
+                       asic = &card_fw[FW_MONA_361_1_ASIC96];
+               else
+                       asic = &card_fw[FW_MONA_301_1_ASIC96];
+       } else {
+               if (chip->device_id == DEVICE_ID_56361)
+                       asic = &card_fw[FW_MONA_361_1_ASIC48];
+               else
+                       asic = &card_fw[FW_MONA_301_1_ASIC48];
+       }
+
+       force_write = 0;
+       if (asic != chip->asic_code) {
+               int err;
+               /* Load the desired ASIC (load_asic_generic() can sleep) */
+               spin_unlock_irq(&chip->lock);
+               err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC,
+                                       asic);
+               spin_lock_irq(&chip->lock);
+
+               if (err < 0)
+                       return err;
+               chip->asic_code = asic;
+               force_write = 1;
+       }
+
+       /* Compute the new control register value */
+       clock = 0;
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_CLOCK_CLEAR_MASK;
+       control_reg &= GML_SPDIF_RATE_CLEAR_MASK;
+
+       switch (rate) {
+       case 96000:
+               clock = GML_96KHZ;
+               break;
+       case 88200:
+               clock = GML_88KHZ;
+               break;
+       case 48000:
+               clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
+               break;
+       case 44100:
+               clock = GML_44KHZ;
+               /* Professional mode */
+               if (control_reg & GML_SPDIF_PRO_MODE)
+                       clock |= GML_SPDIF_SAMPLE_RATE0;
+               break;
+       case 32000:
+               clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
+                       GML_SPDIF_SAMPLE_RATE1;
+               break;
+       case 22050:
+               clock = GML_22KHZ;
+               break;
+       case 16000:
+               clock = GML_16KHZ;
+               break;
+       case 11025:
+               clock = GML_11KHZ;
+               break;
+       case 8000:
+               clock = GML_8KHZ;
+               break;
+       default:
+               DE_ACT(("set_sample_rate: %d invalid!\n", rate));
+               return -EINVAL;
+       }
+
+       control_reg |= clock;
+
+       chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP */
+       chip->sample_rate = rate;
+       DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock));
+
+       return write_control_reg(chip, control_reg, force_write);
+}
+
+
+
+static int set_input_clock(struct echoaudio *chip, u16 clock)
+{
+       u32 control_reg, clocks_from_dsp;
+       int err;
+
+       DE_ACT(("set_input_clock:\n"));
+
+       /* Prevent two simultaneous calls to switch_asic() */
+       if (atomic_read(&chip->opencount))
+               return -EAGAIN;
+
+       /* Mask off the clock select bits */
+       control_reg = le32_to_cpu(chip->comm_page->control_register) &
+               GML_CLOCK_CLEAR_MASK;
+       clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
+
+       switch (clock) {
+       case ECHO_CLOCK_INTERNAL:
+               DE_ACT(("Set Mona clock to INTERNAL\n"));
+               chip->input_clock = ECHO_CLOCK_INTERNAL;
+               return set_sample_rate(chip, chip->sample_rate);
+       case ECHO_CLOCK_SPDIF:
+               if (chip->digital_mode == DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               spin_unlock_irq(&chip->lock);
+               err = switch_asic(chip, clocks_from_dsp &
+                                 GML_CLOCK_DETECT_BIT_SPDIF96);
+               spin_lock_irq(&chip->lock);
+               if (err < 0)
+                       return err;
+               DE_ACT(("Set Mona clock to SPDIF\n"));
+               control_reg |= GML_SPDIF_CLOCK;
+               if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96)
+                       control_reg |= GML_DOUBLE_SPEED_MODE;
+               else
+                       control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_WORD:
+               DE_ACT(("Set Mona clock to WORD\n"));
+               spin_unlock_irq(&chip->lock);
+               err = switch_asic(chip, clocks_from_dsp &
+                                 GML_CLOCK_DETECT_BIT_WORD96);
+               spin_lock_irq(&chip->lock);
+               if (err < 0)
+                       return err;
+               control_reg |= GML_WORD_CLOCK;
+               if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96)
+                       control_reg |= GML_DOUBLE_SPEED_MODE;
+               else
+                       control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       case ECHO_CLOCK_ADAT:
+               DE_ACT(("Set Mona clock to ADAT\n"));
+               if (chip->digital_mode != DIGITAL_MODE_ADAT)
+                       return -EAGAIN;
+               control_reg |= GML_ADAT_CLOCK;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       default:
+               DE_ACT(("Input clock 0x%x not supported for Mona\n", clock));
+               return -EINVAL;
+       }
+
+       chip->input_clock = clock;
+       return write_control_reg(chip, control_reg, TRUE);
+}
+
+
+
+static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
+{
+       u32 control_reg;
+       int err, incompatible_clock;
+
+       /* Set clock to "internal" if it's not compatible with the new mode */
+       incompatible_clock = FALSE;
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+       case DIGITAL_MODE_SPDIF_RCA:
+               if (chip->input_clock == ECHO_CLOCK_ADAT)
+                       incompatible_clock = TRUE;
+               break;
+       case DIGITAL_MODE_ADAT:
+               if (chip->input_clock == ECHO_CLOCK_SPDIF)
+                       incompatible_clock = TRUE;
+               break;
+       default:
+               DE_ACT(("Digital mode not supported: %d\n", mode));
+               return -EINVAL;
+       }
+
+       spin_lock_irq(&chip->lock);
+
+       if (incompatible_clock) {       /* Switch to 48KHz, internal */
+               chip->sample_rate = 48000;
+               set_input_clock(chip, ECHO_CLOCK_INTERNAL);
+       }
+
+       /* Clear the current digital mode */
+       control_reg = le32_to_cpu(chip->comm_page->control_register);
+       control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
+
+       /* Tweak the control reg */
+       switch (mode) {
+       case DIGITAL_MODE_SPDIF_OPTICAL:
+               control_reg |= GML_SPDIF_OPTICAL_MODE;
+               break;
+       case DIGITAL_MODE_SPDIF_RCA:
+               /* GML_SPDIF_OPTICAL_MODE bit cleared */
+               break;
+       case DIGITAL_MODE_ADAT:
+               /* If the current ASIC is the 96KHz ASIC, switch the ASIC
+                  and set to 48 KHz */
+               if (chip->asic_code == &card_fw[FW_MONA_361_1_ASIC96] ||
+                   chip->asic_code == &card_fw[FW_MONA_301_1_ASIC96]) {
+                       set_sample_rate(chip, 48000);
+               }
+               control_reg |= GML_ADAT_MODE;
+               control_reg &= ~GML_DOUBLE_SPEED_MODE;
+               break;
+       }
+
+       err = write_control_reg(chip, control_reg, FALSE);
+       spin_unlock_irq(&chip->lock);
+       if (err < 0)
+               return err;
+       chip->digital_mode = mode;
+
+       DE_ACT(("set_digital_mode to %d\n", mode));
+       return incompatible_clock;
+}
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h
new file mode 100644 (file)
index 0000000..7ddb5be
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ *  Driver p17v chips
+ *  Version: 0.01
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU 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
+ *
+ */
+
+/******************************************************************************/
+/* Audigy2Value Tina (P17V) pointer-offset register set,
+ * accessed through the PTR20 and DATA24 registers  */
+/******************************************************************************/
+
+/* 00 - 07: Not used */
+#define P17V_PLAYBACK_FIFO_PTR 0x08    /* Current playback fifo pointer
+                                        * and number of sound samples in cache.
+                                        */  
+/* 09 - 12: Not used */
+#define P17V_CAPTURE_FIFO_PTR  0x13    /* Current capture fifo pointer
+                                        * and number of sound samples in cache.
+                                        */  
+/* 14 - 17: Not used */
+#define P17V_PB_CHN_SEL                0x18    /* P17v playback channel select */
+#define P17V_SE_SLOT_SEL_L     0x19    /* Sound Engine slot select low */
+#define P17V_SE_SLOT_SEL_H     0x1a    /* Sound Engine slot select high */
+/* 1b - 1f: Not used */
+/* 20 - 2f: Not used */
+/* 30 - 3b: Not used */
+#define P17V_SPI               0x3c    /* SPI interface register */
+#define P17V_I2C_ADDR          0x3d    /* I2C Address */
+#define P17V_I2C_0             0x3e    /* I2C Data */
+#define P17V_I2C_1             0x3f    /* I2C Data */
+
+#define P17V_START_AUDIO       0x40    /* Start Audio bit */
+/* 41 - 47: Reserved */
+#define P17V_START_CAPTURE     0x48    /* Start Capture bit */
+#define P17V_CAPTURE_FIFO_BASE 0x49    /* Record FIFO base address */
+#define P17V_CAPTURE_FIFO_SIZE 0x4a    /* Record FIFO buffer size */
+#define P17V_CAPTURE_FIFO_INDEX        0x4b    /* Record FIFO capture index */
+#define P17V_CAPTURE_VOL_H     0x4c    /* P17v capture volume control */
+#define P17V_CAPTURE_VOL_L     0x4d    /* P17v capture volume control */
+/* 4e - 4f: Not used */
+/* 50 - 5f: Not used */
+#define P17V_SRCSel            0x60    /* SRC48 and SRCMulti sample rate select
+                                        * and output select
+                                        */
+#define P17V_MIXER_AC97_10K1_VOL_L     0x61    /* 10K to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_10K1_VOL_H     0x62    /* 10K to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_P17V_VOL_L     0x63    /* P17V to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_P17V_VOL_H     0x64    /* P17V to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_SRP_REC_VOL_L  0x65    /* SRP Record to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_SRP_REC_VOL_H  0x66    /* SRP Record to Mixer_AC97 input volume control */
+/* 67 - 68: Reserved */
+#define P17V_MIXER_Spdif_10K1_VOL_L    0x69    /* 10K to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_10K1_VOL_H    0x6A    /* 10K to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_P17V_VOL_L    0x6B    /* P17V to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_P17V_VOL_H    0x6C    /* P17V to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D    /* SRP Record to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E    /* SRP Record to Mixer_Spdif input volume control */
+/* 6f - 70: Reserved */
+#define P17V_MIXER_I2S_10K1_VOL_L      0x71    /* 10K to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_10K1_VOL_H      0x72    /* 10K to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_P17V_VOL_L      0x73    /* P17V to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_P17V_VOL_H      0x74    /* P17V to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_SRP_REC_VOL_L   0x75    /* SRP Record to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_SRP_REC_VOL_H   0x76    /* SRP Record to Mixer_I2S input volume control */
+/* 77 - 78: Reserved */
+#define P17V_MIXER_AC97_ENABLE         0x79    /* Mixer AC97 input audio enable */
+#define P17V_MIXER_SPDIF_ENABLE                0x7A    /* Mixer SPDIF input audio enable */
+#define P17V_MIXER_I2S_ENABLE          0x7B    /* Mixer I2S input audio enable */
+#define P17V_AUDIO_OUT_ENABLE          0x7C    /* Audio out enable */
+#define P17V_MIXER_ATT                 0x7D    /* SRP Mixer Attenuation Select */
+#define P17V_SRP_RECORD_SRR            0x7E    /* SRP Record channel source Select */
+#define P17V_SOFT_RESET_SRP_MIXER      0x7F    /* SRP and mixer soft reset */
+
+#define P17V_AC97_OUT_MASTER_VOL_L     0x80    /* AC97 Output master volume control */
+#define P17V_AC97_OUT_MASTER_VOL_H     0x81    /* AC97 Output master volume control */
+#define P17V_SPDIF_OUT_MASTER_VOL_L    0x82    /* SPDIF Output master volume control */
+#define P17V_SPDIF_OUT_MASTER_VOL_H    0x83    /* SPDIF Output master volume control */
+#define P17V_I2S_OUT_MASTER_VOL_L      0x84    /* I2S Output master volume control */
+#define P17V_I2S_OUT_MASTER_VOL_H      0x85    /* I2S Output master volume control */
+/* 86 - 87: Not used */
+#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE    0x88    /* I2S out mono channel swap
+                                                        * and phase inverse */
+#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE  0x89    /* SPDIF out mono channel swap
+                                                        * and phase inverse */
+/* 8A: Not used */
+#define P17V_SRP_P17V_ESR              0x8B    /* SRP_P17V estimated sample rate and rate lock */
+#define P17V_SRP_REC_ESR               0x8C    /* SRP_REC estimated sample rate and rate lock */
+#define P17V_SRP_BYPASS                        0x8D    /* srps channel bypass and srps bypass */
+/* 8E - 92: Not used */
+#define P17V_I2S_SRC_SEL               0x93    /* I2SIN mode sel */
+
+
+
+
+
+
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
new file mode 100644 (file)
index 0000000..a27440f
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for ATI HDMI codecs
+ *
+ * Copyright (c) 2006 ATI Technologies Inc.
+ *
+ *
+ *  This driver is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+struct atihdmi_spec {
+       struct hda_multi_out multiout;
+
+       struct hda_pcm pcm_rec;
+};
+
+static struct hda_verb atihdmi_basic_init[] = {
+       /* enable digital output on pin widget */
+       { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       {} /* terminator */
+};
+
+/*
+ * Controls
+ */
+static int atihdmi_build_controls(struct hda_codec *codec)
+{
+       struct atihdmi_spec *spec = codec->spec;
+       int err;
+
+       err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int atihdmi_init(struct hda_codec *codec)
+{
+       snd_hda_sequence_write(codec, atihdmi_basic_init);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int atihdmi_resume(struct hda_codec *codec)
+{
+       atihdmi_init(codec);
+       snd_hda_resume_spdif_out(codec);
+
+       return 0;
+}
+#endif
+
+/*
+ * Digital out
+ */
+static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                    struct hda_codec *codec,
+                                    struct snd_pcm_substream *substream)
+{
+       struct atihdmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+                                     struct hda_codec *codec,
+                                     struct snd_pcm_substream *substream)
+{
+       struct atihdmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = 0x2, /* NID to query formats and rates and setup streams */
+       .ops = {
+               .open = atihdmi_dig_playback_pcm_open,
+               .close = atihdmi_dig_playback_pcm_close
+       },
+};
+
+static int atihdmi_build_pcms(struct hda_codec *codec)
+{
+       struct atihdmi_spec *spec = codec->spec;
+       struct hda_pcm *info = &spec->pcm_rec;
+
+       codec->num_pcms = 1;
+       codec->pcm_info = info;
+
+       info->name = "ATI HDMI";
+       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
+
+       return 0;
+}
+
+static void atihdmi_free(struct hda_codec *codec)
+{
+       kfree(codec->spec);
+}
+
+static struct hda_codec_ops atihdmi_patch_ops = {
+       .build_controls = atihdmi_build_controls,
+       .build_pcms = atihdmi_build_pcms,
+       .init = atihdmi_init,
+       .free = atihdmi_free,
+#ifdef CONFIG_PM
+       .resume = atihdmi_resume,
+#endif
+};
+
+static int patch_atihdmi(struct hda_codec *codec)
+{
+       struct atihdmi_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+
+       spec->multiout.num_dacs = 0;      /* no analog */
+       spec->multiout.max_channels = 2;
+       spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital,
+                                          * seems to be unused in pure-digital
+                                          * case. */
+
+       codec->patch_ops = atihdmi_patch_ops;
+
+       return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_atihdmi[] = {
+       { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
+       {} /* terminator */
+};